Errors
Every error response from Ele has the same shape:
{ "error": { "type": "not_found", "message": "Resource not found.", "request_id": "…" }}| Field | Meaning |
|---|---|
type |
A short code for what went wrong. Your code branches on this. |
message |
A sentence you can show to a person as it is. Never branch on it: the wording can change. |
request_id |
The ID of this request. Quote it when you contact Ele support. |
details |
More detail, when there is some. On a validation error it lists each field that failed and why. |
step_up |
The step-up challenge, when type is step_up_required. See Step-up and approvals. |
type, message and request_id are always there. details and step_up are
there only when they apply, and may be null.
Branch on the type
Section titled “Branch on the type”Decide what to do from error.type. Do not decide from the HTTP status alone,
because many types share a status: a 403 can mean the person lacks a role, or
that the call needs step-up.
Treat type as an open list. Ele adds new types over time, and any failure
without a specific type comes back as unprocessable_entity. Handle the types
you care about and send everything else to one default branch that shows the
message and logs the request_id.
In Go, with the helper from the example code:
var apiErr *ele.APIErrorif errors.As(err, &apiErr) { switch apiErr.Type { case "step_up_required": // Ask the person to complete step-up, then retry. case "not_authenticated": // The session has ended. Sign the person in again. case "rate_limited": // Wait, then retry. default: log.Printf("ele: %s (request %s)", apiErr.Type, apiErr.RequestID) // Show apiErr.Message to the person. }}Request IDs
Section titled “Request IDs”Every response, success or failure, carries an x-request-id header. On an
error it is the same as error.request_id, except on a
replayed response, whose body keeps the ID of the
original request. Log it with every failed call. When you
ask Ele support about a request, the ID lets them find it.
Error types
Section titled “Error types”These are the types you will meet most often. Each operation’s reference page lists the statuses it can return.
| Status | type |
Meaning | What to do |
|---|---|---|---|
400 |
invalid_request |
A path or query parameter is missing or invalid. details names it. |
Fix the request. Do not retry it unchanged. |
400 |
idempotency_key_required |
This write needs an Idempotency-Key header. |
Add one. See Idempotency. |
401 |
not_authenticated |
The bearer token is missing, invalid or expired. | Sign the person in again. See Authentication. |
401 |
invalid_credentials |
Sign-in: the email or password is wrong. | Ask the person to try again. |
401 |
invalid_api_key |
The API key is malformed, unknown, revoked, for the other environment, or its secret does not match. | Check the key. See API keys. |
403 |
forbidden |
The person’s role in this organization does not allow this. | Show the message. See Organizations and roles. |
403 |
step_up_required |
The call needs the person to confirm they are present. | Complete step-up, then retry. See Step-up and approvals. |
403 |
step_up_enrollment_required |
The call needs step-up, and the person has no method strong enough. | Ask the person to set up an authenticator app. A passkey or the Ele mobile app also counts, but your server can only pass on authenticator codes. |
403 |
api_key_not_permitted |
This operation does not accept an API key. | Call it with a person’s session token. |
403 |
api_scope_missing |
The API key lacks the scope this operation needs. | Give the key that scope, or use another key. |
403 |
organization_unavailable |
The API key’s organization is paused, banned or deleted. | Contact Ele support. |
404 |
not_found |
The resource does not exist, or this person cannot see it. | Check the ID and the organization. |
409 |
conflict |
The request conflicts with the resource’s current state. | Fetch the resource again and decide. |
409 |
idempotency_conflict |
A request with this Idempotency-Key is still running, or stopped partway. |
Wait, then retry with the same key. See Idempotency. |
413 |
content_too_large |
The request body or upload is too large. | Send less. |
415 |
unsupported_media_type |
The body is not JSON. | Send Content-Type: application/json. |
422 |
invalid_request |
The request body failed validation. details lists each field that failed. |
Fix the body. Do not retry it unchanged. |
422 |
validation_error |
Ele rejected a value in the body. details says which. |
Fix the value. |
422 |
idempotency_params_mismatch |
This Idempotency-Key was already used with a different body. |
Use a new key for a new request. |
422 |
insufficient_funds |
The organization’s balance does not cover a payment, a payment batch or a swap. | Show the message. Add money, or send less. |
422 |
insufficient_balance |
The balance does not cover a purchase from Ele, such as a plan or a card order, or there are not enough reward points. | Show the message. |
422 |
kyc_required |
The person or organization must finish identity checks first. | Send the person to onboarding. |
422 |
unprocessable_entity |
Any other refusal without a more specific type. When details is present, it lists the fields that failed. |
Show the message. |
429 |
rate_limited |
Too many attempts. | Wait, then retry. On a write with an Idempotency-Key, retry with a new key. See Rate limits. |
500 |
internal_error |
Something failed inside Ele. | Check whether the work happened before you retry. See Retrying. |
502 |
provider_unavailable |
A partner that Ele relies on did not answer. | Check whether the work happened before you retry. See Retrying. |
502 |
xero_unavailable |
Xero did not answer. | Retry with the same key. See Retrying. |
Many operations add their own types, such as already_rejected when you approve
a rejected request. The reference page and the guide for each area name them.
Retrying
Section titled “Retrying”Reads are always safe to retry. Writes need care.
If you sent a write with an Idempotency-Key, Ele keeps most answers under that
key, errors included. A retry with the same key returns the same error for 24
hours. That includes 429, 500 internal_error and 502 provider_unavailable. To try again after a kept error, you need a new key, and
a new key can do the work a second time if the first attempt did take effect:
- After a kept
4xxrefusal, Ele did not do the work. Fix the cause, or wait, and retry with a new key. - After
500 internal_erroror502 provider_unavailable, check whether the work happened before you retry with a new key. If you cannot tell, do not retry: a duplicate payment is worse than none.
Some answers are not kept. For these, keep the same key:
409 idempotency_conflict: the first request is still running, or stopped partway. Wait, then retry with the same key. Never switch to a new key here: the work may already be done.502 xero_unavailable: retry with the same key.- Validation failures (
invalid_request, orunprocessable_entitywith fielddetails) andstep_up_required: fix the cause, then retry with the same key.
Idempotency lists which answers are kept and which are not.
Errors that are not Ele errors
Section titled “Errors that are not Ele errors”A few failures do not come back in the envelope above. An unexpected failure
inside Ele can return 500 with a different JSON body, and a proxy between you
and Ele can return an HTML page. Your client must still handle these. Treat any
status of 500 or above without an error.type as a failure whose outcome is
unknown: for a write, check whether the work happened before you retry. See
After a failure.
The Go helper does this for you. When the body is not an Ele error, it returns
an APIError with an empty Type, and Message holds the status and the start
of the body.