Talk to usGet started
Guides

Errors

Conventional HTTP status codes, a machine-readable code, a message written for the person, and a request id on every error.

The error body

JSON
{
  "error": "insufficient_funds",
  "message": "Your wallet available is below this amount. Fund your wallet, then retry.",
  "request_id": "req_a1b2c3"
}

error is stable and meant for code. message is written for the person and safe to pass on as it is. Some errors carry one more field: expired_at on expired_api_key, hosts and hint on site_ambiguous, limit on plan_limit, code on a refused top-up.

By status

StatusCodes
400invalid_request, invalid_amount, connection_not_found, site_required, site_ambiguous, agent_required
401missing_api_key, invalid_api_key, expired_api_key
402insufficient_funds, plan_limit, wallet_limit, funding_budget_reached, funding_unavailable, funding_refused
404card_not_found, spend_not_found, checkout_not_found, connection_not_found, account_not_found, not_found
409agent_paused, busy, not_resumable
500server_error, checkout_create_failed
502card_issue_failed, reveal_failed, close_failed, remove_failed, connect_failed, spend_status_failed, checkout_start_failed, enqueue_failed, connect_start_failed, disconnect_failed, wallet_read_failed, funding_session_failed, bank_transfer_failed
503own_card_unavailable, unavailable

The full list with the meaning of each code is in the errors reference.

How to handle them

  • 401: fix the key. Nothing else will work until you do. expired_api_key tells you when it expired.
  • 402 insufficient_funds: read GET /v1/wallet, then fund the wallet. ready_to_spend may already cover a checkout even when available does not.
  • 402 plan_limit: the plan's cards a month, or per-card cap, is reached. The person upgrades in the console under Billing.
  • 409 busy: the merchant session is running another checkout. Wait and retry with the same idempotency_key.
  • 409 agent_paused: the person paused the agent in the console. Nothing runs until they resume it.
  • 502: an upstream step failed; the message says which. Retry with the same idempotency_key; a checkout that already started is returned instead of duplicated.
  • 404: the id is wrong, or belongs to another account. The two are indistinguishable on purpose.

In the SDKs

Both SDKs throw on any non-2xx response with the status, the code and the request id.

import { AgentPay, AgentPayError } from "@agentpay-global/sdk";
try {
  await agentpay.cards.create({ amount: 20, merchant: "namecheap" });
} catch (e) {
  if (e instanceof AgentPayError && e.code === "insufficient_funds") {
    // e.status === 402, e.requestId
  }
}
from agentpay import AgentPay, AgentPayError
try:
    agentpay.cards.create(amount=20, merchant="namecheap")
except AgentPayError as e:
    if e.code == "insufficient_funds":
        print(e.status, e.request_id)