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:
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 whenstatus 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 noafter, 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.
Which failures are safe to retry?
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 returns413.
What do the customer statuses mean?
How do I know when verification finishes?
Subscribe to thekyc.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
customerspermission —ERRCORE_1005 - The country is restricted —
ERRCUS_1605,Onboarding is not permitted for this country
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?
- Ask which fields the corridor requires, then add the recipient
- Generate a quote
- Create a pre-transaction to check the quote, recipient, wallet and KYC together — it moves no money
- 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 overtimestamp + "." + 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. UsesecretHint 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 asDELIVERED,
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 unrecognisedeventType 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. UseX-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 theX-Request-ID from the
response — that id joins straight to our logs.