Skip to main content
Every Platform API error follows the RFC 7807 Problem Details format. This page covers common error scenarios, retry strategies, and domain-specific error codes.

Error Format

{
  "type": "https://api.sumvin.com/errors/wal-404-001",
  "title": "Wallet Not Found",
  "status": 404,
  "detail": "No wallet found with ID 12345",
  "instance": "/v0/wallets/12345",
  "error_code": "WAL-404-001",
  "trace_id": "abc-123-def"
}
FieldDescription
typeA URI identifying the error type
titleA short, human-readable summary
statusThe HTTP status code
detailA human-readable explanation specific to this occurrence
instanceThe request path that generated the error
error_codeMachine-readable code in {DOMAIN}-{STATUS}-{SEQUENCE} format
trace_idUnique identifier for this request — share with support for debugging

Domain Prefixes

Each error code starts with a domain prefix that identifies the resource or subsystem the error originated from. Branch on error_code to render domain-specific UI without parsing detail strings.
PrefixDomain
USRUsers and accounts
ONBOnboarding state machine
WALWallets (EOA and Safe)
KYCKYC verification
SAFSafe smart contract creation
SGNAgent signer setup
STSUser status transitions
PHONEPhone verification
TXNTransactions
RCTReceipts
BUDBudgets
INSInsights
CRDCards
CHTChat sessions and messages
IPAErrand (Intelligent Purchase Authorisation) operations
PINTStamped Mandate (Purchase Intent) signing and validation
PAYPayment Links and x402 settlement
SISSumvin Identity Service (org/env/member/keys)
BNKBank linking and open banking
RMPOn/off-ramp sessions
ACCAccounts
ASTAssets
GENGeneral validation
SYSInternal system errors
The tables below cover the most common errors integrators encounter on the Platform API. The full catalogue is reflected in the OpenAPI spec.

Common HTTP Status Codes

StatusMeaningAction
200Success
201CreatedResource created successfully
202AcceptedAsync operation started — poll _links for completion
208Already ReportedIdempotent replay — resource already exists, returned as-is
400Bad RequestFix the request body or parameters
401UnauthorizedCheck your JWT or API key
403ForbiddenValid credentials but insufficient permissions
404Not FoundResource doesn’t exist — check the ID
409ConflictResource state conflict (e.g., duplicate wallet)
422UnprocessableMissing or invalid required fields
424Failed DependencyUpstream dependency not ready (e.g., agent signer not provisioned)
429Too Many RequestsRate limited — wait for Retry-After header duration
500Internal ErrorRetry with exponential backoff

Authentication Errors

Error CodeStatusDescriptionResolution
USR-401-001401Missing or invalid JWTCheck x-juno-jwt header contains a valid, unexpired token
USR-404-001404No user exists for this JWTCreate the user first with POST /v0/user/

User & Onboarding Errors

Error CodeStatusDescriptionResolution
USR-409-001409User already existsUse the existing user — POST /v0/user/ returns 208 Already Reported
USR-422-001422Missing required fields on user creationInclude primary_eoa_address and chain_id

Wallet Errors

Error CodeStatusDescriptionResolution
WAL-400-001400Invalid Ethereum address formatProvide a valid 0x-prefixed, checksummed address
WAL-400-002400Chain ID does not match primary chainUse the same chain as the primary wallet
WAL-400-004400Primary chain is locked because a Safe wallet is already persisted on a different chainDon’t try to switch primary chain after a Safe has been deployed. See Wallets Guide
WAL-403-001403Cannot delete primary walletSet another wallet as primary first
WAL-403-002403Wallet belongs to another userVerify the wallet ID
WAL-403-003403Wallet address not in verified credentialsVerify wallet ownership — see Wallets Guide
WAL-404-001404Wallet not foundCheck the wallet ID; list wallets via GET /v0/wallets
WAL-409-001409Wallet already exists for this address and chainUse the existing wallet
USR-424-001424No active agent signerWait for onboarding to complete before setting a primary wallet

Onboarding Errors

Error CodeStatusDescriptionResolution
ONB-409-001409Submitted step does not match the user’s current stepRead GET /v0/user/me/onboarding/steps and submit current_step
ONB-409-002409The targeted onboarding step is already completed (BYO Safe / user-signed deploy submission for a closed step)The user is already past this step — fetch their current state and route accordingly

Safe Operation Errors

Error CodeStatusDescriptionResolution
SAF-400-012400User-signed Safe deploy verification failed (not a Safe, wrong owners, wrong contract version)Permanent — do not retry. The deployed contract does not match expectations.
SAF-409-001409Idempotency-Key reused with a different request bodyUse a fresh key for a different request, or replay the original
SAF-503-001503User-signed Safe deploy finalisation hit a transient error after the UserOperation was includedPause polling for the Retry-After interval (default 5s) then retry the status poll

SIS Configuration Errors

Error CodeStatusDescriptionResolution
SIS-409-008409Mutually-exclusive features both requested enabled (ai_agent + user_signed_deploy)Disable one before enabling the other. See Environment features

KYC Errors

Error CodeStatusDescriptionResolution
KYC-403-001403KYC already submittedCheck status with GET /v0/kyc/status instead of re-submitting
KYC-409-001409KYC session already in progressWait for the existing session to complete

Retry Strategy

Retryable Errors

These errors are transient and should be retried with exponential backoff:
StatusStrategy
429Wait for the Retry-After header value, then retry
500Retry up to 3 times with exponential backoff (1s, 2s, 4s)
424Retry after a delay — the upstream dependency may become available
202Not an error — poll the linked resource for completion

Non-Retryable Errors

These indicate a problem with the request itself:
StatusAction
400Fix the request body or parameters
401Refresh or replace the authentication token
403Check permissions — the action may not be allowed in the current state
404Verify the resource ID exists
409Resolve the conflict — typically by using the existing resource

Example: Retry with Backoff

async function apiCall(url: string, options: RequestInit, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.ok || response.status === 208) return response;

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get("Retry-After") ?? "30");
      await new Promise((r) => setTimeout(r, retryAfter * 1000));
      continue;
    }

    if (response.status >= 500 && attempt < maxRetries) {
      await new Promise((r) => setTimeout(r, Math.pow(2, attempt) * 1000));
      continue;
    }

    const error = await response.json();
    throw new ApiError(error.error_code, error.detail, error.trace_id);
  }
}

SIS Error Codes

For error codes from the Sumvin Identity Service (token exchange, revocation), see the SIS Error Reference.