# Screen a vendor file of IBANs in bulk, up to 500 per call > Bulk IBAN sanctions screening before a payout or an onboarding run: up to 500 counterparty IBANs cleared for sanctioned banks and jurisdiction risk in one request, against a single dated snapshot. Published 2026-07-11 · Updated 2026-08-15 · HTML version: https://invoket.com/blog/screen-a-vendor-file-of-ibans-in-one-settlement --- KYB is list-shaped. An agent onboarding a supplier file, preparing a payroll run, or re-clearing an existing counterparty book is never asking about *one* IBAN — it is asking about hundreds. One paid call — [`POST /iban/screen/batch`](/docs/api/iban-screen-batch) — screens up to **500 IBANs** for sanctioned banks/BICs (OFAC / EU / UN) and jurisdiction risk (FATF black/grey, embargoes, EU-AML) in a single request, settled as **one x402 payment for the whole batch** and answered from a single, dated snapshot of the lists. ## The problem: counterparty screening comes in files, not questions The single-IBAN gate is covered in [Sanctions-screen a beneficiary IBAN before an agent pays it](/blog/screen-an-iban-before-an-agent-pays): before disbursing to one beneficiary, clear its bank and jurisdiction. But the inputs that actually reach a compliance-minded agent are lists — a CSV of vendor bank details, the beneficiary column of a payment file, the full book of counterparties a policy says must be re-checked. Looping [`GET /iban/screen`](/docs/api/iban-screen) over 500 rows means 500 HTTP round-trips, 500 `402` challenges and 500 settlements — a per-row toll where the workflow needs a single gate before the run. There is a second, less obvious problem: looping takes time, and the lists move underneath the loop. [OFAC publishes changes to its sanctions lists](https://ofac.treasury.gov/recent-actions/sanctions-list-updates) continuously, on no fixed schedule; the FATF revises its high-risk and monitored jurisdictions at each plenary — the [June 2026 plenary](https://www.fatf-gafi.org/en/publications/High-risk-and-other-monitored-jurisdictions/increased-monitoring-june-2026.html) added Iraq and Bosnia and Herzegovina to the grey list and removed Algeria and Namibia. A batch screened row by row over a long window is not guaranteed to have been screened against one consistent state of the world. ## The call: one JSON array, up to 500 IBANs `POST /iban/screen/batch` takes a JSON body with a single field: `ibans`, an array of 1 to 500 strings. Spaces and dashes are tolerated, case does not matter — paste the column as it came out of the file. ```http POST /iban/screen/batch Content-Type: application/json ``` ```json { "ibans": [ "DE89 3704 0044 0532 0130 00", "FR14 2004 1010 0505 0001 3M02 606", "not-an-iban" ] } ``` A malformed entry *inside* the array is not a request error. It is screened like in the single call and comes back as its own row (`valid: false`, `screening: null`, with an `issue` code) — one bad row never fails the file. ## What comes back: one verdict per row, one snapshot for the run The response is the standard `UnifiedResponse`: a `data` block with `count` and `results[]`, plus one `provenance` block. Three properties make it usable as a pre-run gate: - **Order is preserved.** `results[]` comes back in the same order as the input, and each element carries its own `iban` field, so the agent can re-pair verdicts with file rows without tracking indices. - **Each row is a full `ScreenResult`.** The same shape as the single call: resolved bank and BIC, whether the bank/BIC matched a sanctions list, the jurisdiction level, and the aggregated risk band — `prohibited`, `high`, `elevated`, `clear`, or `unknown`. The band semantics are documented in the [single-call reference](/docs/api/iban-screen). - **One `provenance` covers the whole batch.** Every IBAN in the call is screened against the same lists snapshot, and `provenance.freshness.as_of` dates it. That is the consistency the row-by-row loop cannot give: the whole run cleared against one stated state of the lists, with a date the agent can log next to the payment file. The agent's branch logic is then a fold over the rows: stop the run (or pull the row) on `prohibited`, escalate `high` and `elevated` to policy, and treat `unknown` as *not cleared* — the service refuses to assert `clear` without data behind it. In particular, `clear` requires `full` coverage: an unsignalled IBAN under `partial` coverage (FR / GB / PT) or `structure_only` coverage is `unknown`, never `clear`. Each row carries its own `coverage` field so the agent knows which verdicts are load-bearing. ## The x402 golden rule, applied to a file The agent pays for the *answer to its question*, and "12 of your 500 counterparties are risky, 3 rows are not valid IBANs" is a successful answer. A well-formed batch returns **200** whatever the mix of clean, risky and invalid rows. Only requests the service cannot answer leave the 200 range: a missing or malformed body, an empty array, or a batch over the 500 cap — and the cap is checked **before** any screening, so an oversized file is rejected without being billed. The batch is settled as one x402 payment and **priced per IBAN** by the gateway — the price scales with the number of rows, not the number of calls. As always, the authoritative figure and the accepted rails are served live by the [catalog](https://api.invoket.com/catalog), never hardcoded here. The payment loop itself is the same discover → `402` → pay → replay cycle as every Invoket endpoint; the [Quickstart](/docs/quickstart) walks it with runnable snippets and [For agents](/docs/for-agents) covers the discovery surfaces. ## A concrete shape: the pre-payment-run gate A payout agent holding a 400-row supplier file runs the gate like this: 1. **Extract** the IBAN column, as-is — no need to normalize spacing or case. 2. **Screen** the file: one `POST /iban/screen/batch`, one `402`, one signature, one replay. 3. **Fold** the verdicts: quarantine `prohibited` and invalid rows, route `high` / `elevated` / `unknown` to policy or human review, keep `clear` rows (with `full` coverage) in the run. 4. **Log** `provenance.freshness.as_of` with the run — the audit answer to "screened against which state of the lists?". 5. **Pay** the surviving rows through your own rails. Because the lists move — continuously on the sanctions side, plenary by plenary on the FATF side — the same call is also the **re-screening** primitive: a policy that re-clears the whole counterparty book after each [FATF list revision](https://www.fatf-gafi.org/en/countries/black-and-grey-lists.html) is one scheduled batch call, not a re-onboarding project. ## What this gate does *not* do The scope is exactly the single call's scope, stated in its [documentation](/docs/api/iban-screen#scope-and-limits): - It screens the **bank/BIC against sanctions lists** and the **jurisdiction risk** — it does **not** screen account-holder *names*. Payee-name checking is out of scope for this endpoint. - A `clear` row means no signal on the covered lists as of the snapshot date — it is not a legal compliance opinion and does not discharge your own AML obligations. - If what the file needs first is bank/BIC resolution rather than screening, [`POST /iban/resolve/batch`](/docs/api/iban-resolve-batch) is the companion batch for that job. Used for what it is — one settled call that clears a whole file against one dated snapshot of the sanctions and jurisdiction lists — the batch turns counterparty screening from a per-row toll into a gate an agent can afford to run before *every* payment run. For the request contract, field tables and error codes, see the [`POST /iban/screen/batch` documentation](/docs/api/iban-screen-batch).