Skip to main content
POST
/
v1
/
agents
/
{id}
/
x402-pay
Pay for an x402-gated resource
curl --request POST \
  --url https://api.example.com/v1/agents/{id}/x402-pay \
  --header 'Content-Type: application/json' \
  --data '
{
  "paymentRequirement": {},
  "paymentRequirement.amount": "<string>",
  "paymentRequirement.currency": "<string>",
  "paymentRequirement.network": "<string>",
  "paymentRequirement.recipient": "<string>",
  "paymentRequirement.description": "<string>",
  "paymentRequirement.resource": "<string>"
}
'
{
  "paymentHeader": "<string>",
  "transactionId": "<string>"
}

Documentation Index

Fetch the complete documentation index at: https://docs.relayer.fi/llms.txt

Use this file to discover all available pages before exploring further.

This is the payment primitive of the Agent Kit. The agent presents a payment requirement (received from a 402-responding service), the API validates against all 3 budget layers + the kill switch, executes the on-chain USDC transfer, and returns a payment header the agent can attach to retry the original request.
Most users should use the SDK’s x402fetch() helper instead of calling this endpoint directly. x402fetch handles the full 402 → pay → retry loop transparently.

When to call this directly vs use x402fetch

Use caseRecommended
Calling a third-party API that may return 402x402fetch — handles the loop for you
Building a custom client (non-Node.js, no SDK)This endpoint — replicate the loop yourself
Paying for a resource without retrying (e.g. pre-paying for batch credit)This endpoint — caller controls what to do with the payment header
Inspecting payment intent before executingThis endpoint — you can re-render the requirement to the user before submission

How the loop works (with x402fetch)

The whole loop is one await x402fetch(sdk, url, init) call in the SDK. This page covers what happens server-side during the middle step.

Authentication

This endpoint accepts either auth mode:
  • HMAC (X-Agent-Auth + x-agent-id + x-request-timestamp) — when called by the agent SDK at runtime. See Authentication for the payload spec.
  • API key (Authorization: ApiKey ...) — when called by your backend on behalf of the agent.
The {id} path param must match the calling agent (if HMAC) or be a valid agent in the API key’s workspace (if API key).

Request body

paymentRequirement
object
required
The payment terms received in the 402 response from the resource. Schema below.
The paymentRequirement object:
paymentRequirement.amount
string
required
Decimal USDC amount as a string (e.g. "0.05"). String to avoid float precision issues.
paymentRequirement.currency
string
required
Always "USDC" in v1. Reserved for future expansion.
paymentRequirement.network
string
required
Stablecoin network. Today: "solana". EVM chain support is planned.
paymentRequirement.recipient
string
required
The address that should receive the USDC. The API validates this matches the 402 response’s intent.
paymentRequirement.description
string
Optional human-readable description from the resource. Logged in the audit trail.
paymentRequirement.resource
string
Optional URL of the resource being paid for. Logged in the audit trail.

Response

paymentHeader
string
The opaque value to attach to your retry request as the X-Payment header. The resource will validate it and serve the protected content.
transactionId
string
Optional. Set if the payment resulted in an on-chain transaction (vs. a pre-funded credit pull). Use with chain explorers to confirm.

What the API checks before executing

  1. Authenticates the request (HMAC or API key).
  2. Looks up the agent and validates it’s not killed or paused.
  3. Polls the kill switch state — refuses on active kill switch.
  4. Validates all 3 budget layers atomically (Lua script in Redis):
    • infra — does the agent have infrastructure budget left?
    • tokens — does the agent have LLM token budget left? (informational here)
    • payments — does the requested amount fit under monthlyUSDC AND perTxUSDC?
  5. Checks approval threshold: if amount >= approvalThresholdUSDC, holds the payment and returns HTTP 202 with { approvalId } instead of executing. Wait for human approval, then retry.
  6. Validates wallet balance: rejects if the agent wallet doesn’t have enough USDC.
  7. Executes the on-chain USDC transfer atomically.
  8. Emits a payment event to the agent event stream (visible at GET /v1/agents/{id}/audit).
  9. Returns the payment header.
The budget deduction (step 4) is atomic: even if the agent makes 10 parallel x402-pay calls, the Lua deduction ensures no double-spend past the cap. The cap cannot be bypassed by code path manipulation in the agent.

Approval gate — HTTP 202

If the payment amount triggers the approval threshold, the response is:
{
  "success": true,
  "statusCode": 202,
  "data": {
    "approvalId": "apr_xyz789",
    "status": "pending_approval",
    "expiresAt": "2026-05-15T12:05:00.000Z"
  }
}
The SDK’s x402fetch handles this transparently — it polls /v1/signing/approvals/{id} every 5s until resolved or approvalTimeout (default 5 minutes), then retries the original request. If you’re calling this endpoint directly, you must implement the same loop. Approvals can resolve in one of three states:
  • approved — proceed with the original retry using the payment header
  • rejected — surface the error to your agent’s reasoning; do not retry
  • expired — same as rejected; the threshold was set for a reason

Common errors

StatusCauseFix / Recovery
401 invalid_authHMAC headers missing or signature mismatchVerify the SDK is correctly initialized; check secret rotation
401 agent_killedAgent in killed stateProvision a new agent; this one is dead
402 budget_exhaustedOne or more budget layers empty. Response body includes failedLayersTop up the budget via POST /v1/agents/{id}/budget and retry
402 insufficient_wallet_balanceBudget OK but wallet has no USDCFund via POST /v1/agents/{id}/fund/prepare + /fund/confirm
503 kill_switch_activeGlobal kill switch trippedWait for resolution; do not retry until kill switch clears
202 approval_requiredAbove thresholdPoll the approval ID

Working with paymentRequirement

The exact format of paymentRequirement depends on the 402-responding service. The SDK normalizes common variants:
  • HTTP 402 with WWW-Authenticate: x402 header
  • HTTP 402 with paymentRequirement JSON body
  • HTTP 402 with Payment-Required body field
If you’re calling this endpoint without the SDK, parse the 402 response yourself and pass the requirement here as-is. Use the SDK’s x402fetch wrapper. It handles 402 detection, this endpoint call, header injection, and retry transparently — your agent code calls a normal fetch and never deals with payment plumbing directly. See SDK Reference — x402fetch.

Next steps

  • SDK Reference — x402fetch — the recommended way to do this
  • Agent Kit Flow Guide — full agent lifecycle context
  • POST /v1/agents/{id}/budget — adjust spend limits if you hit them often
  • POST /v1/agents/{id}/fund/prepare — top up the agent wallet