Caravel Pay Docs

API reference

Errors

Failed requests return a non-2xx status and a JSON body with a stable code you can branch on, plus a readable message.

Error format#

400 Bad Request
{
  "error": {
    "code": "invalid_amount",
    "message": "amount must be a string with two decimals, like \"136.41\"",
    "param": "amount"
  }
}

param is included when the error is about one field.

HTTP status codes#

StatusMeaningRetry?
200 201Success.—
400The request is malformed or a field is invalid.No. Fix the request.
401Missing or wrong credentials, signature or timestamp.No. Fix the signing.
403This merchant can't create checkouts right now: it is paused or waiting for approval.No. See the code.
404No such checkout for this merchant.No.
409The order_id already belongs to a checkout with different details, or a limit was reached.No. See the code.
429Too many requests.Yes, after the Retry-After header.
500Something went wrong on our side.Yes, with backoff and the same order_id.
503New checkouts are briefly unavailable.Yes, after the Retry-After header, with the same order_id.

Error codes#

CodeStatusWhat happened
invalid_request400The body isn't valid JSON, a field is missing or unknown, a query parameter is wrong, or the body is over 16 KiB. See param.
invalid_amount400amount isn't a string with exactly two decimals between "0.01" and "1000000.00".
unsupported_currency400currency isn't "USD".
invalid_url400One of return_url, cancel_url or callback_url isn't an absolute HTTPS URL on your site (your site_url, with or without www). On POST /v1/connect: site_url isn't a plain HTTPS address.
unknown_merchant401Caravel-Merchant is missing or doesn't match a merchant.
invalid_signature401Caravel-Signature doesn't match. See common mistakes.
timestamp_expired401Caravel-Timestamp is missing, malformed or more than 300 seconds from our clock.
merchant_paused403New checkouts are paused for this merchant. Open checkouts and payouts still finish. Email hello@caravelpay.app.
merchant_pending_review403The site is waiting for approval. Checkouts open once it is approved.
not_found404No checkout with that id belongs to you, or no such endpoint.
order_id_conflict409That order_id was already used for a checkout with different details. Use a new order_id.
limit_exceeded409A limit for this merchant was reached: order size, daily count or volume, or open checkouts. Try a smaller order or try again later. On POST /v1/connect: the payout wallet already serves the maximum number of merchants.
rate_limited429Slow down and retry after Retry-After seconds.
server_error500Unexpected error on our side. Safe to retry.
service_unavailable503New checkouts (or new merchants) are briefly unavailable. Retry after Retry-After seconds, with the same order_id. Open checkouts and payouts aren't affected.

Retrying safely#

  • Network errors, 429 and 5xx: retry with exponential backoff, and wait at least Retry-After seconds when it is sent. Re-sign each attempt with a fresh timestamp, and keep the same order_id so you can't create a duplicate checkout.
  • Other 4xx: don't retry unchanged. Fix the request first.