Resources
Error codes
Every failure uses the same envelope. Branch on error.code — it is stable — and show error.message only to your own staff.
json
{
"error": {
"code": "invalid_request",
"message": "Invalid uuid",
"details": [{ "field": "plan_id", "message": "Invalid uuid" }]
}
}Codes
| Code | HTTP | Cause | What to do |
|---|---|---|---|
| unauthorized | 401 | Missing, unknown or revoked API key. | Check the Authorization header and that the key is still active in your portal. |
| forbidden | 403 | The key is not allowed to perform this action. | Contact support — your key scope needs changing. |
| account_inactive | 403 | Your partner account is pending or suspended. | Nothing to retry. Contact support@journeystack.co. |
| invalid_request | 400 | A field is missing, malformed or out of range. | Read `error.details` for the offending field, fix and resend. |
| insufficient_funds | 402 | Your prepaid balance is lower than the order total. | Top up, then retry with the same idempotency key. |
| not_found | 404 | Unknown plan, order or eSIM, or one belonging to another partner. | Re-fetch the ID. Plans return not_found once they are retired from the catalogue. |
| conflict | 409 | The request clashes with the current state of the resource. | Re-read the resource before retrying. |
| rate_limited | 429 | You exceeded your per-minute request limit. | Honour `Retry-After` (60 seconds) and back off. Ask support for a higher limit. |
| provider_error | 502 | The eSIM could not be issued on the network. The order is marked failed. | You were refunded in full. Safe to place a new order with a new idempotency key. |
| internal_error | 500 | Unexpected failure on our side. | Retry with the same idempotency key — it can never double-charge you. |
Which errors cost money
None of them. A validation, authentication, rate limit or not-found error never touches your balance, and `provider_error` is refunded in full before the response is written.