Skip to content

Errors

Every failure carries a machine-readable code and a human sentence.

Branch on code, never on the message

The sentence is written for a person and may be reworded at any time. The code is part of the contract and will not change within v1.

The distinction that matters most is DENIAL versus COULD NOT CHECK

AUTH_UNAVAILABLE and LOOKUP_FAILED are 503s meaning we failed, not you are refused. Treating them as denial is how a working integration appears broken during a blip.

Every code v1 can return

All 22 of them, extracted from the API's own errorCodes.js — this table is generated, so a code cannot exist without appearing here.

codestatusretrymeaning and what to do
API_KEY_EXPIRED401noThe key is past its expiry. Request a new one.
API_KEY_INACTIVE401noThe key exists but is disabled. Talk to us; it was revoked or paused.
API_KEY_INVALID401noThe key did not match a live record. Check the key. Terminal — do not retry.
API_KEY_REQUIRED401noNo key, and no recognised origin. Send X-API-Key, or ask us to register your origin.
AUTH_UNAVAILABLE503yesWe could not CHECK your key — not a denial. 🚨 Retry. Treating this as a refusal locks out a legitimate partner during a blip.
CHAIN_DISABLED400noThat chain is retired or paused. Terminal. Fall back to capabilities.mintUrl.
CHAIN_NOT_SUPPORTED_BY_SURFACE400nov1 mints Solana only. Use the mint page for other chains.
CLIENT_BROADCAST_NOT_ALLOWED400noYou sent a transaction hash — meaning you broadcast it yourself. 🚨 Send the signed BYTES instead. We submit. There is no flag to disable this.
CODE_REQUIRED400noA claim-code check arrived with no code. Send { code } in the body.
COLLECTION_CLOSED409noThe drop is closed. Terminal for minting; the read still works.
COLLECTION_NOT_FOUND404noNo live drop matches that identifier. Address a drop by its short id or on-chain address — not an internal uuid.
COLLECTION_NOT_IN_SCOPE403noThe key was not issued for that drop. A key is scoped to specific collections. Terminal.
COLLECTION_REQUIRED400noNo collection was supplied. Include collectionId.
LOOKUP_FAILED503yesWe could not load the drop. Retry shortly. Not a statement about whether it exists.
NFTS_LOCKED409yesThe items are briefly held by another mint that is still settling. Transient — not a failure. Retry in a moment; tell the collector to try again, never "mint failed".
NOT_ELIGIBLE403noThis wallet does not meet the phase requirements. Show the reason from the eligibility endpoint. Terminal for this wallet/phase.
ORIGIN_NOT_ALLOWED403noThis origin is not on the key. Usually OUR configuration to fix — send us the exact origin, staging and preview included.
RATE_LIMITED429yesToo many requests. Back off and honour Retry-After.
SESSION_EXPIRED410noThe prepared session timed out before the signature came back. Call prepare again. Never reuse a stale session.
TX_MODIFIED400noThe signed transaction does not match what we built. 🚨 Never retry blindly — rebuild with prepare. This is the guard that protects your collectors.
UNSUPPORTED_BY_SURFACE409noThe drop needs a mechanic v1 cannot render faithfully. Read capabilities.requiresFeatures and link to capabilities.mintUrl rather than rendering a wrong panel.
WALLET_MISMATCH400noThe signing wallet is not the wallet the session was prepared for. Prepare and sign with the same wallet.

The mint-time ones worth reading twice

  • NFTS_LOCKED is not a failure. The item is briefly held by another mint that is still settling. Telling the collector "mint failed" is wrong — tell them to try again in a moment.
  • TX_MODIFIED means the bytes we received are not the bytes we built. Rebuild; never resubmit. This is the check that makes it safe for us to be the one broadcasting.
  • CLIENT_BROADCAST_NOT_ALLOWED cannot be turned off. See the broadcast rule.

SDK pages are generated from the published npm tarballs and cannot drift.