Concepts
Errors and idempotency
Match the machine-readable error code, retry only what is safe to retry, and use idempotency keys so a retry never creates a second payment.
Error format
{
"error": {
"code": "validation_failed",
"message": "Validation failed.",
"field": "amountCents"
}
}Use error.code; messages can change. Validation errors name the field in error.field. An unknown top-level field is reported as body and an unknown customer field as customer. Malformed JSON and invalid headers return 400 invalid_request.
Error codes
| HTTP | Code | What to do |
|---|---|---|
| 400 | invalid_request invalid_query | Fix the JSON, headers or filters. |
| 401 | unauthorized | Check the full key, its environment, and that your account is active. |
| 404 | not_found | Check the ID and the key’s environment. Other merchants’ payments also return 404. |
| 409 | idempotency_in_progress | The first request is still running. Retry later with the same key and body. |
| 409 | idempotency_key_reused | The key was used with a different body. Restore the original pairing; do not retry automatically. |
| 409 | payment_in_progress | An attempt is processing. Poll the payment; do not charge again. |
| 409 | action_required | Complete the customer action first. |
| 409 | confirmation_in_progress | Confirmation is processing. Poll the payment. |
| 409 | confirmation_not_required | Nothing to confirm. Read the current state. |
| 409 | result_pending | The previous result is being reconciled. Poll before submitting again. |
| 410 | checkout_expired attempts_exhausted | Checkout is closed. Read the payment before deciding on a new checkout. |
| 422 | validation_failed | Fix the field in error.field. An explicit environment must match the key. |
| 422 | card_token_rejected | Fix card capture, then read the checkout state before another attempt. |
| 429 | rate_limited | Wait for Retry-After and reduce concurrency. |
| 503 | service_unavailable | Retry with backoff within a limit, then escalate. It does not mean your key is invalid. |
Errors describe the request, not the payment. A failed request never replaces reading the payment status.
Idempotency
POST /v1/payments and the sandbox simulation endpoints require an Idempotency-Key header: 16–255 visible ASCII characters, unique per order.
- Store it first. Generate and save the key with the order before sending, so a retry after a crash reuses it.
- Same key, same body: replays the original
201response, with no second payment. - Same key, different body:
409 idempotency_key_reused. - Scope and lifetime: per merchant and operation, kept for 24 hours. Use different keys in sandbox and live.
Never create a new payment because a response was lost
Retry with the same key and body instead. Keep your own unique order constraint beyond the 24-hour window, and contact Wegopay if a response is still unknown near that limit.
Retry policy
- On
429, wait forRetry-After. On503, honour it when present; otherwise use exponential backoff with jitter. - On network errors, retry with the original key and body using the same backoff.
- Stop after a bounded number of attempts and investigate.
- Never log authorization headers, checkout URLs, signing secrets or payment payloads.