Build
Errors and status codes.
What each refusal means, whether anything was charged, and what to do next.
A refused request has this shape, on every endpoint:
{ "error": { "message": "…", "type": "…", "code": "…" } }type is the class of error. code names the exact reason, or is null for a plain validation error. message says what to change.
Three answers add to it or differ:
- A
402quote, or a refused MPP credential, adds the quote and payment fields, and the problem fieldstype,title,statusanddetail. - An agent's request held for approval is answered
202with the approval hold itself. See Approvals. - A stream that fails after it started sends the error as a
data:event before[DONE].
What to retry:
- Do not send a
400,402or403again unchanged. It fails the same way. - Retry a
429or503afterRetry-After, in seconds. - A
502or504was not charged, or was refunded.
The statuses the gateway answers with, their error types, and whether anything was charged:
| Status | Type | Meaning | Charged | What to do |
|---|---|---|---|---|
| 202 | approval_required | An agent's request is above its approval threshold and waits for the owner. The body is the approval hold, not an error. | No | Wait for the decision, then send it again with x-approval-id. |
| 400 | invalid_request_error | The request is malformed or asks for something the model or endpoint does not do. | No | Fix the request. The message says what is wrong. |
| 401 | authentication_error | No key, a key the ledger rejects, or a missing, expired or signed-out session or read token. | No | Send a valid credential. |
| 402 | insufficient_quota, payment_required | The balance, a cap or a budget cannot cover the request (insufficient_quota), or a payment is needed or was refused (payment_required). A link above the balance has the type insufficient_balance. | No | Fund the balance, raise the cap, or pay the quote. |
| 403 | invalid_request_error, permission_error | Not allowed: a paused key, a model or tool off the allowlist, someone else's resource, or a credential of the wrong kind. | No | Change the key's settings, or use a credential that may. |
| 404 | invalid_request_error | No such model, route, receipt or resource for this credential. | No | Check the id. A routing policy no route meets is also a 404. |
| 405 | invalid_request_error | The method is not served on this path. | No | Use the method the Allow header names. |
| 408 | invalid_request_error | The body arrived too slowly, or too little time was left to serve a paid call. | No | Send it again. |
| 409 | invalid_request_error, upstream_error | The resource is not in a state that allows this: a taken slug, a pending deposit, a job not ready. A failed or expired batch job, and a failed video, have the type upstream_error. | No | Read the message, wait or change the request, then retry. |
| 410 | invalid_request_error | A batch result, a video clip or a link is no longer held or claimable. | No; a result or clip was billed when it was made | Results and clips are kept for a limited time. Fetch them sooner. |
| 413 | invalid_request_error | The body is larger than the endpoint takes. The code is null, or upstream_rejected when the provider refused the size. | No | Send a smaller body. |
| 429 | rate_limit_error | A rate limit, an upload or job slot, or a payment already settling. | No | Wait for Retry-After, in seconds, then send it again. |
| 500 | server_error | The gateway itself failed. | No | Retry. The receipt shows any refund. |
| 502 | upstream_error, server_error | Every eligible route failed, a payment's outcome is not known yet, or the ledger did not answer. | No, or refunded | Retry, or pick another model. |
| 503 | service_unavailable, server_error | A model cannot serve right now, or a policy, setting or chain read did not answer. | No | Wait for Retry-After where given, or pick another model. |
| 504 | upstream_error | No provider answered before the deadline. | No | Retry, or lower max_tokens. |
The codes the gateway sends, by what you were doing. Each table is in alphabetical order. A refusal the ledger makes names its own reason as the code, and the message always says what to change.
- Requests and models
- Video
- Limits, caps and balances
- Pay per request
- Sessions, keys and the account
- Agents and approvals
- Links, swaps and the pool
- Platforms and providers
- Public reads
Requests and models
Chat, text completions, the other modalities, batch jobs, tools and MCP calls.
| Code | Status | What happened | What to do |
|---|---|---|---|
audio_too_long | 400 | The file can hold more than four hours of audio. | Split the file. |
bad_multipart | 400 | The multipart body could not be parsed. | Send a well-formed multipart body. |
batch_expired | 409 | The batch job ended without a result. | Nothing was charged. Submit it again. |
batch_failed | 409 | The upstream failed the batch job. | Nothing was charged. Submit it again. |
| 400 or 503 | This model, key or request cannot run as a batch job, or the gateway is not taking jobs right now (503). | Use a model with batch rates, a key without no-logs, and no stream. | |
body_incomplete | 400 | The request body ended early. | Send the whole body. |
body_timeout | 408 | The request body arrived too slowly. | Send it again. |
context_length_exceeded | 400 | max_tokens or the prompt is larger than the model takes. | Lower max_tokens or shorten the prompt. |
deadline_too_close | 408 | A paid MCP call had too little time left to serve. Nothing was settled. | Call again. |
endpoint_not_supported | 400 | A model on attested hardware serves chat completions only. | Use POST /v1/chat/completions. |
gateway_restarting | 503 | The gateway is restarting and did not serve the request. Nothing was charged. | Send it again. |
input_too_long | 400 | The speech input is longer than the model takes. | Shorten the input. |
invalid_size | 400 | The image size is not WxH within the allowed range. | Send a valid size. |
| 503 | The key's privacy flags could not be read, so nothing ran. | Retry after Retry-After. | |
max_price_unsupported | 400 | max_price was sent to an endpoint not priced per token. | Drop provider.max_price there. |
model_not_found | 404 | No listed model has this id. | See GET /v1/models. |
| 503 | The model is listed but cannot serve right now. | Retry later, or pick another model. | |
model_unverified | 503 | The model has not yet returned a verified result. | Pick a verified model. |
no_route_for_policy | 404 | No route meets the request's provider preferences. Nothing was held. | Relax the preferences. |
not_multipart | 400 | The endpoint takes multipart/form-data. | Send the body as multipart. |
not_ready | 404 | The batch job's result is not ready yet. | Poll the job until it is done. |
payment_with_key | 400 | An MCP call sent both a key and a payment. | Send one. |
| 503 | The key's or agent's policy could not be read, so nothing ran. | Retry. | |
| 400 | A batch job cannot run on the private tier. | Send it as a normal request. | |
result_expired | 410 | The batch result is no longer held. | Results are kept 7 days. Fetch them sooner. |
| 503 | The account's routing defaults could not be read, so nothing ran. | Retry. | |
stream_cut | In a stream | The gateway restarted during the stream. Nothing was charged. | Send the request again. |
stream_interrupted | In a stream | The provider's stream ended before it closed the answer. What was produced is billed, and the receipt says partial. | Send it again for the rest. |
too_many_images | 400 | More than 16 images in one chat request. | Send fewer images. |
too_many_uploads | 429 | Too many uploads in progress. | Retry after Retry-After. |
tool_error | 500 | The tool failed. Nothing was charged. | Retry. |
tool_input_invalid | 400 | The input does not match the tool's input_schema. | Fix the input. GET /v1/tools has the schema. |
tool_input_rejected | 400 or the tool's 4xx | The tool's upstream refused the input, with its own status. | Fix the input. |
tool_not_found | 404 | No tool has this id. | See GET /v1/tools. |
tool_timeout | 504 | The tool's upstream did not answer in time. Nothing was charged. | Retry. |
| 409 | The tool is disabled. Nothing was held. | Use an enabled tool. | |
tool_upstream_error | 502 | The tool's upstream failed. Nothing was charged. | Retry. |
unsupported_audio | 400 | The audio container cannot be bounded before the request runs. | Convert to WAV, FLAC, MP3 or Ogg. |
unsupported_parameter | 400 | functions or function_call was sent. | Use tools and tool_choice. |
upstream_rate_limited | 429 | The tool's upstream is rate limiting. | Retry after Retry-After. |
upstream_rejected | 400 or the provider's 4xx | The provider rejected the request itself. Chat and keyed modalities answer 400; video, batch jobs and modalities paid per request pass the provider's own 4xx through, 413 for example. Nothing is charged on a key; paid per request, $0.01 is kept. | Fix the request. |
upstream_timeout | 504 | No provider answered before the deadline. Nothing was charged. | Retry. |
| 502 | Every eligible route failed. Nothing was charged. | Retry, or pick another model. | |
wrong_endpoint | 400 | The model does not serve this endpoint. | Use one of the endpoints the message names. |
Video
Video jobs, polling and the clip.
| Code | Status | What happened | What to do |
|---|---|---|---|
aspect_ratio_unsupported | 400 | The model does not take this aspect_ratio, or takes none. | Use one the message names, or leave it out. |
gateway_restart | 503 | The gateway restarted before the clip was made or fetched. Nothing was charged. | Send the request again. |
image_required | 400 | The model makes video from a first frame. | Send image as a PNG or JPEG data URL. |
image_too_large | 400 | The first frame is too large. | Send a smaller image. |
image_unsupported | 400 | The model makes video from text only. | Leave image out. |
invalid_image | 400 | image is not a PNG or JPEG data URL that can be read. | Send a PNG or JPEG data URL. |
invalid_seconds | 400 | seconds is not a whole number the model takes. | Use the range the message names. |
negative_prompt_too_long | 400 | negative_prompt is longer than the model takes. | Shorten it. |
negative_prompt_unsupported | 400 | The model takes no negative_prompt. | Leave it out. |
prompt_too_long | 400 | The prompt is longer than the model takes. | Shorten the prompt. |
read_token_required | 401 | A video job paid per request needs its read token. | Send Authorization: Bearer <read_token>. |
restarting | 503 | This gateway instance takes no new video jobs while it restarts. | Retry shortly. |
size_unsupported | 400 | size is not taken: each model is sold at one resolution. | Send aspect_ratio instead. |
too_many_video_jobs | 429 | The key has two unbilled video jobs, or the gateway is at capacity. | Fetch or wait for one first. |
unsupported_resolution | 400 | resolution is not the model's one resolution. | Send the model's resolution, or leave it out. |
video_expired | 410 | The clip is no longer held. | Clips are kept 30 minutes. Fetch them sooner. |
video_failed | 409 | The video job failed. Nothing was charged. | Start a new job. |
video_not_ready | 409 | The clip is still being made. | Poll the job until it is completed. |
Limits, caps and balances
Rate limits, spend caps, budgets, allowlists and pauses, on keys and agents alike.
| Code | Status | What happened | What to do |
|---|---|---|---|
insufficient_balance | 402 | The balance cannot cover the request's hold, a payment or a link. | Fund the balance, or lower max_tokens. |
key_budget_exceeded | 402 | The payment is above what is left of the key's budget. | Raise the budget, or pay less. |
key_paused | 403 | The key is paused. | Resume it with paused set to false. |
model_not_allowed | 403 | The key's or the agent's allowlist does not include this model. | Add it to the allowlist, or pick another model. |
rate_limited | 429 | Over a rate limit. | Retry after Retry-After. |
request_cap_exceeded | 402 | The request's worst case is above the agent's per-request cap. | Lower max_tokens, or raise the cap. |
spend_limit_exceeded | 402 | A key's or agent's hourly, daily or monthly cap is reached. | Wait for the window to move on, or raise the cap. |
tool_not_allowed | 403 | The agent's tool allowlist does not include this tool. | Add it, or use another tool. |
Pay per request
x402 and MPP payments on the /x402 paths and keyless MCP calls.
| Code | Status | What happened | What to do |
|---|---|---|---|
agent_identity_invalid | 400 | The x-erc8004-agent value is malformed, or names another registry. | Send the agent id, or the registry this gateway checks. |
agent_identity_not_payer | 403 | The payer is not the named agent's owner or wallet. | Pay from the identity's wallet, or drop the header. |
agent_identity_unknown | 400 | The x-erc8004-agent id is not in the registry. | Check the agent id. |
| 402 | This payment signature was already used. | Sign a new payment. | |
funds_lease | 503 | Payments and gasless deposits pause briefly while gateway instances hand over. Nothing was charged. | Retry after Retry-After. |
insufficient_funds | 402 | The payer's wallet cannot fund the payment. For one minute after this or permit2_allowance_required, the address is refused in that asset with this code and Retry-After. | Hold enough of the asset, then pay again. The other asset is not affected. |
invalid_address | 400 | The wallet address is not a valid hex address. | Send the wallet's full address. |
mpp_invalid_challenge | 402 | The MPP challenge was not issued here, was altered, or is already paid. | Use a fresh challenge from a new 402. |
mpp_invalid_payload | 402 | The MPP payload does not have the shape its type needs. | Check the credential's payload. |
mpp_malformed_credential | 402 | The MPP credential could not be read. | Send base64url JSON with challenge, payload and source. |
mpp_payment_expired | 402 | The MPP challenge or signature has expired. | Ask for a new challenge. |
payment_already_resolved | 409 | This payment was already settled another way, for example refunded. Nothing was served. | Sign a new payment. |
payment_conflict | 400 | Both an x402 payment and an MPP credential were sent, or two credentials. | Send one. |
payment_in_flight | 429 | Another payment from this address is still settling. | Retry after Retry-After. |
payment_invalid | 402 | The payment does not verify. | Check the typed data and the accept signed. |
payments_busy | 429 | The gateway is settling at capacity. | Retry after Retry-After. |
permit2_allowance_required | 402 | USDF is not approved to Permit2. | Approve once, then pay again after a minute. Paying in USDG is not affected. |
quote_mismatch | 402 | The payment does not match the current quote. | Ask for a new quote. |
settlement_failed | 402 | The transfer did not settle. Nothing was served. | Pay again. |
settlement_unconfirmed | 502 | The transfer's outcome is not known yet. Nothing was served; if it lands, it is refunded automatically. | Keep the transaction the message names. Pay again if you need the answer now. |
x402 | 402 | Payment required: the body carries the quote. | Pay the quote and send the request again. |
Sessions, keys and the account
Signing in, API keys, wallet linking, deposits, withdrawals, settings, statements, teams and referrals.
| Code | Status | What happened | What to do |
|---|---|---|---|
account_not_linked | 401 | The sign-in is not linked to an account yet. | Finish signing in on the site. |
address_in_use | 409 | This wallet is linked to another account or sub-key. | Link a wallet of your own. |
already_referred | 409 | The account already has a referrer. | A referral is attached once. |
attach_velocity | 429 | Too many accounts attached a referral code from this address. | Retry later. |
| 400 | The USDG deposit authorization was refused. Nothing was taken. | Sign the typed data the gateway returned. | |
authorization_used | 409 | This USDG deposit authorization was already used or cancelled. | Ask for new typed data and sign again. |
bad_signature | 400 | The wallet signature does not match. | Sign the exact message returned. |
below_minimum | 400 or 409 | The amount is below the minimum for a link, a USDG deposit or a withdrawal. | Send at least the minimum the message names. |
| 503 | A referral code could not be allocated. | Retry shortly. | |
daily_cap | 429 | The account made the most gasless deposits it can in a day. Nothing was taken. | Retry later, or send USDF. |
deposit_in_flight | 429 | A gasless deposit for this account is still being processed. | Retry once it has finished. |
deposit_pending | 409 | A deposit is not yet final at the chain's safe head. | Retry in a few minutes. |
future_month | 400 | The statement's month has not started. | Ask for a past or the current month. |
gas_low | 503 | Gasless deposits pause while the gateway's gas is refilled. Nothing was taken. | Retry later, or send USDF. |
insufficient_usdg | 409 | The linked wallet holds less USDG than the deposit. | Deposit less, or add USDG. |
invalid_api_key | 401 | No key, or a key the ledger rejects. | Send a valid key as a Bearer token. |
| 400 | The deposit authorization is malformed. | Send the fields the typed data names. | |
invalid_nonce | 409 | The wallet link nonce expired or was already used. | Ask for a new nonce. |
invalid_session | 401 | The session token is not valid. | Sign in again. |
invalid_signature | 400 | The signature is not a hex signature of the right length. | Send the wallet's signature of the typed data. |
invalid_units | 400 | units is not a positive whole number of base units. | Send units as a string of digits. |
invalid_value | 400 | A key field is outside what the ledger takes. | Read the message, and change that field. |
invite_expired | 410 | The team invite has expired. | Ask for a new one. |
invite_limit | 409 | The team has the most open invites it can have. | Withdraw some, or wait for answers. |
key_limit | 409 | The team has the most live keys it can have. | Revoke one first. |
key_not_returned | 502 | The ledger did not return the new key. | List the keys to see whether it was made. |
key_refused | 409 | The ledger refused the key change: the active-key or hourly limit. | Revoke a key, or wait. |
key_revoked | 409 | The key is revoked; its limits no longer apply. | Use a live key. |
key_scope | 403 | This credential cannot read or act on that resource. | Use the key that made it, or a session. |
spend_read_failed | 502 | The key was changed, but its spend and limits could not be read back. | Read the key again with GET /v1/keys/{id}/limits. |
| 502 or 503 | The ledger could not be read or did not answer. | Retry shortly. | |
link_failed | 409 | The wallet could not be linked. | Read the message, then link again. |
no_account | 404 | There is no ledger account for this session. | Sign in again. |
not_key_owner | 403 | A team key can be changed only by the member who created it. | Ask its creator. |
not_linked_wallet | 400 or 409 | The authorization is not signed by the account's linked wallet. | Sign with the linked wallet. |
not_opened | 409 | The gasless deposit could not be opened. | Read the message, then try again. |
org_owner_required | 403 | Only the team's owner may do this. | Ask the owner. |
org_refused | 400 | The ledger refused the team change. | Read the message, and change the request. |
org_role_required | 403 | This needs the team's owner or an admin. | Ask an owner or admin. |
owner_not_linked | 409 | The top-up permit is not signed by the linked wallet. | Sign the permit with the linked wallet. |
owner_role_fixed | 400 or 403 | The owner's role cannot change, and the owner cannot leave. | Invite admins or members instead. |
permit_invalid | 400 | The top-up permit was refused. | Sign the permit the gateway returned. |
pull_in_flight | 409 | A top-up pull is in progress. | Retry once it has settled. |
self_referral | 409 | An account cannot refer itself. | Use another code. |
self_referral_wallet | 409 | The code belongs to an account with the same linked wallet. | Use another code. |
session_ended | 401 | The session was signed out. | Sign in again. |
session_required | 403 | This needs a signed-in session, not a key. | Use the session token. |
session_retired | 401 | This kind of session is no longer accepted. | Sign in again on the site. |
| 503 | A contract wallet's signature could not be checked on-chain. | Retry shortly. | |
| 401 or 503 | The sign-in check is unavailable. | Retry shortly. | |
| 503 | The referral terms could not be read. | Retry shortly. | |
topup_in_flight | 409 | A top-up pull from the current wallet is in progress. | Link the new wallet once it has settled. |
unauthenticated | 401 | This needs a signed-in session, or the session expired. | Sign in and send the session token. |
unknown_account | 404 or 409 | There is no account for this session yet. | Sign in again. |
unknown_code | 404 | No account has that referral code. | Check the code. |
wallet_locked | 409 | The balance must be withdrawn before another wallet is linked. | Withdraw first, then link the new wallet. |
wallet_not_linked | 409 | This needs a linked wallet. | Link a wallet first. |
wallet_required | 409 | This needs a linked wallet: deposits, top-ups and earnings use it. | Link a wallet first. |
withdrawal_refused | 409 | The ledger refused the withdrawal: the minimum, the balance, or the open and daily limits. | Read the message, then change the amount or wait. |
Agents and approvals
Creating, funding and paying agents, approvals, and the agent's token.
| Code | Status | What happened | What to do |
|---|---|---|---|
agent_not_created | 409 | The ledger did not create the agent. | Read the message, then try again. |
already_decided | 409 | The approval was already decided. | Read the queue for its status. |
already_launched | 409 | The agent already has a launch. | Each agent launches once. |
approval_denied | 403 | The owner denied this approval. | Change the request, or ask again. |
approval_expired | 403 | The approval expired. | Send the request again to queue a new one. |
approval_mismatch | 403 | The approval was given for a different request. | Send the approval with the request it covers. |
approval_not_a_hold | 403 | The agent asked for this approval itself; it does not release a held request. | Send the request without it, to be held. |
approval_not_recorded | 500 | The approval was not recorded. | Retry. |
approval_over_approved | 403 | The request could cost more than the approval covers. | Lower the request's worst case, or ask again. |
approval_required | 202 | Held for the owner's approval. Nothing was charged. | Poll the approval, then resend with x-approval-id. |
| 503 | The agent's approval threshold could not be read, so nothing ran. | Retry after Retry-After. | |
approval_unknown_approval | 403 | No approval with this id for this agent. | Check the approval id. |
approval_used | 403 | The approval was already used. | Each approval is single use. Ask again. |
approvals_pending | 429 | Too many of the agent's requests wait for approval. | Wait for the owner's decisions. |
bad_approval_id | 400 | x-approval-id is not an approval id. | Send the digits of the approval id. |
buyback_enabled | 409 | The launch has buyback on; launches through the gateway have it off. | Prepare the launch again and send that transaction. |
directory_full | 409 | The gateway's agent directory is full. | Use an existing agent, or retry later. |
idempotency_key_reused | 409 | The same Idempotency-Key came with a different amount or recipient. | Use a new key for a new payment. |
key_not_issued | 409 | No key was issued for the agent. | Read the message, then retry. |
launch_not_recorded | 409 | The ledger did not record the launch. | Read the message, then confirm again. |
launch_reverted | 409 | The launch transaction reverted. | Prepare and send a new launch. |
launch_taken | 409 | This launch is already recorded for another agent. | Each token's fees go to one agent. |
launcher_not_allowed | 409 | The launchpad does not let this wallet launch right now. | Retry later. |
launches_disabled | 409 | The launchpad has launches turned off right now. | Retry later. |
launchpad_offline | 409 | This chain's launches are not prepared through the gateway. | Use the robinhood chain. |
launchpad_unverified | 409 | This chain's launch cannot be checked by the gateway. | Use the robinhood chain. |
no_key | 409 | The agent has no active key. | Issue one with POST /v1/agents/{slug}/key. |
no_launchpad | 409 | No launchpad serves the agent's chain. | Create the agent on robinhood. |
not_a_launch | 409 | The transaction is not exactly one launch the launchpad recorded. | Send the launch transaction's hash. |
not_confirmed | 409 | The launch does not have its confirmations yet. | Retry shortly. |
not_mined | 409 | The transaction is not mined yet. | Retry shortly. |
not_owner | 403 | Only the agent's owner may do this. | Use the owner's session. |
not_provisioned | 409 | The agent has no account of its own yet. | Retry shortly. |
not_this_agent | 403 | This key is not the agent's own. | Use the agent's key. |
pair_not_approved | 409 | The launchpad does not take USDG as a pair right now. | Retry later. |
recipient_not_agent | 403 | Under the owner's session, a payment must go to an agent. | Withdraw to move a balance out. |
same_account | 400 | A payment to the paying account itself. | Pay another account. |
slug_reserved | 400 | The agent slug is reserved. | Choose another slug. |
slug_taken | 409 | Another agent has this slug. | Choose another slug. |
too_many_agents | 409 | The owner has five agents already. | Use an existing agent. |
unknown_recipient | 404 | No agent or account with that id. | Check the recipient. |
wrong_chain | 404 or 409 | The launchpad is on another chain than this gateway. | Use the gateway on Robinhood Chain. |
wrong_config | 409 | The launch used a different launch configuration. | Prepare the launch again and send that transaction. |
wrong_deployer | 409 | The launch was not signed by the account's linked wallet. | Send it from the linked wallet. |
wrong_fee_receiver | 409 | The launch's creator fees go to another address. | Prepare the launch again and send that transaction. |
wrong_pair | 409 | The launch is not paired with USDG. | Prepare the launch again and send that transaction. |
Links, swaps and the pool
USDF links, swap quotes and the USDF/USDG pool.
| Code | Status | What happened | What to do |
|---|---|---|---|
already_claimed | 409 | The link was already claimed. | Nothing to claim or cancel. |
amount_too_small | 400 | The amount swaps to less than one base unit of USDF. | Swap more. |
bad_amount | 400 | amount is not a positive integer in the token's base units. | Send the amount in base units: wei for ETH. |
bad_recipient | 400 | recipient is not the address that receives the USDF. | Send a valid address. |
bad_slippage | 400 | slippage_bps is outside the range the gateway takes. | Use the range the message names. |
bad_token | 400 | token is not an ERC-20 address or eth. | Send a token address, or eth. |
link_cancelled | 409 or 410 | The link was cancelled. | Nothing to claim. |
link_expired | 409 or 410 | The link expired, and its amount went back to the sender. | Ask the sender for a new link. |
link_not_found | 404 | No link has this token. | Check the link. |
no_route | 404 | No pool can fill the whole amount for this token. | Swap less, or another token. |
no_swap_needed | 400 | The token is USDG or USDF already. | Wrap USDG with depositFor, or use the USDF. |
own_link | 409 | This is your own link. | Cancel it to get the amount back. |
| 503 | The pool could not be read. | Retry shortly. | |
| 503 | The chain did not answer the quote. | Retry shortly. | |
token_required | 400 | token is missing. | Send an ERC-20 address, or eth. |
too_many_open_links | 409 | The account has the most unclaimed links it can have. | Cancel some, or wait for claims. |
x_identity_mismatch | 403 | The link is addressed to another X account. | Sign in with that X account. |
| 503 | Swap quotes are served on Robinhood Chain mainnet only. | Use the mainnet gateway. |
Platforms and providers
Platform keys and sub-keys, and serving your own endpoint.
| Code | Status | What happened | What to do |
|---|---|---|---|
account_suspended | 403 | An endpoint of this account is suspended. | Wait for the review. |
bad_end_user_ref | 400 | end_user_ref is empty or too long. | Send a shorter reference. |
bad_models | 400 | models is empty or has more models than the gateway takes. | Send the number the message names. |
bad_wallet | 400 | wallet_address is not the end user's own wallet. | Send the end user's wallet. |
balance_remaining | 409 | The sub-key still holds the end user's USDF. | Withdraw it to the sub-key's wallet first. |
cross_chain_limit | 409 | The balance came in on another chain. | Withdraw it on the chain it was deposited on. |
duplicate_model | 400 | A model is listed twice. | List each model once. |
end_user_exists | 409 | This end_user_ref already has a live sub-key. | Revoke it first, or reuse it. |
host_suspended | 403 | An endpoint on this host is suspended. | Wait for the review. |
id_taken | 409 | That provider slug belongs to another account. | Choose another slug. |
invalid_base_url | 400 | base_url is not an https URL on a public host. | Fix base_url. |
invalid_key | 401 | The platform key is not valid. | Send a live platform key. |
invalid_provider | 400 | A registration field is invalid. | Read the message, and fix that field. |
no_wallet | 409 | The sub-key has no wallet to return the balance to. | Set one first. |
not_platform_key | 403 | This key is not a platform key. | Create one with POST /v1/platform/create. |
platform_key_exists | 409 | The account already has a live platform key. | Revoke it first. |
priced_above_sheet | 400 | A price is not far enough below the cheapest listed route. | Lower it below the ceiling the message names. |
private_address | 400 | base_url resolves to a private address. | Use a public host. |
proof_failed | 400 | No wallet proof was issued. | Read the message, then ask again. |
| 503 | The promised rates could not be read, so prices were not checked. | Retry shortly. | |
rate_locked | 409 | A price would raise a rate a published sheet still promises. | Keep it at or below the promised rate until the date named. |
sub_key_limit | 429 | The platform has the most sub-keys it can have. | Revoke unused sub-keys. |
supplier_payer_refused | 403 | Only providers' own endpoints could serve this request, and they serve requests from a user account's own balance. | Use an account key, or another model. |
supply_full | 409 | The gateway lists the most providers' new models it can. | Register catalog models, or fewer new ones. |
suspended | 403 | This endpoint is suspended. | Wait for the review. |
too_many_open | 429 | The sub-key has the most open withdrawals it can have. | Wait for one to be sent. |
too_many_providers | 409 | The account has the most endpoints it can register. | Remove one first. |
too_many_today | 429 | The sub-key made the most withdrawals it can today. | Retry tomorrow. |
too_soon | 429 | The endpoint was changed moments ago. | Retry shortly. |
unresolved_host | 400 | base_url's host does not resolve. | Fix the host name. |
wallet_proof_required | 400 | The wallet proof is missing, expired, already used, or for another user or address. | Ask for a new proof with POST /v1/platform/wallet-proof. |
Public reads
Receipts, the usage log, the chain and other reads with no key.
| Code | Status | What happened | What to do |
|---|---|---|---|
| 400 or 503 | The chain could not be read, or is not open for this action. | Retry shortly. | |
loading | 503 | The list is still loading. | Retry shortly. |
log_integrity | 500 | The usage log is withheld while a fault is checked. | Retry later. |
method_not_allowed | 405 | The method is not served on this path. | Use the method the Allow header names. |
not_found | 404 | No such receipt, job or resource for this credential. | Check the id and the credential. |
not_yet_published | 404 or 503 | The request is not in the published log yet, or the log is loading. | Retry in a few seconds. |
unknown_chain | 400 | The chain is not one this gateway serves. | Use a chain the message names. |
unknown_cursor | 400 | before names no listed payment. | Pass the last receipt_id of a page. |
A refused MPP credential gets 402, fresh challenges and one of these problem types. The gateway's own error.code is kept beside it.
| Problem type | Meaning | error.code beside it |
|---|---|---|
malformed-credential | The credential could not be read. | mpp_malformed_credential |
invalid-challenge | Not issued by this gateway, altered, or already paid. | mpp_invalid_challenge |
payment-expired | The challenge or the signature has expired. | mpp_payment_expired |
invalid-payload | The payload does not have the shape its type needs. | mpp_invalid_payload |
verification-failed | The payment does not match the challenge, or the payer cannot fund it. | payment_invalid, insufficient_funds, permit2_allowance_required, quote_mismatch, authorization_used and the rest |
After permit2_allowance_required or insufficient_funds, that address is refused in that asset for one minute, with insufficient_funds and Retry-After. It can still pay in the other asset. Refunds after payment are in Refunds and refusals.
Retry-Afteris in seconds. Wait that long before sending the request again.- An agent's
fundandpaytake anIdempotency-Key. Repeating the call with the same key returns the first receipt and moves nothing. The same key with another amount or recipient gets409 idempotency_key_reused. - An x402 payment signature and an approval id are each single use. Sign or ask again for a new request.
- A request refused before it ran was not charged. A request that failed after its hold was taken is refunded, and its receipt says so.