> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fraudtraceai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /v1/verify/upi/batch — Batch UPI Verification

> Verify up to 100 UPI Virtual Payment Addresses in a single API request and receive a risk verdict for each, plus flagged and cleared summary counts.

The Batch Verify endpoint lets you submit up to 100 UPI Virtual Payment Addresses in a single API call and receive a risk verdict for each one. You get the same `FLAGGED` / `CLEARED` verdicts, confidence scores, and cluster details as the single-VPA endpoint, plus top-level summary counts — `flagged_count` and `cleared_count` — so you can triage results without counting rows yourself. This endpoint is designed for bulk onboarding checks, overnight screening runs, and any workflow where you need to evaluate a list of VPAs at once.

## Endpoint

**`POST https://api.fraudtraceai.com/v1/verify/upi/batch`**

***

## Request Headers

<ParamField header="Authorization" type="string" required>
  Your API key, passed as a Bearer token: `Authorization: Bearer YOUR_API_KEY`
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`.
</ParamField>

***

## Request Body

<ParamField body="upis" type="string[]" required>
  An array of UPI Virtual Payment Addresses to verify. Each item must be a valid VPA in the format `handle@provider` (e.g., `user@ybl`). You can send between 1 and 100 VPAs per request.
</ParamField>

```json theme={null}
{
  "upis": ["user1@ybl", "user2@okaxis", "merchant3@paytm"]
}
```

<Note>
  The maximum batch size is **100 VPAs per request**. If you need to screen more than 100 VPAs, split your list into chunks of 100 and send them as sequential requests. See the [batch lookup guide](/guides/batch-lookup) for a pagination pattern.
</Note>

***

## Request Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.fraudtraceai.com/v1/verify/upi/batch \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"upis": ["user1@ybl", "user2@okaxis", "merchant3@paytm"]}'
  ```

  ```python Python theme={null}
  import requests

  payload = {
      "upis": ["user1@ybl", "user2@okaxis", "merchant3@paytm"]
  }

  response = requests.post(
      "https://api.fraudtraceai.com/v1/verify/upi/batch",
      headers={
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json",
      },
      json=payload,
  )

  data = response.json()
  print(f"Flagged: {data['flagged_count']} / Total: {data['total']}")

  for result in data["results"]:
      print(result["upi"], result["status"], result.get("confidence"))
  ```
</CodeGroup>

***

## Response

The response body contains a `results` array — one entry per submitted VPA in the same order as your input — along with top-level summary counts.

```json theme={null}
{
  "results": [
    {
      "upi": "user1@ybl",
      "status": "FLAGGED",
      "confidence": 0.91,
      "risk_category": "mule",
      "cluster_id": "MC-2104",
      "cluster_size": 7,
      "evidence_count": 2
    },
    {
      "upi": "user2@okaxis",
      "status": "CLEARED",
      "confidence": null,
      "risk_category": null,
      "cluster_id": null,
      "cluster_size": 0,
      "evidence_count": 0
    },
    {
      "upi": "merchant3@paytm",
      "status": "FLAGGED",
      "confidence": 0.67,
      "risk_category": "gambling",
      "cluster_id": null,
      "cluster_size": 0,
      "evidence_count": 1
    }
  ],
  "total": 3,
  "flagged_count": 2,
  "cleared_count": 1
}
```

### Top-Level Response Fields

<ResponseField name="results" type="array">
  An ordered array of result objects, one per VPA submitted. The order matches your input array.

  <Expandable title="result object fields">
    <ResponseField name="results[].upi" type="string">
      The UPI VPA that was evaluated. Echoed back for easy correlation.
    </ResponseField>

    <ResponseField name="results[].status" type="string">
      The risk verdict. Either `FLAGGED` or `CLEARED`.
    </ResponseField>

    <ResponseField name="results[].confidence" type="float | null">
      Confidence score between `0.0` and `1.0`. Returns `null` when `status` is `CLEARED`.
    </ResponseField>

    <ResponseField name="results[].risk_category" type="string | null">
      The primary risk category: `mule`, `gambling`, `phishing`, `scam`, or `nbfc_impersonation`. Returns `null` when `status` is `CLEARED`.
    </ResponseField>

    <ResponseField name="results[].cluster_id" type="string | null">
      The cluster identifier if this VPA belongs to a known mule cluster (e.g., `MC-2104`). Returns `null` if not clustered or `CLEARED`.
    </ResponseField>

    <ResponseField name="results[].cluster_size" type="integer">
      Number of VPAs in the cluster. Returns `0` when `cluster_id` is `null`.
    </ResponseField>

    <ResponseField name="results[].evidence_count" type="integer">
      Total evidence items associated with this VPA. Returns `0` when `status` is `CLEARED`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="total" type="integer">
  The total number of VPAs evaluated in this batch. Matches the length of your input `upis` array.
</ResponseField>

<ResponseField name="flagged_count" type="integer">
  The number of VPAs in this batch that returned `status: FLAGGED`.
</ResponseField>

<ResponseField name="cleared_count" type="integer">
  The number of VPAs in this batch that returned `status: CLEARED`.
</ResponseField>

<Info>
  Batch results include key risk signals but **omit the full `sources` array** to keep response payloads compact. If you need the complete list of evidence sources for a specific VPA — for example, to satisfy a compliance audit trail — call [GET /v1/verify/upi](/api-reference/muletrace/verify-upi) for that VPA individually.
</Info>

***

## Error Codes

| HTTP Status                 | Meaning                                                                                                        |
| --------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`           | The request body is missing, malformed, contains an invalid VPA format, or the `upis` array exceeds 100 items. |
| `401 Unauthorized`          | The `Authorization` header is missing or the API key is invalid.                                               |
| `429 Too Many Requests`     | You have exceeded your rate limit. Check the `Retry-After` header and retry after the indicated delay.         |
| `500 Internal Server Error` | An unexpected error occurred on the FraudTrace side. Retry with exponential back-off.                          |

<Warning>
  Submitting more than 100 VPAs in a single request returns a `400` error. Chunk large lists into batches of 100 and iterate sequentially or with controlled concurrency to stay within rate limits.
</Warning>
