- authentication
- Secret API key as a bearer token
- billing
- Each identifier bills like a single lookup — 1 credit only when a register carried it, free for an unknown, malformed or unsupported identifier, free for a register that is not installed and free for a 7-day repeat — and the call stops cleanly where the balance ends.
Runs the single-identifier lookup for every item, in input order, under the exact single-lookup billing rules. Every answer is read from registers synced onto this server, so a full list makes no network call at all. data.results[] mirrors the single-identifier response per item and each item's meta carries credits_used and cache_hit.
An item is either a bare identifier string, which is read as a LEI because that is the only type needing no country, or an object with identifier, type and — for a company number — the country whose register it belongs to. Countries are only required per item, never for the list, because a list may mix registers.
The cap is 500, not the 1,000 the IP and phone batches take: those read indexes already held in memory, while each identifier here is a database read, and two when a LEI names a national-register counterpart. It is the same limit a monitored list of identifiers has, and a monitor run walks its list through this same lookup.
meta.found is the count this endpoint has that the other batches do not need. Business lookups bill only for an identifier a register actually carried, so a list of 500 unknown identifiers is processed in full and billed nothing, and processed on its own would imply a charge that was never made. credits_used is found less any identifier that was already looked up on this account inside the last seven days.
The list is walked in order and stops where the balance would run out: running out of credits mid-batch returns the paid partial results with meta.stopped_reason: "insufficient_credits" and processed lower than requested, never discarding billed work. Only a batch whose first lookup is refused answers the typed 402. A key with a daily credit cap stops the list the same way once the cap is spent, reporting meta.stopped_reason: "key_spend_cap"; a call that starts with the cap already spent answers 429 KEY_SPEND_CAP_REACHED and runs nothing.
A batch counts as one request against the rate limit. As with the single lookup, no registered address is stored or returned.
Every item carries index, its zero-based position in the list you sent, and input, the identifier exactly as you sent it — the answer carries the register's own spelling of it. A batch stopped early by stopped_reason answers only a prefix of the list, so those two are what line an answer up with the row it came from.
Request body
| field | type | description |
|---|---|---|
| identifiersrequired | string[] | 1 to 500 identifiers. An item is a LEI string, or an object carrying its own type and country. |
| identifiers[].identifier | string | At most 64 characters. |
| identifiers[].type | string | One of: lei, company_number. |
| identifiers[].country | string | null | Required when `type` is `company_number`. At most 2 characters. |
Example request
curl -X POST https://spaw.co/api/v1/entity/batch \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{
"identifiers": [
"213800QILIUD4ROSUO03",
{
"identifier": "01234567",
"type": "company_number",
"country": "GB"
}
]
}'This endpoint has no console on its page. It bills once per item in the list, so what one run costs depends on what you paste in. The single-value endpoint for the same signal is runnable instead.
Responses
200One result per processed identifier, plus the batch totals.
{
"success": true,
"data": {
"results": [
{
"index": 0,
"input": "213800QILIUD4ROSUO03",
"data": {
"identifier": "213800QILIUD4ROSUO03",
"identifier_type": "lei",
"found": true,
"reason": null,
"name": "ACME HOLDINGS LIMITED",
"status": "active",
"country": "GB",
"checksum_valid": true,
"registration_status": "ISSUED",
"flags": []
},
"meta": {
"credits_used": 1,
"cache_hit": false
}
},
{
"index": 1,
"input": "01234567",
"data": {
"identifier": "01234567",
"identifier_type": "company_number",
"found": true,
"reason": null,
"name": "ACME HOLDINGS LIMITED",
"status": "dissolved",
"status_detail": "Dissolved",
"country": "GB",
"flags": [
"dissolved_in_national_register"
]
},
"meta": {
"credits_used": 1,
"cache_hit": false
}
},
{
"index": 2,
"input": "5493001KJTIIGC8Y1R99",
"data": {
"identifier": "5493001KJTIIGC8Y1R99",
"identifier_type": "lei",
"found": false,
"reason": "unknown_identifier",
"name": null,
"checksum_valid": false,
"flags": []
},
"meta": {
"credits_used": 0,
"cache_hit": false
}
}
]
},
"meta": {
"requested": 3,
"processed": 3,
"found": 2,
"credits_used": 2,
"credits_remaining": 998,
"stopped_reason": null,
"request_id": "req_01m1kgdrtqdvwnks99vfgx2rcw"
}
}401The key is missing, malformed, or revoked.
{
"success": false,
"error": {
"code": "UNAUTHENTICATED",
"message": "Provide a valid API key as a bearer token.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}402The balance is empty. The lookup did not run.
{
"success": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Your credit balance is empty.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}422The request body could not be validated; `error.errors` lists the fields.
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "The email field is required.",
"errors": {
"email": [
"The email field is required."
]
},
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}429Over 5 requests per second for the key. Retry after the limit resets.
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Retry after the limit resets.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}Error codes
Failures answer { success: false, error: { code, message, request_id } }. Each code has its own page.