Skip to main content
Answers to the questions partners ask most often while integrating. Each heading links directly, so you can point a colleague at a single answer.

Getting started

What do I need before my first call?

An API key issued by Endl, carrying the permissions for the endpoints you intend to call. There is no sign-up endpoint and no login step — keys are issued to your partner account by Endl.

Is there a sandbox?

Yes. Every Try it button in this documentation sends to sandbox, so you can exercise an endpoint from the page you are reading.

Which API do I need?

One key authenticates all four, though each endpoint is gated by its own permission — POBO needs pobo.

How do I get production access?

Your production base URL and credentials are issued by Endl at onboarding. Point your client at that host and use the credentials issued with it — the request and response shapes are identical to sandbox.

Authentication

Do I need an API secret?

No. Authentication is a single header, API-KEY. The API-SECRET header was removed and is no longer part of any endpoint.

Do I need to send anything besides the API key?

Yes — Api-Version. Every /api/v0/* request carries two required headers:
Omitting the version is a 400, whatever your key says. The version that served the request is echoed back on the response, so you can assert on it. See Versioning.

Why am I getting 400 The 'Api-Version' header is required?

The Api-Version header is missing, malformed, or names a version Endl does not ship. The format is YYYY-MM.<release> — 2026-09.1 — validated against ^\d{4}-\d{2}\.\d+$. v1 and 2026-9 are both malformed. OPTIONS preflight requests are exempt.

My key is valid, so why am I getting a 403?

A missing permission. Endpoints are gated by quotes, recipients, accounts, webhooks, events, customers, pobo and cards, and a key without the required one is rejected at the edge before the request reaches the service — so the 403 never confirms or denies that the resource you asked for exists. This is the same across all four APIs: they sit behind one edge, which is what authenticates and authorises every /api/v0 request.

What is the difference between 401 and a 5xx?

401 means your credentials were rejected — the header is missing, the key is unknown, or the partner is inactive. These are deliberately indistinguishable, and retrying will never succeed. A 5xx means your key may be fine and something upstream failed, so retry with backoff. 502 means the edge could not reach the service behind it; 503 DIRECTORY_UNAVAILABLE means it could not reach the credential store.

Why does a URL I know is correct return 401?

Because authentication runs before routing. Without a valid key every request answers 401, including one to a path that does not exist or sent with the wrong verb. A 404 or 405 only becomes visible once you are authenticated, so check the credential before you start doubting the path.

Can I call the API from a browser or a mobile app?

No. The key authenticates your partner account, not an end user, so it belongs server-side only. Never ship it in client code or commit it to source control.

What do I do if a key leaks?

Ask Endl to issue a replacement credential.

Requests and responses

What shape are responses?

Two shapes, which is the one inconsistency worth holding in mind: Errors raised at the edge — a rejected key, a tripped rate limit — use the envelope on every surface, whatever the success shape is. Onboarding errors use one five-key envelope — { code, message, status, data, errors[] } — for every status code, and each onboarding error carries its own ERRCUS_* code. See Errors and lifecycle.

Should I trust the HTTP status or the body?

Both. On the Partner, Webhooks and POBO APIs a response is only successful when status is SUCCESS and errors is empty. See Errors and the response envelope.

Do I need to handle 429?

Yes. Requests are rate-limited per API key at the edge — 60 per minute by default — and exceeding it returns 429 with X-RateLimit-Limit and X-RateLimit-Remaining. The window is a rolling minute, and nothing was processed, so back off and retry.
Webhooks has a second, unrelated limit. The per-subscription retry and send allowances — 20 per minute by default — are a property of the subscription rather than of your key. They return 429 too, but under their own codes, ERRWHK_1105 and ERRWHK_1106.Branch on the code, not the status: ERRCORE_1006 means slow down overall, ERRWHK_110x means slow down on that one subscription.

How should I handle money values?

As decimal strings, never floats — "1500.00". Parse them with a decimal type. Binary floats lose cents at scale.

How does pagination work?

Opaque, forward-only cursors. Call with no after, read data.nextCursor, and call again with after=<nextCursor> and the same filters until the cursor is null. limit defaults to 25 and caps at 100.
A short page is not the end. Filters are applied after the query, so a page can return fewer items than limit — even zero — while nextCursor is still non-null. Follow the cursor until it is null.

Which failures are safe to retry?

Never blindly retry a write that may have succeeded — Submit transaction in particular. Read the transaction back before resubmitting it.

Why did I get a 404 for a resource I know exists?

Identity is derived from your API key, and you only ever see your own resources. Another partner’s resource returns 404, never 403, so the API never reveals that it exists.

Onboarding

What is the difference between KYC and KYB?

KYC verifies an individual; KYB verifies a business and its beneficial owners. Step-by-step walkthroughs: Individual (KYC) and Business (KYB).

What file types and sizes are accepted for documents?

JPEG, PNG or PDF, at most 5 MB per file. Content is sniffed rather than trusted from the extension. A larger file returns 413.

What do the customer statuses mean?

How do I know when verification finishes?

Subscribe to the kyc.completed and kyc.rejected webhook events, or poll Get customer.

Why did creating a customer return 403?

Two different causes share that status — errors[].code distinguishes them:
  • Your key lacks the customers permission — ERRCORE_1005
  • The country is restricted — ERRCUS_1605, Onboarding is not permitted for this country
The country check runs before anything is created, so nothing needs cleaning up afterwards.

A create timed out with 503. Can I retry it?

Yes, with the same body. Endl reconciles rather than creating a duplicate.

Payouts

What is the sequence of calls?

  1. Ask which fields the corridor requires, then add the recipient
  2. Generate a quote
  3. Create a pre-transaction to check the quote, recipient, wallet and KYC together — it moves no money
  4. Submit, then poll Get transaction or subscribe to payout.completed

How long is a quote valid for?

Ten minutes. expiresOn is set 600 seconds after the quote is generated, and expiry is enforced when you use the quote, at Create pre-transaction — not when you read it. A quote also backs exactly one transaction, including one that later fails, so every retry needs a fresh quote. See The ten minutes in the Quotes guide.

Why was my recipient rejected as invalid?

Required fields vary by destination currency and rail and are not guessable — a GBP domestic payout needs different fields from a SEPA or SWIFT one. Call Get recipient fields first and collect exactly what it returns.

Which currencies, countries and rails are supported?

These catalogues change, so they are served by the API rather than listed here: Cache the results rather than re-fetching them on every request.

Webhooks

Should I use PUSH or PULL?

SQS and SSE are reserved but not yet available — requesting either returns 422.

How do I verify a delivery came from Endl?

HMAC-SHA512 over timestamp + "." + body, compared against X-WEBHOOK-SIGNATURE. Three things to get right: it is SHA-512, the hex is lowercase, and you must hash the raw received bytes — parsing and re-serializing the JSON changes those bytes and breaks the signature. Worked Python and Node examples are on Verifying signatures.

I lost my signing secret. Can I retrieve it?

No, and there is no rotate endpoint. It is returned once, when the subscription is created, and cannot be read back. Delete the subscription and create a new one — that mints a fresh secret bound to a new subscription id and leaves the old one’s delivery history intact. Use secretHint to check which secret you are signing with without either side handling the secret itself.

What happens if my endpoint is down?

Endl retries, and every attempt is recorded. A delivery ends as DELIVERED, FAILED, EXPIRED or CANCELLED; only FAILED and EXPIRED can be retried. Inspect what happened with List deliveries, which includes the response your endpoint returned.

Why is my subscription SUSPENDED?

Endl suspends a subscription after repeated delivery failures. You cannot set that status yourself. PAUSED, which you control, holds events rather than dropping them — they drain when you resume.

How many subscriptions can I have?

Five active per partner by default. target is limited to 512 characters.

Will you send event types I do not recognise?

Yes. Endl manages the catalogue and adds types over time, so handle an unrecognised eventType gracefully rather than rejecting it — otherwise a new event type becomes an outage in your receiver. Subscribing with a glob such as payout.* picks up related types automatically.

Are PULL feed responses signed?

No. You are reading from Endl over an authenticated connection, so there is nothing to verify. Signatures exist because PUSH arrives unsolicited.

Why does a delivery use an idempotency key?

Retries mean your endpoint can legitimately receive the same event more than once. Use X-WEBHOOK-EVENT-ID to deduplicate.

Still stuck?

Deliveries and errors are inspectable from the API itself — start with List deliveries for webhook problems and Errors and the response envelope for everything else. If that does not resolve it, contact your Endl representative with the failing request, the response body, the timestamp, and the X-Request-ID from the response — that id joins straight to our logs.