{ "openapi": "3.1.0", "info": { "title": "Deposit Service API", "version": "1.0.0", "description": "Cross-chain deposit processing service with automatic token bridging and gas sponsorship" }, "servers": [ { "url": "https://v1.orchestrator.rhinestone.dev/deposit-processor" } ], "components": { "schemas": { "ChainsResponse": { "type": "object", "additionalProperties": { "type": "object", "properties": { "name": { "type": "string" }, "testnet": { "type": "boolean" }, "deposit": { "type": "boolean" }, "destination": { "type": "boolean" }, "supportedTokens": { "anyOf": [ { "type": "string", "enum": [ "all" ] }, { "type": "array", "items": { "type": "object", "properties": { "symbol": { "type": "string" }, "address": { "type": "string" }, "decimals": { "type": "number" } }, "required": [ "symbol", "address", "decimals" ] } } ] } }, "required": [ "name", "testnet", "deposit", "destination", "supportedTokens" ] } }, "CheckResponse": { "type": "object", "properties": { "isRegistered": { "type": "boolean", "description": "Whether the EVM account is registered. EVM-scoped (legacy): a Solana/Tron-only account reads `false` here. Use `sources` for per-chain registration across all namespaces." }, "targetChain": { "type": "string" }, "targetToken": { "type": "string" }, "recipient": { "type": "string" }, "sourceChains": { "type": "array", "items": { "type": "string" } }, "outputTokenRules": { "type": "array", "items": { "$ref": "#/components/schemas/OutputTokenRule" } }, "rejectUnmapped": { "type": "boolean" }, "sources": { "type": "array", "items": { "type": "object", "properties": { "chain": { "type": "string" }, "depositAddress": { "type": "string" } }, "required": [ "chain", "depositAddress" ] }, "description": "Every chain this account can receive deposits from — CAIP-2 id + deposit address — uniform across EVM, Solana, and Tron. A chain is present iff the account is registered for it (the canonical per-source registration signal); absence means not registered. EVM chains share the account address; Solana/Tron carry their own. Always present (may be empty)." } }, "required": [ "isRegistered", "sources" ] }, "OutputTokenRule": { "type": "object", "properties": { "match": { "$ref": "#/components/schemas/OutputTokenRuleMatch" }, "outputToken": { "type": "string", "minLength": 1 } }, "required": [ "match", "outputToken" ], "description": "Destination token routing rule. Matches deposits by source token attributes and selects the target-chain output token.", "example": { "match": { "symbol": "USDC" }, "outputToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" } }, "OutputTokenRuleMatch": { "type": "object", "properties": { "chain": { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$", "description": "CAIP-2 chain identifier (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "token": { "type": "string", "minLength": 1 }, "symbol": { "type": "string" } }, "description": "Source-token match criteria. Rules may match by source chain, source token address, source symbol, or a combination.", "example": { "chain": "eip155:10", "symbol": "USDC" } }, "ErrorResponse": { "type": "object", "properties": { "error": { "type": "string" }, "details": { "type": "array", "items": { "type": "object", "properties": { "message": { "type": "string" }, "path": { "type": "array", "items": { "anyOf": [ { "type": "string" }, { "type": "number" } ] } }, "code": { "type": "string" } }, "required": [ "message" ] } } }, "required": [ "error" ] }, "UnsupportedFactoryResponse": { "type": "object", "properties": { "error": { "type": "string" }, "code": { "type": "string", "enum": [ "UNSUPPORTED_ACCOUNT_FACTORY" ] } }, "required": [ "error", "code" ] }, "SetupResponse": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] }, "SetupRequestBody": { "type": "object", "properties": { "params": { "$ref": "#/components/schemas/ClientInput" } }, "required": [ "params" ] }, "ClientInput": { "type": "object", "properties": { "webhookUrl": { "type": [ "string", "null" ], "format": "uri" }, "webhookSecret": { "type": [ "string", "null" ] }, "sponsorship": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/ChainSponsorship" } }, "depositWhitelist": { "$ref": "#/components/schemas/DepositWhitelist" }, "maxPriceDeviationBps": { "type": [ "integer", "null" ], "minimum": 0, "maximum": 10000, "description": "Maximum allowed price deviation in basis points for stablecoin-to-stablecoin bridges. Defaults to 200 (2%) if not set.", "example": 200 }, "minDepositUsd": { "type": [ "number", "null" ], "minimum": 0, "description": "Minimum deposit value in USD. Deposits priced below this are rejected and the client is notified via deposit-rejected. Applies to all tokens and chains.", "example": 1 }, "appFees": { "$ref": "#/components/schemas/AppFees" } } }, "ChainSponsorship": { "type": "object", "properties": { "gas": { "type": "string", "enum": [ "all", "none", "deployed" ], "description": "Gas sponsorship mode", "example": "all" }, "swap": { "type": "string", "enum": [ "all", "none" ], "description": "Fee sponsorship mode", "example": "all" }, "bridging": { "type": "string", "enum": [ "all", "none" ], "description": "Fee sponsorship mode", "example": "all" }, "protocolFee": { "type": "string", "enum": [ "all", "none" ], "description": "Fee sponsorship mode", "example": "all" } } }, "DepositWhitelist": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "object", "properties": { "token": { "type": "string", "minLength": 1 }, "minAmount": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "maxAmount": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" } }, "required": [ "token" ] } }, "description": "Per-source-chain deposit allowlist keyed by CAIP-2 chain identifiers (for example \"eip155:8453\"). Each key maps to allowed source tokens and optional min/max amount limits in raw token units.", "example": { "eip155:8453": [ { "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "minAmount": "1000000", "maxAmount": "5000000000" } ] } }, "AppFees": { "type": [ "object", "null" ], "properties": { "feeBps": { "type": "integer", "minimum": 0, "maximum": 10000 }, "tokens": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "object", "properties": { "token": { "type": "string", "minLength": 1 }, "feeBps": { "type": "integer", "minimum": 0, "maximum": 10000 } }, "required": [ "token", "feeBps" ] } } } }, "description": "Project app-fee settings. A source chain+token rate overrides feeBps; unmatched source assets use feeBps or 0 when omitted.", "example": { "feeBps": 100, "tokens": { "eip155:8453": [ { "token": "0x4200000000000000000000000000000000000006", "feeBps": 200 } ] } } }, "GetSetupResponse": { "type": "object", "properties": { "webhookUrl": { "type": "string" }, "hasWebhookSecret": { "type": "boolean" }, "sponsorship": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/ChainSponsorship" } }, "depositWhitelist": { "type": "object", "additionalProperties": { "type": "object", "additionalProperties": { "type": "object", "properties": { "minAmount": { "type": "string" }, "maxAmount": { "type": "string" } } } }, "description": "Per-source-chain deposit allowlist keyed by CAIP-2 chain identifiers, each mapping allowed tokens to optional raw-unit min/max limits." }, "maxPriceDeviationBps": { "type": "number" }, "minDepositUsd": { "type": "number" }, "appFees": { "type": "object", "properties": { "feeBps": { "type": "integer", "minimum": 0, "maximum": 10000 }, "tokens": { "type": "object", "additionalProperties": { "type": "object", "additionalProperties": { "type": "integer", "minimum": 0, "maximum": 10000 } } } } } }, "required": [ "hasWebhookSecret", "maxPriceDeviationBps" ] }, "RegisterResponse": { "type": "object", "properties": { "evmDepositAddress": { "type": "string" }, "solanaDepositAddress": { "type": "string" }, "tronDepositAddress": { "type": "string" } }, "required": [ "evmDepositAddress" ] }, "RegisterRequestBody": { "type": "object", "properties": { "account": { "$ref": "#/components/schemas/AccountInput" } }, "required": [ "account" ] }, "AccountInput": { "type": "object", "properties": { "address": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "accountParams": { "$ref": "#/components/schemas/AccountParams" }, "target": { "$ref": "#/components/schemas/Target" } }, "required": [ "address", "accountParams", "target" ] }, "AccountParams": { "type": "object", "properties": { "factory": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "factoryData": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" }, "sessionDetails": { "$ref": "#/components/schemas/EnableSessionDetails" } }, "required": [ "factory", "factoryData", "sessionDetails" ] }, "EnableSessionDetails": { "type": "object", "properties": { "hashesAndChainIds": { "type": "array", "items": { "type": "object", "properties": { "chainId": { "type": "integer", "exclusiveMinimum": 0, "description": "Positive integer", "example": 1 }, "sessionDigest": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "chainId", "sessionDigest" ] } }, "signature": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "hashesAndChainIds", "signature" ] }, "Target": { "type": "object", "properties": { "recipient": { "type": "string" }, "chain": { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$", "description": "CAIP-2 chain identifier (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "token": { "type": "string", "minLength": 1 }, "outputTokenRules": { "type": "array", "items": { "$ref": "#/components/schemas/OutputTokenRule" } }, "rejectUnmapped": { "type": "boolean" }, "postBridgeActions": {} }, "required": [ "chain", "token" ], "description": "Destination target configuration. `chain` must be a CAIP-2 chain identifier such as \"eip155:8453\" or \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\". `outputTokenRules` select the final target token per source token; `rejectUnmapped` ignores deposits with no matching rule.", "example": { "chain": "eip155:8453", "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "outputTokenRules": [ { "match": { "symbol": "USDC" }, "outputToken": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }, { "match": { "chain": "eip155:10", "symbol": "ETH" }, "outputToken": "0x0000000000000000000000000000000000000000" } ], "rejectUnmapped": true } }, "DepositAddressesResponse": { "type": "object", "properties": { "evmDepositAddress": { "type": "string" }, "solanaDepositAddress": { "type": "string" }, "tronDepositAddress": { "type": "string" } }, "required": [ "evmDepositAddress" ] }, "SessionResponse": { "type": "object", "properties": { "message": { "type": "string" } }, "required": [ "message" ] }, "SessionRequestBody": { "type": "object", "properties": { "sessionDetails": { "$ref": "#/components/schemas/EnableSessionDetails" } }, "required": [ "sessionDetails" ] }, "TokenAccountResponse": { "type": "object", "properties": { "ataAddress": { "type": "string" }, "created": { "type": "boolean" }, "txSignature": { "type": "string" } }, "required": [ "ataAddress", "created" ] }, "TokenAccountRequestBody": { "type": "object", "properties": { "mint": { "type": "string", "description": "Base58-encoded SPL token mint to create the Associated Token Account for", "example": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" } }, "required": [ "mint" ] }, "RetryDepositResponse": { "type": "object", "properties": { "message": { "type": "string" }, "deposits": { "type": "array", "items": { "type": "object", "properties": { "txHash": { "type": "string" }, "chain": { "type": "string" } }, "required": [ "txHash", "chain" ] } } }, "required": [ "message", "deposits" ] }, "RetryDepositRequestBody": { "type": "object", "properties": { "address": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" } }, "required": [ "address" ] }, "RefundDepositResponse": { "type": "object", "properties": { "message": { "type": "string" }, "transactionHash": { "type": "string" }, "amount": { "type": "string" } }, "required": [ "message", "transactionHash", "amount" ] }, "RefundDepositRequestBody": { "type": "object", "properties": { "chain": { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$", "description": "CAIP-2 chain identifier of the deposit (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "txHash": { "type": "string", "minLength": 1, "description": "Source transaction hash of the stuck deposit", "example": "0xabc123..." }, "account": { "type": "string", "minLength": 1, "description": "Managed account address that received the deposit (EVM address or Solana public key)", "example": "0xde0fdf9c06b404cc5e20543cb84cac9067102f19" }, "token": { "type": "string", "minLength": 1, "description": "Source token address. Use the zero address (0x000…000) for native transfers.", "example": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" }, "recipient": { "type": "string", "minLength": 1, "description": "Address to receive the refunded tokens (EVM address or Solana public key)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" } }, "required": [ "chain", "txHash", "account", "token", "recipient" ] }, "RecoverDepositErrorResponse": { "type": "object", "properties": { "error": { "type": "string" }, "code": { "type": "string", "enum": [ "DEPOSIT_NOT_RECOVERABLE", "RECOVERY_UNSUPPORTED", "SIGNATURE_EXPIRED", "SIGNATURE_INVALID", "VERIFICATION_UNAVAILABLE", "REFUND_RECONCILIATION_REQUIRED", "REFUND_FAILED" ] } }, "required": [ "error", "code" ] }, "RecoverDepositRequestBody": { "type": "object", "properties": { "chain": { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$", "description": "CAIP-2 chain identifier of the deposit (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "txHash": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Source transaction hash of the failed/rejected deposit", "example": "0xabc123..." }, "account": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Deposit smart account that received the funds", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "token": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Source token address. Use the zero address for native transfers.", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "recipient": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Address to receive the recovered tokens on the source chain", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "deadline": { "type": "integer", "exclusiveMinimum": 0, "description": "Unix timestamp (seconds) after which the signature is no longer valid", "example": 1800000000 }, "signature": { "type": "string", "pattern": "^0x[a-fA-F0-9]{130}$", "description": "Raw 65-byte ECDSA signature by the account owner over the RecoverDeposit typed data", "example": "0x1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" } }, "required": [ "chain", "txHash", "account", "token", "recipient", "deadline", "signature" ] }, "ListDepositsResponse": { "type": "object", "properties": { "deposits": { "type": "array", "items": { "$ref": "#/components/schemas/DepositListItem" } }, "nextCursor": { "type": [ "string", "null" ] } }, "required": [ "deposits", "nextCursor" ] }, "DepositListItem": { "type": "object", "properties": { "id": { "type": "string", "description": "Deposit id. Pass to GET /deposits/{id}/quotes.", "example": "12345" }, "chain": { "type": "string" }, "txHash": { "type": "string" }, "token": { "type": "string" }, "amount": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "sender": { "type": "string" }, "recipient": { "type": "string", "description": "Destination-chain address that receives the funds. Falls back to the smart account for EVM/HyperCore/Tron when no distinct recipient is configured; for Solana it is the EVM recipient, never the internal swig." }, "depositAddress": { "type": "string", "description": "Source-chain address that received the deposit (EVM smart account, Solana wallet PDA, or Tron deposit address)." }, "targetChain": { "type": "string" }, "targetToken": { "type": "string" }, "status": { "type": "string", "enum": [ "pending", "processing", "completed", "failed", "rejected", "ignored", "expecting_refund", "refunded", "delayed", "awaiting_sweep", "reconciliation_required" ] }, "sourceTxHash": { "type": [ "string", "null" ] }, "destinationTxHash": { "type": [ "string", "null" ] }, "sourceAmount": { "type": [ "string", "null" ], "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "destinationAmount": { "type": [ "string", "null" ], "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "createdAt": { "type": "string" }, "completedAt": { "type": [ "string", "null" ] }, "errorCode": { "type": [ "string", "null" ] }, "retryable": { "type": "boolean" }, "isSpam": { "type": "boolean" } }, "required": [ "id", "chain", "txHash", "token", "amount", "sender", "recipient", "depositAddress", "targetChain", "targetToken", "status", "sourceTxHash", "destinationTxHash", "sourceAmount", "destinationAmount", "createdAt", "completedAt", "errorCode", "retryable", "isSpam" ] }, "DepositQuotesResponse": { "type": "object", "properties": { "count": { "type": "integer" }, "items": { "type": "array", "items": { "$ref": "#/components/schemas/DepositQuoteItem" } } }, "required": [ "count", "items" ] }, "DepositQuoteItem": { "type": "object", "properties": { "intentId": { "type": "string" }, "settlementLayer": { "type": "string" }, "bridgeProvider": { "type": [ "string", "null" ] }, "rank": { "type": "integer" }, "outcome": { "type": "string", "enum": [ "quoted", "attempted", "succeeded", "failed", "skipped" ] }, "quote": {}, "errorCode": { "type": [ "string", "null" ] }, "errorMessage": { "type": [ "string", "null" ] }, "attemptedAt": { "type": [ "string", "null" ] }, "completedAt": { "type": [ "string", "null" ] }, "createdAt": { "type": "string" } }, "required": [ "intentId", "settlementLayer", "bridgeProvider", "rank", "outcome", "errorCode", "errorMessage", "attemptedAt", "completedAt", "createdAt" ] }, "QuotePreviewResponse": { "type": "object", "properties": { "settlementLayer": { "type": "string" }, "expiresAt": { "type": "integer" }, "estimatedFillTimeSeconds": { "type": "integer", "minimum": 0 }, "fees": { "type": "object", "properties": { "total": { "type": "object", "properties": { "usd": { "type": "number" } }, "required": [ "usd" ] }, "totalUsd": { "type": "number" }, "breakdown": { "type": "object", "properties": { "gas": { "$ref": "#/components/schemas/PreviewFeeLine" }, "bridge": { "$ref": "#/components/schemas/PreviewFeeLine" }, "swap": { "$ref": "#/components/schemas/PreviewFeeLine" }, "app": { "$ref": "#/components/schemas/PreviewFeeLine" }, "protocol": { "$ref": "#/components/schemas/PreviewFeeLine" }, "sponsorSurcharge": { "$ref": "#/components/schemas/PreviewFeeLine" } }, "required": [ "gas", "bridge", "swap", "app", "protocol", "sponsorSurcharge" ], "additionalProperties": { "$ref": "#/components/schemas/PreviewFeeLine" } } }, "required": [ "total", "breakdown" ] }, "output": { "type": "object", "properties": { "token": { "type": "string" }, "amount": { "type": "string" }, "symbol": { "type": [ "string", "null" ] }, "decimals": { "type": [ "integer", "null" ] } }, "required": [ "token", "amount", "symbol", "decimals" ] } }, "required": [ "settlementLayer", "expiresAt", "estimatedFillTimeSeconds", "fees", "output" ] }, "PreviewFeeLine": { "type": "object", "properties": { "usd": { "type": "number" }, "sponsored": { "type": "boolean" }, "label": { "type": "string" }, "internal": { "type": "boolean" } }, "required": [ "usd", "sponsored" ] }, "QuotePreviewRequest": { "type": "object", "properties": { "account": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "sourceChainId": { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$", "description": "CAIP-2 chain identifier (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "sourceToken": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "amount": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" } }, "required": [ "account", "sourceChainId", "sourceToken", "amount" ] }, "DepositStatsResponse": { "type": "object", "properties": { "period": { "type": "string", "enum": [ "24h", "7d", "30d" ], "description": "Rolling time window for aggregated stats", "example": "7d" }, "totalDeposits": { "type": "integer", "minimum": 0 }, "uniqueUsers": { "type": "integer", "minimum": 0 }, "volumeUsd": { "type": "string" } }, "required": [ "period", "totalDeposits", "uniqueUsers", "volumeUsd" ] }, "ManagedRegisterResponse": { "type": "object", "properties": { "evmDepositAddress": { "type": "string" }, "solanaDepositAddress": { "type": "string" }, "tronDepositAddress": { "type": "string" } }, "required": [ "evmDepositAddress" ] }, "ManagedRegisterRequestBody": { "type": "object", "properties": { "account": { "$ref": "#/components/schemas/ManagedAccountInput" } }, "required": [ "account" ] }, "ManagedAccountInput": { "type": "object", "properties": { "salt": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" }, "target": { "$ref": "#/components/schemas/ManagedTarget" } }, "required": [ "salt", "target" ] }, "ManagedTarget": { "type": "object", "properties": { "recipient": { "type": "string", "minLength": 1 }, "chain": { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$", "description": "CAIP-2 chain identifier (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "token": { "type": "string", "minLength": 1 }, "outputTokenRules": { "type": "array", "items": { "$ref": "#/components/schemas/OutputTokenRule" } }, "rejectUnmapped": { "type": "boolean" }, "postBridgeActions": {} }, "required": [ "recipient", "chain", "token" ], "description": "Destination target configuration for managed accounts. `recipient` is required and specifies the address that receives the final tokens." }, "SetupAccountResponse": { "type": "object", "properties": { "smartAccount": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "isRegistered": { "type": "boolean" }, "targetChain": { "type": "string" }, "targetToken": { "type": "string" }, "needsRegistration": { "type": "boolean" }, "solanaDepositAddress": { "type": "string" }, "accountParams": { "type": "object", "properties": { "factory": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "factoryData": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "factory", "factoryData" ] }, "sessionDetailsUnsigned": { "type": "object", "properties": { "hashesAndChainIds": { "type": "array", "items": { "type": "object", "properties": { "chainId": { "type": "string" }, "sessionDigest": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "chainId", "sessionDigest" ] } }, "data": { "type": "object", "additionalProperties": {} } }, "required": [ "hashesAndChainIds", "data" ] } }, "required": [ "smartAccount", "isRegistered", "needsRegistration" ] }, "SetupAccountRequestBody": { "type": "object", "properties": { "ownerAddress": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "sessionOwnerAddress": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "targetToken": { "type": "string", "minLength": 1 }, "targetChain": { "anyOf": [ { "type": "integer", "exclusiveMinimum": 0 }, { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$" } ], "description": "Chain identifier as a positive integer or CAIP-2 string (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "recipient": { "type": "string" }, "outputTokenRules": { "type": "array", "items": { "$ref": "#/components/schemas/OutputTokenRule" } }, "rejectUnmapped": { "type": "boolean" }, "postBridgeActions": {}, "signerAddress": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "sessionChainIds": { "type": "array", "items": { "type": "integer", "exclusiveMinimum": 0 } }, "forceRegister": { "type": "boolean" } }, "required": [ "ownerAddress", "sessionOwnerAddress", "targetToken", "targetChain" ] }, "PortfolioResponse": { "type": "object", "properties": { "tokens": { "type": "array", "items": { "type": "object", "properties": { "chainId": { "anyOf": [ { "type": "number" }, { "type": "string" } ] }, "address": { "type": "string" }, "symbol": { "type": "string" }, "name": { "type": "string" }, "decimals": { "type": "number" }, "balance": { "type": "string" }, "balanceUsd": { "type": "number" } }, "required": [ "chainId", "symbol", "name", "decimals", "balance", "balanceUsd" ] } }, "totalUsd": { "type": "number" }, "truncated": { "type": "boolean" } }, "required": [ "tokens", "totalUsd" ] }, "PositionsResponse": { "type": "object", "properties": { "positions": { "type": "array", "items": { "type": "object", "properties": { "venue": { "type": "string", "enum": [ "aave" ] }, "kind": { "type": "string", "enum": [ "lending" ] }, "market": { "type": "object", "properties": { "address": { "type": "string" }, "name": { "type": "string" } }, "required": [ "address", "name" ], "description": "Positions are keyed by market, not chain — Ethereum alone hosts four Aave v3 markets with distinct pools and risk params." }, "chain": { "type": "string", "description": "CAIP-2 chain id", "example": "eip155:8453" }, "asset": { "type": "object", "properties": { "address": { "type": "string" }, "symbol": { "type": "string" }, "decimals": { "type": "number" } }, "required": [ "address", "symbol", "decimals" ] }, "amount": { "type": "string", "description": "Supplied balance in base units, accrued interest included" }, "usdValue": { "type": "number" }, "apy": { "type": "number" }, "isCollateral": { "type": "boolean" }, "maxWithdrawable": { "type": "string", "description": "Largest amount withdrawable right now, in base units. Capped so the withdraw cannot be rejected on-chain." }, "withdrawableUsd": { "type": "number", "description": "USD value of `maxWithdrawable` — what would actually reach the deposit address, as opposed to `usdValue`, which prices the whole holding. Display this next to an amount you offer: it is also the figure this project's deposit floor is judged against, and re-deriving it from `usdValue` needs the amount ratio taken in integer space to survive an 18-decimal balance.", "example": 40.02 }, "isFullExit": { "type": "boolean", "description": "True when the entire supplied balance can leave in one transaction" }, "constraints": { "type": "array", "items": { "type": "string", "enum": [ "health_factor", "frozen_reserve", "nothing_supplied", "paused_reserve", "ltv_validation", "available_liquidity", "below_deposit_floor", "deposit_not_whitelisted" ], "description": "Why the position cannot be fully migrated. Venue reasons (`health_factor`, `paused_reserve`, `ltv_validation`, `available_liquidity`) cap `maxWithdrawable` itself. `frozen_reserve` is advisory — Aave still permits withdrawing from a frozen reserve. `below_deposit_floor` and `deposit_not_whitelisted` mean the venue would pay out but this project's deposit policy would then reject the proceeds, so they do not reduce `maxWithdrawable`." } } }, "required": [ "venue", "kind", "market", "chain", "asset", "amount", "usdValue", "apy", "isCollateral", "maxWithdrawable", "withdrawableUsd", "isFullExit", "constraints" ] } }, "totalUsd": { "type": "number" }, "minDepositUsd": { "type": "number", "description": "The USD floor the withdrawn proceeds must clear for this project, resolved from the platform minimum and the project's own `minDepositUsd`. Proceeds below it are rejected on ingest after the withdrawal has already happened.", "example": 0.04 }, "failures": { "type": "array", "items": { "type": "object", "properties": { "venue": { "type": "string" }, "reason": { "type": "string" } }, "required": [ "venue", "reason" ] }, "description": "Present only when a venue could not be reached, so an empty `positions` list can be told apart from a failed lookup." } }, "required": [ "positions", "totalUsd", "minDepositUsd" ] }, "PrepareUnwindResponse": { "type": "object", "properties": { "transaction": { "type": "object", "properties": { "to": { "type": "string" }, "data": { "type": "string" }, "value": { "type": "string" }, "chainId": { "type": "number" } }, "required": [ "to", "data", "value", "chainId" ], "description": "Unsigned transaction for the holding EOA to sign and send. The backend never executes it — the EOA holds the aTokens, so only it can authorise the withdraw." }, "amount": { "type": "string", "description": "Base units the transaction will withdraw" }, "isFullExit": { "type": "boolean", "description": "True when the whole position is being withdrawn, in which case the calldata uses the max-uint sentinel so interest accrued before the transaction lands is swept too." }, "recipient": { "type": "string", "description": "The deposit address the proceeds are sent to, resolved from the registered account. Echoed so it is auditable." }, "constraints": { "type": "array", "items": { "type": "string" }, "description": "Why the amount is below the supplied balance, if it is. Empty for an unconstrained full exit." } }, "required": [ "transaction", "amount", "isFullExit", "recipient", "constraints" ] }, "PrepareUnwindRequestBody": { "type": "object", "properties": { "account": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The registered deposit account the proceeds go to. The recipient is resolved from this server-side; it is never taken from the request directly." }, "market": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The Aave market's Pool address, as returned in a position's `market.address`. Required rather than inferred, because a chain can host several markets." }, "chainId": { "type": "integer", "exclusiveMinimum": 0, "example": 8453 }, "asset": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The supplied underlying token to withdraw" }, "amount": { "type": "string", "pattern": "^\\d+$", "description": "Base units to withdraw. Omit for the largest amount currently permitted. An amount above that maximum is rejected rather than silently reduced.", "example": "1000000000000000000" } }, "required": [ "account", "market", "chainId", "asset" ] }, "LiquidityResponse": { "type": "object", "properties": { "hasLiquidity": { "type": "boolean" }, "symbol": { "type": "string" }, "decimals": { "type": "number" }, "unlimited": { "type": "boolean" }, "maxAmount": { "type": [ "string", "null" ] } }, "required": [ "hasLiquidity", "symbol", "decimals", "unlimited", "maxAmount" ] }, "PricesResponse": { "type": "object", "properties": { "prices": { "type": "object", "additionalProperties": { "type": "number" }, "description": "USD unit price keyed by uppercased token symbol (for `symbols`) or by CAIP-2 token id (for `addresses`)", "example": { "SOL": 168.42 } } }, "required": [ "prices" ] }, "QrTokensResponse": { "type": "object", "properties": { "tokens": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "object", "properties": { "symbol": { "type": "string", "example": "USDC" }, "address": { "type": "string", "example": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" }, "decimals": { "type": "integer", "minimum": 0, "example": 6 } }, "required": [ "symbol", "address", "decimals" ] } }, "description": "Keyed by EVM chain id as a decimal string, plus \"solana\" and \"hypercore\". An empty array means the deposit whitelist disallows this chain entirely — clients should hide it rather than offer a chain with nothing to send, and it is reported even for chains this shortlist does not curate. An absent chain carries no opinion (it is allowed, but no shortlist is curated for it) and clients should keep whatever default they have for it; the two are not interchangeable." } }, "required": [ "tokens" ] }, "WithdrawResponse": { "type": "object", "properties": { "message": { "type": "string" }, "txHash": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "message" ] }, "WithdrawRequestBody": { "type": "object", "properties": { "chainId": { "anyOf": [ { "type": "integer", "exclusiveMinimum": 0 }, { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$" } ], "description": "Chain identifier as a positive integer or CAIP-2 string (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "safeAddress": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "safeTransaction": { "$ref": "#/components/schemas/SafeTransaction" }, "signature": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "chainId", "safeAddress", "safeTransaction", "signature" ] }, "SafeTransaction": { "type": "object", "properties": { "to": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "value": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "data": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" }, "operation": { "anyOf": [ { "type": "number", "enum": [ 0 ] }, { "type": "number", "enum": [ 1 ] } ] }, "safeTxGas": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "baseGas": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "gasPrice": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "gasToken": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "refundReceiver": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "nonce": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" } }, "required": [ "to", "value", "data", "operation", "safeTxGas", "baseGas", "gasPrice", "gasToken", "refundReceiver", "nonce" ] }, "PolymarketWithdrawResponse": { "type": "object", "properties": { "message": { "type": "string" }, "txHash": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "message", "txHash" ] }, "PolymarketWithdrawRequestBody": { "type": "object", "properties": { "depositWallet": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "owner": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "nonce": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "deadline": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "calls": { "type": "array", "items": { "$ref": "#/components/schemas/PolymarketCall" }, "minItems": 1 }, "signature": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "depositWallet", "owner", "nonce", "deadline", "calls", "signature" ] }, "PolymarketCall": { "type": "object", "properties": { "target": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "value": { "type": "string", "pattern": "^\\d+$", "description": "Numeric string representing a bigint value", "example": "1000000000000000000" }, "data": { "type": "string", "pattern": "^0x[a-fA-F0-9]+$", "description": "Hex-encoded string (0x followed by hex characters)", "example": "0x1234abcd" } }, "required": [ "target", "value", "data" ] }, "ListWebhookEventsResponse": { "type": "object", "properties": { "events": { "type": "array", "items": { "$ref": "#/components/schemas/WebhookEvent" } }, "nextCursor": { "type": [ "string", "null" ] } }, "required": [ "events", "nextCursor" ] }, "WebhookEvent": { "type": "object", "properties": { "eventId": { "type": "string" }, "type": { "type": "string" }, "time": { "type": "string" }, "status": { "type": "string", "enum": [ "pending", "delivered", "failed" ] }, "attempts": { "type": "number" }, "payload": {}, "depositId": { "type": [ "string", "null" ] }, "deliveredAt": { "type": [ "string", "null" ] } }, "required": [ "eventId", "type", "time", "status", "attempts", "depositId", "deliveredAt" ] }, "ResendWebhookEventResponse": { "type": "object", "properties": { "message": { "type": "string" }, "eventId": { "type": "string" }, "status": { "type": "string", "enum": [ "pending", "delivered", "failed" ] }, "attempts": { "type": "number" } }, "required": [ "message", "eventId", "status", "attempts" ] }, "TestWebhookResponse": { "type": "object", "properties": { "message": { "type": "string" }, "eventId": { "type": "string" } }, "required": [ "message", "eventId" ] }, "TestWebhookRequestBody": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "deposit-received", "bridge-started", "bridge-delayed", "bridge-complete", "bridge-failed", "deposit-rejected", "deposit-delayed", "deposit-refunded", "onramp-order", "error" ], "description": "Which webhook type to simulate", "example": "bridge-started" } }, "required": [ "type" ] }, "SwappedUrlResponse": { "type": "object", "properties": { "ok": { "type": "boolean", "enum": [ true ] }, "url": { "type": "string" }, "currencyCode": { "type": "string" }, "sandbox": { "type": "boolean" }, "externalCustomerId": { "type": "string" }, "expiresAt": { "type": "string" }, "exchangeFeeBps": { "type": "integer", "minimum": 0 } }, "required": [ "ok", "url", "currencyCode", "sandbox", "externalCustomerId", "expiresAt" ] }, "SwappedWidgetUrlRequestBody": { "type": "object", "properties": { "smartAccount": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "email": { "type": "string" }, "baseCountry": { "type": "string", "pattern": "^[A-Z]{2}$", "description": "ISO-3166-1 alpha-2 country code", "example": "US" }, "baseCurrencyCode": { "type": "string", "pattern": "^[A-Z]{3,4}$", "description": "ISO fiat currency code", "example": "USD" }, "baseCurrencyAmount": { "type": "number", "exclusiveMinimum": 0 }, "locale": { "type": "string" }, "method": { "type": "string", "description": "Optional. Preselects a Swapped payment method (a `payment_group`) in the widget — e.g. \"creditcard\", \"apple-pay\", \"bank-transfer\", \"skrill\", \"pix\", \"sepa-bank-transfer\". Any Swapped-supported value is accepted and forwarded as-is; omit it to let Swapped auto-select the best method for the user based on their location and other signals. See Swapped's Get Payment Methods endpoint for the full, per-region list.", "example": "apple-pay" }, "methodSelectionSource": { "type": "string", "enum": [ "personalized", "fallback", "configured" ], "description": "How the caller obtained `method`. Use `personalized` only for a method rendered from the regional payment-method response; with a trusted `x-user-country`, this opts into strict catalog validation. `fallback`, `configured`, and omission preserve the legacy exact-method pass-through behavior.", "example": "personalized" } }, "required": [ "smartAccount" ] }, "SwappedExchangeFeeChangedResponse": { "type": "object", "properties": { "error": { "type": "string" }, "exchangeFeeBps": { "type": "integer", "minimum": 0, "maximum": 10000 } }, "required": [ "error", "exchangeFeeBps" ] }, "SwappedConnectUrlRequestBody": { "type": "object", "properties": { "smartAccount": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "baseCountry": { "type": "string", "pattern": "^[A-Z]{2}$", "description": "ISO-3166-1 alpha-2 country code", "example": "US" }, "baseCurrencyCode": { "type": "string", "pattern": "^[A-Z]{3,4}$", "description": "ISO fiat currency code", "example": "USD" }, "locale": { "type": "string" }, "connection": { "type": "string" }, "acceptedExchangeFeeBps": { "type": "integer", "minimum": 0, "maximum": 10000 } }, "required": [ "smartAccount" ] }, "SwappedPaymentMethodsResponse": { "type": "object", "properties": { "country": { "type": [ "string", "null" ], "pattern": "^[A-Z]{2}$", "description": "ISO-3166-1 alpha-2 country code", "example": "US" }, "methods": { "type": "array", "items": { "type": "object", "properties": { "method": { "type": "string" }, "label": { "type": "string" }, "iconUrl": { "type": [ "string", "null" ] }, "iconUrlLight": { "type": [ "string", "null" ] }, "minAmount": { "type": [ "number", "null" ], "minimum": 0 }, "maxAmount": { "type": [ "number", "null" ], "minimum": 0 }, "badge": { "type": [ "string", "null" ], "enum": [ "Popular" ] } }, "required": [ "method", "label", "iconUrl", "iconUrlLight", "minAmount", "maxAmount", "badge" ] } }, "recommendedMethod": { "type": [ "string", "null" ] } }, "required": [ "country", "methods", "recommendedMethod" ] }, "SwappedStatusResponse": { "type": "object", "properties": { "ok": { "type": "boolean" }, "reason": { "type": "string" }, "orderId": { "type": "string" }, "status": { "type": [ "string", "null" ] }, "orderCrypto": { "type": [ "string", "null" ] }, "orderCryptoAmount": { "type": [ "string", "null" ] }, "transactionId": { "type": [ "string", "null" ] }, "receivedAt": { "type": [ "string", "null" ] }, "paidAmountUsd": { "type": [ "number", "null" ] }, "paidAmountEur": { "type": [ "number", "null" ] }, "onrampFeeUsd": { "type": [ "number", "null" ] }, "paymentMethod": { "type": [ "string", "null" ] } }, "required": [ "ok" ] }, "SwappedConnectExchangesResponse": { "type": "object", "properties": { "exchanges": { "type": "array", "items": { "type": "object", "properties": { "connection": { "type": "string" }, "name": { "type": "string" }, "logoUrl": { "type": [ "string", "null" ] } }, "required": [ "connection", "name", "logoUrl" ] } }, "fetchedAt": { "type": "string" }, "expiresAt": { "type": "string" }, "stale": { "type": "boolean" }, "exchangeFeeBps": { "type": "integer", "minimum": 0 } }, "required": [ "exchanges", "fetchedAt", "expiresAt", "stale" ] } }, "parameters": {} }, "paths": { "/chains": { "get": { "tags": [ "Utilities" ], "summary": "List supported chains and tokens", "description": "Returns all chains supported by the deposit service, with their tokens and whether they support deposits, bridging destinations, or both", "responses": { "200": { "description": "Supported chains with their tokens", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChainsResponse" } } } } } } }, "/check/{address}": { "get": { "tags": [ "Accounts" ], "summary": "Check if account is registered", "description": "Check if an account is registered and return its target chain and token if registered", "parameters": [ { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "Ethereum address (0x followed by 40 hex characters)", "name": "address", "in": "path" } ], "responses": { "200": { "description": "Account registration status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CheckResponse" } } } }, "400": { "description": "Invalid address format", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "Account was registered with a factory the service does not support", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UnsupportedFactoryResponse" } } } } } } }, "/setup": { "post": { "tags": [ "Clients" ], "summary": "Configure client settings", "description": "Configure webhook URL, secret, sponsorship rules, and source-token whitelist rules for a client. Deposit whitelist keys must use CAIP-2 chain identifiers (for example \"eip155:8453\").", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetupRequestBody" } } } }, "responses": { "200": { "description": "Client updated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetupResponse" } } } }, "400": { "description": "Invalid parameters or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } }, "get": { "tags": [ "Clients" ], "summary": "Read client settings", "description": "Returns the stored client configuration — webhook URL/secret, sponsorship rules, source-token whitelist, and price-deviation guard — for the authenticated project.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "responses": { "200": { "description": "Client configuration", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GetSetupResponse" } } } }, "401": { "description": "Authentication required", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/register": { "post": { "tags": [ "Accounts" ], "summary": "Register a new account", "description": "Register a new account with factory, factory data, session details, and target. `target.chain` must use a CAIP-2 chain identifier (for example \"eip155:8453\").", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterRequestBody" } } } }, "responses": { "200": { "description": "Account registered successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RegisterResponse" } } } }, "400": { "description": "Invalid account data or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Failed to register with Alchemy", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Webhook provider enrollment is rate limited; retry after the number of seconds in the Retry-After header", "headers": { "Retry-After": { "description": "Seconds to wait before retrying the registration", "schema": { "type": "integer" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/account/{address}/deposit-addresses": { "post": { "tags": [ "Accounts" ], "summary": "Fetch or backfill deposit addresses for a registered account", "description": "Return the EVM, Solana, and Tron deposit addresses for an already-registered account. Missing Solana and Tron deposit addresses are backfilled on first call (derivation and Rhino.fi mint as needed) without modifying the account config (session details, target). Idempotent on repeat.", "parameters": [ { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "Ethereum address (0x followed by 40 hex characters)", "name": "address", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "Deposit addresses for the account", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepositAddressesResponse" } } } }, "400": { "description": "Invalid API key or address", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "Unauthorized - API key does not belong to the client that registered the account", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Account not registered", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Failed to backfill deposit addresses", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/account/{address}/session": { "post": { "tags": [ "Accounts" ], "summary": "Add session details to account", "description": "Add session details (chain IDs, session digests, and signature) to an existing account", "parameters": [ { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "Ethereum address (0x followed by 40 hex characters)", "name": "address", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SessionRequestBody" } } } }, "responses": { "200": { "description": "Session added successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SessionResponse" } } } }, "400": { "description": "Invalid request or account not registered", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "Unauthorized - API key does not belong to the client that registered the account", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/account/{address}/token-accounts": { "post": { "tags": [ "Accounts" ], "summary": "Create a Solana token account (ATA) for an account", "description": "Create the Solana Associated Token Account (ATA) for a registered account's Solana deposit address and an SPL mint, so transfers from senders that omit a create-ATA instruction (some CEXes) do not bounce on-chain. Allowlisted clients only. Idempotent: returns the existing ATA with created=false if it already exists. Rejects native/wrapped SOL (no ATA needed).", "parameters": [ { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "Ethereum address (0x followed by 40 hex characters)", "name": "address", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenAccountRequestBody" } } } }, "responses": { "200": { "description": "Token account exists (created now or previously)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TokenAccountResponse" } } } }, "400": { "description": "Invalid mint (bad base58, unsupported token, or SOL/WSOL)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Missing or invalid API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "Project not in the allowlist, lacks deposits:write scope, or the account is owned by a different project", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "No Solana account registered for this address", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "502": { "description": "Solana RPC or transaction submission failure", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/deposits/retry": { "post": { "tags": [ "Processing" ], "summary": "Retry failed deposits for an account", "description": "Retry all failed deposits for a given account address. Authenticate with an `x-api-key` (write scope) or a Bearer platform token; the credential must belong to the client that registered the account.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RetryDepositRequestBody" } } } }, "responses": { "200": { "description": "Deposit retries initiated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RetryDepositResponse" } } } }, "400": { "description": "Invalid request or account not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Authentication required or invalid", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "Unauthorized - credential does not belong to the client that registered the account, or API key lacks write scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/deposits/refund": { "post": { "tags": [ "Processing" ], "summary": "Refund a failed deposit", "description": "Transfer the funds from a failed deposit back to a user-provided address on the same chain. Authenticate with an `x-api-key` (write scope) or a Bearer platform token; the credential must belong to the client that registered the account.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefundDepositRequestBody" } } } }, "responses": { "200": { "description": "Deposit refunded successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefundDepositResponse" } } } }, "400": { "description": "Invalid request, deposit not found, or not eligible for refund", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Authentication required or invalid", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "Unauthorized - credential does not belong to the client that registered the account, or API key lacks write scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Refund transfer failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/deposits/recover": { "post": { "tags": [ "Processing" ], "summary": "Recover a failed deposit with an owner signature", "description": "Return a failed or rejected deposit's source-chain funds to a user-chosen recipient, authorized by the smart-account owner's EIP-712 signature (not just the API key). The server reconstructs the RecoverDeposit typed data from the stored deposit and verifies it against the account via ERC-1271/ERC-6492, then runs the same claim + transfer path as the refund endpoint. EVM Nexus accounts created by the deposit modal only. Authenticate with an `x-api-key` (write scope).", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecoverDepositRequestBody" } } } }, "responses": { "200": { "description": "Deposit recovered; funds returned on the source chain", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RefundDepositResponse" } } } }, "400": { "description": "Deposit not recoverable (DEPOSIT_NOT_RECOVERABLE), account type unsupported (RECOVERY_UNSUPPORTED), or signature expired (SIGNATURE_EXPIRED)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecoverDepositErrorResponse" } } } }, "401": { "description": "Authentication required or invalid", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks the deposits:write scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "The refund may have been submitted and is held for reconciliation (REFUND_RECONCILIATION_REQUIRED)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecoverDepositErrorResponse" } } } }, "422": { "description": "The signature does not authorize this recovery (SIGNATURE_INVALID)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecoverDepositErrorResponse" } } } }, "500": { "description": "Recovery transfer failed (REFUND_FAILED)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecoverDepositErrorResponse" } } } }, "503": { "description": "Smart-account signature verification is temporarily unavailable (VERIFICATION_UNAVAILABLE)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecoverDepositErrorResponse" } } } } } } }, "/deposits": { "get": { "tags": [ "Utilities" ], "summary": "List deposits for the authenticated client", "description": "Returns the authenticated client's deposits, newest first. Supports filtering by account, recipient, address, status, source chain, and transaction hash. The `account` filter accepts an EVM address or a Solana public key (deposit address or swig address); `address` matches the source-chain deposit address or target-chain recipient.", "parameters": [ { "schema": { "type": "string", "description": "EVM address (0x...) or Solana base58 public key", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": false, "description": "EVM address (0x...) or Solana base58 public key", "name": "account", "in": "query" }, { "schema": { "type": "string", "description": "Filter by the account's recipient address. Aggregates deposits across every smart account that resolves to the same recipient (typically the integrator's user wallet).", "example": "0x2ca6f15be9580c4f332656bedc11c35bf820d08d" }, "required": false, "description": "Filter by the account's recipient address. Aggregates deposits across every smart account that resolves to the same recipient (typically the integrator's user wallet).", "name": "recipient", "in": "query" }, { "schema": { "type": "string", "description": "Filter by the source-chain deposit address or target-chain recipient.", "example": "0x2ca6f15be9580c4f332656bedc11c35bf820d08d" }, "required": false, "description": "Filter by the source-chain deposit address or target-chain recipient.", "name": "address", "in": "query" }, { "schema": { "type": "string", "enum": [ "pending", "processing", "completed", "failed", "rejected", "ignored", "expecting_refund", "refunded", "delayed", "awaiting_sweep", "reconciliation_required" ], "description": "Filter by deposit status", "example": "failed" }, "required": false, "description": "Filter by deposit status", "name": "status", "in": "query" }, { "schema": { "type": "string", "pattern": "^[a-z0-9]+:[a-zA-Z0-9]+$", "description": "CAIP-2 chain identifier (e.g. \"eip155:8453\")", "example": "eip155:8453" }, "required": false, "description": "CAIP-2 chain identifier (e.g. \"eip155:8453\")", "name": "chain", "in": "query" }, { "schema": { "type": "string", "description": "Filter by source transaction hash (EVM 0x... or Solana base58 signature)", "example": "0xabc123..." }, "required": false, "description": "Filter by source transaction hash (EVM 0x... or Solana base58 signature)", "name": "txHash", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20, "description": "Maximum number of deposits to return", "example": 20 }, "required": false, "description": "Maximum number of deposits to return", "name": "limit", "in": "query" }, { "schema": { "type": "string", "pattern": "^\\d+$", "description": "Pagination cursor. Use the `nextCursor` returned by the previous page.", "example": "123" }, "required": false, "description": "Pagination cursor. Use the `nextCursor` returned by the previous page.", "name": "cursor", "in": "query" }, { "schema": { "type": "boolean", "description": "When true, include spam-flagged deposits (tokens with no known price). Defaults to false.", "example": false }, "required": false, "description": "When true, include spam-flagged deposits (tokens with no known price). Defaults to false.", "name": "includeSpam", "in": "query" }, { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "responses": { "200": { "description": "Client deposits", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListDepositsResponse" } } } }, "400": { "description": "Invalid query or API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Invalid or expired platform bearer token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/deposits/{id}/quotes": { "get": { "tags": [ "Utilities" ], "summary": "List candidate quotes considered for a deposit", "description": "Returns every quote the orchestrator (or Solana bridge adapter) returned for this deposit, including which one was attempted and its terminal outcome. Scoped to the caller's tenant.", "parameters": [ { "schema": { "type": "string", "pattern": "^\\d+$", "description": "Deposit id. Returned by GET /deposits.", "example": "12345" }, "required": true, "description": "Deposit id. Returned by GET /deposits.", "name": "id", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" } ], "responses": { "200": { "description": "Quotes considered for the deposit", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepositQuotesResponse" } } } }, "400": { "description": "Invalid deposit id or API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Deposit not found or not owned by the caller", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/quotes/preview": { "post": { "tags": [ "Processing" ], "summary": "Preview a bridge quote before depositing", "description": "Returns the fees and expected output for bridging `amount` of `sourceToken` from `sourceChainId` to the account's registered target, before any funds are deposited. The orchestrator quotes against the supplied amount as if the deposit wallet already held it; the result is indicative and may differ from the quote applied once a real deposit lands. EVM source chains only. Scoped to the caller's tenant.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuotePreviewRequest" } } } }, "responses": { "200": { "description": "Indicative quote for the requested route", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuotePreviewResponse" } } } }, "400": { "description": "Malformed request body or unsupported source chain", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Missing/invalid API key or expired platform bearer token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Account not found or not owned by the caller", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "422": { "description": "Route cannot be quoted (token/amount not allowed by the client whitelist, unsupported token route, no session for the source chain, or no available routes)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/deposits/stats": { "get": { "tags": [ "Utilities" ], "summary": "Aggregated deposit statistics", "description": "Returns aggregated deposit statistics (total deposits, unique depositors, and total USD volume) for the authenticated client over the requested rolling time window. Only completed deposits are counted.", "parameters": [ { "schema": { "type": "string", "enum": [ "24h", "7d", "30d" ], "description": "Rolling time window for aggregated stats", "example": "7d" }, "required": true, "description": "Rolling time window for aggregated stats", "name": "period", "in": "query" }, { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "responses": { "200": { "description": "Deposit statistics for the requested period", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DepositStatsResponse" } } } }, "400": { "description": "Invalid query or API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Invalid or expired platform bearer token", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/register-managed": { "post": { "tags": [ "Accounts" ], "summary": "Register a server-managed account", "description": "Register a server-owned smart account. Provide a salt for deterministic addressing and a target chain/token.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ManagedRegisterRequestBody" } } } }, "responses": { "200": { "description": "Managed account registered successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ManagedRegisterResponse" } } } }, "400": { "description": "Invalid parameters or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Failed to register with webhook providers", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Webhook provider enrollment is rate limited; retry after the number of seconds in the Retry-After header", "headers": { "Retry-After": { "description": "Seconds to wait before retrying the registration", "schema": { "type": "integer" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/setup-account": { "post": { "tags": [ "Accounts" ], "summary": "Prepare account for registration", "description": "Derive the Rhinestone smart account for (ownerAddress, sessionOwnerAddress), compare against the existing registration and target, and return either the Solana deposit address (if no re-registration is needed) or the unsigned session details and factory parameters the client must sign before calling /register.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetupAccountRequestBody" } } } }, "responses": { "200": { "description": "Account setup result", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SetupAccountResponse" } } } }, "400": { "description": "Invalid request or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Failed to derive account or build sessions", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/portfolio/{address}": { "get": { "tags": [ "Utilities" ], "summary": "Get a wallet portfolio", "description": "Returns a normalised token portfolio for the given address. If the address is a Solana base58 public key, the Solana portfolio is returned; otherwise the EVM portfolio is aggregated from the orchestrator's `/accounts/:address/portfolio` endpoint and priced via the price service.", "parameters": [ { "schema": { "type": "string", "description": "EVM address or Solana base58 public key", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "EVM address or Solana base58 public key", "name": "address", "in": "path" }, { "schema": { "type": "string", "description": "Comma-separated chain IDs to filter the portfolio", "example": "1,8453,42161" }, "required": false, "description": "Comma-separated chain IDs to filter the portfolio", "name": "chainIds", "in": "query" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "Wallet portfolio", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PortfolioResponse" } } } }, "400": { "description": "Invalid request or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "502": { "description": "Invalid upstream response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/positions/{address}": { "get": { "tags": [ "Utilities" ], "summary": "Get migratable DeFi positions", "description": "Returns the address's DeFi positions in one normalised shape, each carrying the largest amount that can actually be withdrawn right now. `maxWithdrawable` is capped against the venue's full withdraw validation — health factor (with a buffer above the liquidation edge), E-Mode thresholds, zero-LTV collateral, paused reserves and pool liquidity — so a client never asks a user to sign an exit the protocol would reject. Currently covers Aave v3 across every market on the deposit-enabled chains; a `failures` entry appears when a venue could not be reached, so an empty list is distinguishable from a failed lookup.", "parameters": [ { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "EVM address holding the DeFi positions", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "EVM address holding the DeFi positions", "name": "address", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "Normalised DeFi positions", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PositionsResponse" } } } }, "400": { "description": "Invalid request, unauthorized, or the project is not configured for deposits", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks the required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/positions/{address}/unwind": { "post": { "tags": [ "Utilities" ], "summary": "Prepare an Aave position unwind", "description": "Returns an **unsigned** `Pool.withdraw` transaction that exits an Aave position straight to the project's deposit address, so the existing deposit pipeline ingests the proceeds. Nothing is executed: the holding EOA owns the aTokens, so only it can authorise the withdraw, and the service holds no key on this path. The amount is capped server-side against Aave's full withdraw validation and is refused outright if the proceeds would fall foul of the project's deposit policy — that check happens here because this is the last point before an irreversible signature.", "parameters": [ { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "The EOA holding the position. It signs and sends the returned transaction.", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "The EOA holding the position. It signs and sends the returned transaction.", "name": "address", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PrepareUnwindRequestBody" } } } }, "responses": { "200": { "description": "Unsigned withdraw transaction", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PrepareUnwindResponse" } } } }, "400": { "description": "Invalid request, unauthorized, no such position, an amount above the withdrawable maximum, or proceeds the deposit policy would reject", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks the required deposits scope, or the account belongs to another project", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/portfolio/solana/{address}": { "get": { "tags": [ "Utilities" ], "summary": "Get a Solana wallet portfolio", "description": "Returns a normalised SPL portfolio for the given Solana address by paginating through Helius wallet balances.", "parameters": [ { "schema": { "type": "string", "description": "Solana base58 public key", "example": "So11111111111111111111111111111111111111112" }, "required": true, "description": "Solana base58 public key", "name": "address", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "Solana wallet portfolio", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PortfolioResponse" } } } }, "400": { "description": "Invalid Solana address or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "502": { "description": "Helius upstream error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/liquidity": { "get": { "tags": [ "Utilities" ], "summary": "Check route liquidity for an amount", "description": "Returns whether the given source→destination route can fulfil the requested amount, along with the underlying liquidity metadata from the orchestrator.", "parameters": [ { "schema": { "type": "integer", "exclusiveMinimum": 0, "description": "Source chain ID (EVM chain ID)", "example": 1 }, "required": true, "description": "Source chain ID (EVM chain ID)", "name": "sourceChainId", "in": "query" }, { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Source token address", "example": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" }, "required": true, "description": "Source token address", "name": "sourceToken", "in": "query" }, { "schema": { "type": "integer", "exclusiveMinimum": 0, "description": "Destination chain ID (EVM chain ID)", "example": 8453 }, "required": true, "description": "Destination chain ID (EVM chain ID)", "name": "destinationChainId", "in": "query" }, { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Destination token address", "example": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }, "required": true, "description": "Destination token address", "name": "destinationToken", "in": "query" }, { "schema": { "type": "string", "pattern": "^\\d+$", "description": "Deposit amount in raw source-token units (integer string)", "example": "1000000" }, "required": true, "description": "Deposit amount in raw source-token units (integer string)", "name": "amount", "in": "query" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "Liquidity information for the requested route", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LiquidityResponse" } } } }, "400": { "description": "Invalid request parameters or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "502": { "description": "Invalid liquidity response from orchestrator", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/prices": { "get": { "tags": [ "Utilities" ], "summary": "Get USD unit prices for token symbols", "description": "Returns USD unit prices keyed by uppercased token symbol. Used to convert a USD amount into estimated destination-token units for tokens not present in the portfolio (e.g. a SOL or ETH destination the user does not hold).", "parameters": [ { "schema": { "type": "string", "minLength": 1, "description": "Comma-separated token symbols to price (e.g. \"SOL,ETH\"). Prefer `addresses` for arbitrary tokens — symbol pricing collides across tokens that share a ticker (a spam token can inherit a real token's price). Exactly one of `symbols` or `addresses` must be provided.", "example": "SOL" }, "required": false, "description": "Comma-separated token symbols to price (e.g. \"SOL,ETH\"). Prefer `addresses` for arbitrary tokens — symbol pricing collides across tokens that share a ticker (a spam token can inherit a real token's price). Exactly one of `symbols` or `addresses` must be provided.", "name": "symbols", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Comma-separated CAIP-2 token ids to price by exact on-chain contract (e.g. \"eip155:8453:0x833589...\"). Collision-free; preferred over `symbols`. Exactly one of `symbols` or `addresses` must be provided.", "example": "eip155:8453:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" }, "required": false, "description": "Comma-separated CAIP-2 token ids to price by exact on-chain contract (e.g. \"eip155:8453:0x833589...\"). Collision-free; preferred over `symbols`. Exactly one of `symbols` or `addresses` must be provided.", "name": "addresses", "in": "query" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "USD unit prices for the requested symbols", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PricesResponse" } } } }, "400": { "description": "Invalid request parameters or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/qr/tokens": { "get": { "tags": [ "Utilities" ], "summary": "List the QR/transfer token shortlist", "description": "Returns the curated per-chain token shortlist the QR / manual-transfer flow offers as \"what are you sending?\". That flow has no connected wallet to read balances from, so it needs a suggested set rather than a discovered one. Filtered against the authenticated project's `depositWhitelist` when one is configured, so the flow cannot offer a token the client would reject on arrival. This is a suggestion list, not a capability list — `/chains` remains the authority on what the service supports.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "responses": { "200": { "description": "Token shortlist per chain", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QrTokensResponse" } } } }, "401": { "description": "Authentication required", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/safe/withdraw": { "post": { "tags": [ "Processing" ], "summary": "Relay a Safe withdrawal via shared Nexus relayer", "description": "Relay a signed Safe execTransaction via a shared AWS-owned Nexus account with sponsored gas", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WithdrawRequestBody" } } } }, "responses": { "200": { "description": "Withdrawal relayed successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WithdrawResponse" } } } }, "400": { "description": "Invalid request or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Relay failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/polymarket/withdraw": { "post": { "tags": [ "Processing" ], "summary": "Relay a Polymarket deposit-wallet withdrawal", "description": "Relay a user-signed Polymarket deposit-wallet `WALLET` batch (approve/unwrap pUSD or transfer USDC.e) through the Polymarket relayer using server-held builder credentials. Submitted calls must target known Polymarket contracts.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PolymarketWithdrawRequestBody" } } } }, "responses": { "200": { "description": "Withdrawal relayed successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PolymarketWithdrawResponse" } } } }, "400": { "description": "Invalid request, disallowed call, or unauthorized", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "502": { "description": "Polymarket relayer rejected or failed the batch", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Polymarket builder credentials not configured", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/webhooks/events": { "get": { "tags": [ "Webhooks" ], "summary": "List persisted webhook events for the calling client", "description": "Returns webhook events delivered (or attempted) to the caller's webhook URL. Use for backfill or replay verification. Results are id-desc; pass the last `nextCursor` to paginate.", "parameters": [ { "schema": { "type": "string", "format": "date-time", "description": "Return events created at or after this ISO timestamp" }, "required": false, "description": "Return events created at or after this ISO timestamp", "name": "since", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Filter by webhook type (e.g. \"bridge-started\")" }, "required": false, "description": "Filter by webhook type (e.g. \"bridge-started\")", "name": "type", "in": "query" }, { "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50, "description": "Max events to return (1-200, default 50)", "example": 50 }, "required": false, "description": "Max events to return (1-200, default 50)", "name": "limit", "in": "query" }, { "schema": { "type": "string", "minLength": 1, "description": "Opaque cursor from a previous page. Returned events are id-desc; pass the lowest id from the previous page." }, "required": false, "description": "Opaque cursor from a previous page. Returned events are id-desc; pass the lowest id from the previous page.", "name": "cursor", "in": "query" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "Webhook events list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListWebhookEventsResponse" } } } }, "400": { "description": "Invalid API key or malformed query", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/webhooks/events/{id}/resend": { "post": { "tags": [ "Webhooks" ], "summary": "Re-attempt delivery of a stored webhook event", "description": "Re-sends an existing webhook event to the configured webhook URL using its original eventId. Useful for replaying a delivery that failed permanently. Does not allocate a new event id.", "parameters": [ { "schema": { "type": "string", "pattern": "^\\d+$" }, "required": true, "name": "id", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "responses": { "200": { "description": "Resend attempted", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResendWebhookEventResponse" } } } }, "400": { "description": "Invalid API key", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "Event does not belong to caller's client", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "404": { "description": "Event not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/webhooks/test": { "post": { "tags": [ "Webhooks" ], "summary": "Send a test webhook to the configured URL", "description": "Sends a single webhook with fixture data to the client's configured URL. Uses the client's real webhook secret so signature verification works as in production. Envelope and persisted payload both carry `\"test\": true` so the receiver can filter and the dashboard can mark it.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication", "example": "your-api-key" }, "required": true, "description": "API key for authentication", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "pattern": "^\\d{4}-\\d{2}\\.[a-z0-9]+$", "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "example": "2026-04.amazon" }, "required": false, "description": "API version identifier (e.g. \"2026-04.amazon\"). Optional today, will become required in a future release.", "name": "x-api-version", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestWebhookRequestBody" } } } }, "responses": { "200": { "description": "Test webhook dispatched", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TestWebhookResponse" } } } }, "400": { "description": "Invalid request, unknown type, or client has no webhook URL configured", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/onramp/swapped/widget-url": { "post": { "tags": [ "Onramp" ], "summary": "Mint a signed Swapped widget URL (fiat on-ramp)", "description": "Returns a signed Swapped widget URL the modal embeds in an iframe for the fiat on-ramp. The destination asset is fixed server-side (the configured currency code); the caller supplies the smart account that receives the crypto. `methodSelectionSource: \"personalized\"` opts a trusted regional selection into strict merchant-catalog validation; fallback, configured, and legacy selections retain exact-method pass-through.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" }, { "schema": { "type": "string", "pattern": "^[A-Z]{2}$", "description": "Trusted edge-resolved ISO country. When present it overrides body.baseCountry and x-client-ip, and enables country-specific payment-method validation.", "example": "PH" }, "required": false, "description": "Trusted edge-resolved ISO country. When present it overrides body.baseCountry and x-client-ip, and enables country-specific payment-method validation.", "name": "x-user-country", "in": "header" }, { "schema": { "type": "string", "description": "The end user's IP address as observed by the edge, for edges that can name the IP but cannot resolve a country themselves (no local GeoIP database). Used only when x-user-country is absent, and ignored unless it is a publicly-routable address. Prefer x-user-country when your edge already has a country — for example Cloudflare's cf-ipcountry — since it needs no lookup here.", "example": "203.0.113.7" }, "required": false, "description": "The end user's IP address as observed by the edge, for edges that can name the IP but cannot resolve a country themselves (no local GeoIP database). Used only when x-user-country is absent, and ignored unless it is a publicly-routable address. Prefer x-user-country when your edge already has a country — for example Cloudflare's cf-ipcountry — since it needs no lookup here.", "name": "x-client-ip", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedWidgetUrlRequestBody" } } } }, "responses": { "200": { "description": "Signed widget URL", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedUrlResponse" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Authentication required or invalid credential", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks the required deposits scope, or the account is not registered to the calling project", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Server misconfigured or signing failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Swapped on-ramp is not configured", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/onramp/swapped/connect-url": { "post": { "tags": [ "Onramp" ], "summary": "Mint a signed Swapped Connect URL (CEX funding)", "description": "Returns a signed Swapped Connect URL the modal embeds in an iframe so the user can fund from a centralized exchange. Current callers send the exact picker rate as acceptedExchangeFeeBps; omission preserves legacy fee-free delivery, while a stale rate returns 409 before any URL or session state is minted. Requires a configured public webhook callback URL.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" }, { "schema": { "type": "string", "pattern": "^[A-Z]{2}$", "description": "Trusted edge-resolved ISO country. When present it overrides body.baseCountry and x-client-ip, and enables country-specific payment-method validation.", "example": "PH" }, "required": false, "description": "Trusted edge-resolved ISO country. When present it overrides body.baseCountry and x-client-ip, and enables country-specific payment-method validation.", "name": "x-user-country", "in": "header" }, { "schema": { "type": "string", "description": "The end user's IP address as observed by the edge, for edges that can name the IP but cannot resolve a country themselves (no local GeoIP database). Used only when x-user-country is absent, and ignored unless it is a publicly-routable address. Prefer x-user-country when your edge already has a country — for example Cloudflare's cf-ipcountry — since it needs no lookup here.", "example": "203.0.113.7" }, "required": false, "description": "The end user's IP address as observed by the edge, for edges that can name the IP but cannot resolve a country themselves (no local GeoIP database). Used only when x-user-country is absent, and ignored unless it is a publicly-routable address. Prefer x-user-country when your edge already has a country — for example Cloudflare's cf-ipcountry — since it needs no lookup here.", "name": "x-client-ip", "in": "header" } ], "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedConnectUrlRequestBody" } } } }, "responses": { "200": { "description": "Signed Connect URL", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedUrlResponse" } } } }, "400": { "description": "Invalid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Authentication required or invalid credential", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks the required deposits scope, or the account is not registered to the calling project", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "409": { "description": "The Exchange Fee changed after the caller loaded the picker; the returned rate must be disclosed and accepted before retrying", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedExchangeFeeChangedResponse" } } } }, "500": { "description": "Server misconfigured or signing failed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Swapped on-ramp is not configured", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/onramp/swapped/payment-methods": { "get": { "tags": [ "Onramp" ], "summary": "List localized Swapped payment methods", "description": "Returns the configured popular method (when merchant-enabled) followed by the supported subset of credit card, bank transfer, and Apple Pay for the trusted edge-resolved x-user-country. A missing/unknown country or unavailable catalog returns the null-country fallback so clients can use their built-in global defaults.", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" }, { "schema": { "type": "string", "pattern": "^[A-Z]{2}$", "description": "Trusted edge-resolved ISO country. When present it overrides body.baseCountry and x-client-ip, and enables country-specific payment-method validation.", "example": "PH" }, "required": false, "description": "Trusted edge-resolved ISO country. When present it overrides body.baseCountry and x-client-ip, and enables country-specific payment-method validation.", "name": "x-user-country", "in": "header" }, { "schema": { "type": "string", "description": "The end user's IP address as observed by the edge, for edges that can name the IP but cannot resolve a country themselves (no local GeoIP database). Used only when x-user-country is absent, and ignored unless it is a publicly-routable address. Prefer x-user-country when your edge already has a country — for example Cloudflare's cf-ipcountry — since it needs no lookup here.", "example": "203.0.113.7" }, "required": false, "description": "The end user's IP address as observed by the edge, for edges that can name the IP but cannot resolve a country themselves (no local GeoIP database). Used only when x-user-country is absent, and ignored unless it is a publicly-routable address. Prefer x-user-country when your edge already has a country — for example Cloudflare's cf-ipcountry — since it needs no lookup here.", "name": "x-client-ip", "in": "header" } ], "responses": { "200": { "description": "Localized payment methods or the generic fallback", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedPaymentMethodsResponse" } } } }, "400": { "description": "Invalid country header", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Authentication required or invalid credential", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Swapped on-ramp is not configured", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/onramp/swapped/status/{smartAccount}": { "get": { "tags": [ "Onramp" ], "summary": "Poll the latest Swapped order status for a smart account", "description": "Returns the latest Swapped order recorded for the smart account (from notify webhooks), or `{ ok: false, reason: \"no_order\" }` when none exists yet.", "parameters": [ { "schema": { "type": "string", "pattern": "^0x[a-fA-F0-9]{40}$", "description": "Ethereum address (0x followed by 40 hex characters)", "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f5bE91" }, "required": true, "description": "Ethereum address (0x followed by 40 hex characters)", "name": "smartAccount", "in": "path" }, { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "responses": { "200": { "description": "Latest order status (or no_order)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedStatusResponse" } } } }, "400": { "description": "Invalid smart account address", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "401": { "description": "Authentication required or invalid credential", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks the required deposits scope, or the account is not registered to the calling project", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "500": { "description": "Failed to read order status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Swapped on-ramp is not configured", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } }, "/onramp/swapped/connect-exchanges": { "get": { "tags": [ "Onramp" ], "summary": "List centralized exchanges for the Connect picker", "description": "Returns the centralized exchanges offered by the Swapped Connect picker. Served from a maintained static list (Swapped exposes no enumeration API).", "parameters": [ { "schema": { "type": "string", "description": "API key for authentication (omit when sending Authorization)", "example": "your-api-key" }, "required": false, "description": "API key for authentication (omit when sending Authorization)", "name": "x-api-key", "in": "header" }, { "schema": { "type": "string", "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "example": "Bearer eyJhbGciOi..." }, "required": false, "description": "Bearer platform token (e.g. forwarded by user-service). Takes precedence over `x-api-key` when both are present.", "name": "authorization", "in": "header" } ], "responses": { "200": { "description": "Supported exchanges", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwappedConnectExchangesResponse" } } } }, "401": { "description": "Authentication required or invalid credential", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "403": { "description": "API key lacks required deposits scope", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }, "503": { "description": "Swapped on-ramp is not configured", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } } } } } }, "webhooks": {} }