From 67aabd907bd1577a6588312a7aba06ac7e13bc9c Mon Sep 17 00:00:00 2001 From: rodrigopavezi Date: Tue, 28 Jul 2026 09:39:21 -0300 Subject: [PATCH 1/2] docs: add the /v2/secure-payments surface to openapi.v2.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec was missing every secure-payments endpoint, including POST /v2/secure-payments — the primary flow the prose docs teach — and POST /v2/secure-payments/multicall-payouts. Because docs.json auto-generates the "Endpoints (V2)" playground pages from this file, none of them had a reference page, and rules like the optionality of requests[].destinationId could only be sourced from prose. Adds all 12 operations across 11 paths under the V2/Secure Payment tag, reconciled against the request-api implementation (RequestNetwork/request-api @ 0.28.0, identical on main and staging). Schemas are generated from the zod schemas in src/validation/schemas/secure-payment.schema.ts rather than copied from the live /open-api/openapi.json, because the Route decorator's generateSchema() helper takes Object.keys(components.schemas)[0] and so mis-picks a nested component whenever a schema references another registered one. The served spec is wrong for SecurePaymentResponse (shows the fee plan snapshot), GetSecurePaymentResponse, GetSecurePaymentCalldataResponse, SecurePaymentInfoResponse, MulticallPayoutDetailsResponse, RecordSecurePaymentIntent(Response), and the TRON broadcast body. Also corrected against the source: - Added the missing `token` path parameter on GET /v2/secure-payments/{token} and /{token}/pay. The served spec only declares the same-named *query* parameter (the crosschain source currency), which left the path parameter undeclared and the two meanings conflated. Both are now documented. - Added the `Authorization` header to the operations whose guard accepts a session, with the guard's actual precedence (orchestrator key, then api key / client id, then session). - Added `enum: ["true", "false"]` to the `isSafe` query parameter, which the decorator drops because the zod enum sits behind a transform. - Documented `requests[].destinationId` from the service: the server always resolves the destination itself, a mismatched value is rejected with 403, and a backend Client ID must be bound to a payee destination. - Added 401 to every operation, plus the 400/403 cases on POST /v2/secure-payments. Schemas are emitted as OpenAPI 3.0 (nullable, boolean exclusiveMinimum) to match the "openapi": "3.0.0" this file declares. The additions validate cleanly; the one pre-existing validation error on /v2/payee-destination/{destinationId} is untouched and unrelated. --- api-reference/openapi.v2.json | 6803 +++++++++++++++++++++++++++++++++ 1 file changed, 6803 insertions(+) diff --git a/api-reference/openapi.v2.json b/api-reference/openapi.v2.json index 61095b5..4f9ec7e 100644 --- a/api-reference/openapi.v2.json +++ b/api-reference/openapi.v2.json @@ -5455,6 +5455,6805 @@ ] } }, + "/v2/secure-payments": { + "post": { + "description": "Creates a secure payment entry with a token. Accepts an array of payment requests using destination IDs (composite ERC-7828 payee address + token address). The server resolves chain, wallet, and currency from each destination ID. Single item creates a single incoming payment. Multiple items preserve the legacy incoming-payment batch shape and are unrelated to multicall payout parents; create multicall payout parents only through /v2/secure-payments/multicall-payouts. All requests must resolve to the same network. Returns a secure payment URL.", + "operationId": "SecurePaymentController_createSecurePayment_v2", + "parameters": [ + { + "name": "x-api-key", + "in": "header", + "description": "API key for authentication (optional if using Client ID, session, or orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication (required when paired with orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-orchestrator-key", + "in": "header", + "description": "Orchestrator key for authentication (must be paired with Client ID)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "Bearer token for session authentication (or use the session_token cookie). Only consulted when no x-orchestrator-key, x-api-key, or x-client-id header is present.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (required for Client ID / orchestrator auth, automatically set by browser)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "requests": { + "type": "array", + "items": { + "type": "object", + "properties": { + "destinationId": { + "type": "string", + "minLength": 1, + "description": "Destination ID in composite format: ERC-7828 payee address + token address, separated by ':' (e.g. '0x742d...bEb0@eip155:11155111#80B12379:0x370D...623C').\n\nOptional. The server always resolves the destination itself \u2014 from the payee destination bound to the authenticating Client ID, falling back to the platform's active destination \u2014 so you can omit this field whenever the Client ID has a bound payee destination. When you do send it, it must equal the resolved destination ID: a different value is rejected with 403 'Destination does not match the configured payment destination.' Every item in `requests[]` therefore resolves to the same destination. A backend Client ID (one with no allowed domains) must be bound to a payee destination, otherwise creation fails with 403." + }, + "amount": { + "type": "string", + "description": "The payable amount, in human readable format" + } + }, + "required": [ + "amount" + ] + }, + "minItems": 1, + "description": "Array of payment requests. Single item = single incoming payment. Multiple items preserve the legacy incoming-payment batch shape and are unrelated to multicall payout parents." + }, + "feePercentage": { + "type": "string", + "description": "DEPRECATED. Legacy fee percentage; ignored. Fees are now resolved server-side from the fee plan snapshot." + }, + "feeAddress": { + "type": "string", + "description": "DEPRECATED. Legacy fee recipient; ignored. Fees are now resolved server-side from the fee plan snapshot." + }, + "reference": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Merchant reference for receipt tracking and identification" + }, + "payerIdentifier": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Payer identifier for tracking who is making the payment" + }, + "redirectUrl": { + "type": "string", + "description": "URL the payer is redirected to after a successful payment" + }, + "redirectLabel": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "pattern": "^[^<>&\"'`]*$", + "description": "Optional label describing the redirect destination" + }, + "accessPolicy": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "inherit", + "off", + "kyt_all_wallets" + ] + }, + "screeningProvider": { + "type": "string", + "enum": [ + "hypernative", + "merklescience" + ], + "nullable": true + }, + "hideUntilApproved": { + "type": "boolean" + }, + "hidePayeeAddress": { + "type": "boolean" + }, + "allowedPayerAddresses": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "Optional per-payment access policy override. If omitted, the payment inherits the destination access policy." + } + }, + "required": [ + "requests" + ] + }, + "examples": { + "singlePayment": { + "summary": "Single payment example", + "value": { + "requests": [ + { + "destinationId": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "amount": "10" + } + ] + } + }, + "singlePaymentWithFees": { + "summary": "Single payment with fees example", + "value": { + "requests": [ + { + "destinationId": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "amount": "10" + } + ], + "feePercentage": "2.5", + "feeAddress": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7" + } + }, + "batchPayment": { + "summary": "Legacy incoming batch payment example", + "value": { + "requests": [ + { + "destinationId": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "amount": "10" + }, + { + "destinationId": "0xb07d2398d2004378cad234da0ef14f1c94a530e4@eip155:11155111#E5F6A7B8:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "amount": "5" + } + ] + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Secure payment entry created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "requestIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of request IDs created for this secure payment" + }, + "securePaymentUrl": { + "type": "string", + "format": "uri", + "description": "URL to the secure payment page" + }, + "token": { + "type": "string", + "description": "Secure payment token" + }, + "feePlan": { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Resolved fee plan snapshot. Null when fees don't apply \u2014 e.g. non-stablecoin currency, or a batch that spans multiple currencies (not yet supported).", + "nullable": true + } + }, + "required": [ + "requestIds", + "securePaymentUrl", + "token", + "feePlan" + ] + }, + "examples": { + "singlePayment": { + "summary": "Single payment response", + "value": { + "requestIds": [ + "01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cdb" + ], + "securePaymentUrl": "https://secure.request.network/01ABC123DEF456GHI789JKL", + "token": "01ABC123DEF456GHI789JKL" + } + }, + "batchPayment": { + "summary": "Batch payment response", + "value": { + "requestIds": [ + "01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cdb", + "01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cde" + ], + "securePaymentUrl": "https://secure.request.network/01ABC123DEF456GHI789JKL", + "token": "01ABC123DEF456GHI789JKL" + } + } + } + } + } + }, + "400": { + "description": "Invalid request body, no active payment destination for the platform, `requests[]` items resolving to more than one network, or a multi-item batch on a TRON network." + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "The supplied `destinationId` does not match the destination resolved for the caller, the authenticated platform is not wallet-based, or a backend Client ID (no allowed domains) is not bound to a payee destination." + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Create a secure payment entry", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + }, + "get": { + "description": "Looks up the secure payment associated with a given request ID. Returns the payment link URL, status, and metadata. Requires a SIWE session.", + "operationId": "SecurePaymentController_findSecurePayment_v2", + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "Bearer token for session authentication (or use session_token cookie)", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "requestId", + "required": true, + "in": "query", + "description": "Request ID to look up the associated secure payment", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Secure payment found", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Secure payment token" + }, + "securePaymentUrl": { + "type": "string", + "format": "uri", + "description": "URL to the secure payment page" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "completed", + "expired", + "invalidated", + "compliance_failed" + ], + "description": "Current status of the secure payment" + }, + "paymentType": { + "type": "string", + "enum": [ + "single", + "batch" + ], + "description": "Type of payment: single or batch" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "When the secure payment was created", + "nullable": true + }, + "expiresAt": { + "type": "string", + "format": "date-time", + "description": "When the secure payment token expires" + }, + "redirectUrl": { + "type": "string", + "description": "Optional redirect URL configured at creation time. Null when no redirect was set.", + "nullable": true + }, + "redirectLabel": { + "type": "string", + "description": "Optional label describing the redirect destination. Null when no label was provided.", + "nullable": true + }, + "completedAt": { + "type": "string", + "format": "date-time", + "description": "When the secure payment was completed", + "nullable": true + }, + "payerAddress": { + "type": "string", + "description": "Detected payer address for the completed secure payment", + "nullable": true + }, + "payerKytResults": { + "type": "array", + "items": { + "type": "object", + "properties": { + "walletAddress": { + "type": "string" + }, + "walletType": { + "type": "string", + "enum": [ + "eoa", + "smart_account" + ] + }, + "parentWalletAddress": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string", + "nullable": true + }, + "reasonCode": { + "type": "string", + "nullable": true + }, + "provider": { + "type": "string", + "nullable": true + }, + "providerReference": { + "type": "string", + "nullable": true + }, + "reportUrl": { + "type": "string", + "nullable": true + }, + "notes": { + "type": "string", + "nullable": true + }, + "rawStatus": { + "type": "string", + "nullable": true + }, + "evaluatedAt": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ], + "nullable": true + } + }, + "required": [ + "walletAddress", + "walletType", + "parentWalletAddress", + "status", + "reasonCode", + "provider", + "providerReference", + "reportUrl", + "notes", + "rawStatus", + "evaluatedAt" + ], + "description": "KYT result for a wallet screened for a secure payment" + }, + "description": "KYT results for the actual detected payer wallets only" + }, + "payeeKytResults": { + "type": "array", + "items": { + "type": "object", + "properties": { + "walletAddress": { + "type": "string" + }, + "walletType": { + "type": "string", + "enum": [ + "eoa", + "smart_account" + ] + }, + "parentWalletAddress": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string", + "nullable": true + }, + "reasonCode": { + "type": "string", + "nullable": true + }, + "provider": { + "type": "string", + "nullable": true + }, + "providerReference": { + "type": "string", + "nullable": true + }, + "reportUrl": { + "type": "string", + "nullable": true + }, + "notes": { + "type": "string", + "nullable": true + }, + "rawStatus": { + "type": "string", + "nullable": true + }, + "evaluatedAt": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ], + "nullable": true + } + }, + "required": [ + "walletAddress", + "walletType", + "parentWalletAddress", + "status", + "reasonCode", + "provider", + "providerReference", + "reportUrl", + "notes", + "rawStatus", + "evaluatedAt" + ], + "description": "KYT result for a wallet screened for a secure payment" + }, + "description": "KYT results for outgoing payout payee wallets only" + }, + "destination": { + "type": "object", + "properties": { + "destinationId": { + "type": "string", + "description": "Composite destination ID: ERC-7828 payee address + token address (e.g., '0x742d...bEb0@eip155:11155111#80B12379:0x370D...623C'). Omitted when payee-address fields are masked." + }, + "payeeAddress": { + "type": "string", + "description": "Payee address in ERC-7828 human-readable format" + }, + "tokenAddress": { + "type": "string", + "description": "ERC20 token contract address" + }, + "walletAddress": { + "type": "string", + "description": "Raw wallet address" + }, + "network": { + "type": "string", + "description": "Blockchain network name" + }, + "isMasked": { + "type": "boolean", + "description": "Whether payee-address fields in this destination are intentionally masked" + } + }, + "required": [ + "payeeAddress", + "tokenAddress", + "walletAddress", + "network" + ], + "description": "Resolved destination for the selected request row, when stored", + "nullable": true + }, + "claimedDestination": { + "type": "object", + "properties": { + "destinationId": { + "type": "string", + "description": "Composite destination ID: ERC-7828 payee address + token address (e.g., '0x742d...bEb0@eip155:11155111#80B12379:0x370D...623C'). Omitted when payee-address fields are masked." + }, + "payeeAddress": { + "type": "string", + "description": "Payee address in ERC-7828 human-readable format" + }, + "tokenAddress": { + "type": "string", + "description": "ERC20 token contract address" + }, + "walletAddress": { + "type": "string", + "description": "Raw wallet address" + }, + "network": { + "type": "string", + "description": "Blockchain network name" + }, + "isMasked": { + "type": "boolean", + "description": "Whether payee-address fields in this destination are intentionally masked" + } + }, + "required": [ + "payeeAddress", + "tokenAddress", + "walletAddress", + "network" + ], + "description": "Recipient claimed destination snapshot captured when the payout was created. Null when the recipient had no claimed destination or the row predates this snapshot.", + "nullable": true + }, + "orchestratorId": { + "type": "string", + "description": "Orchestrator ID associated with the secure payment, if any", + "nullable": true + }, + "feePlan": { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Fee plan snapshot persisted at secure payment creation. Immutable, so it reflects the fees that applied to the payment whether it is still pending or already completed. Null when no snapshot was stored \u2014 e.g. non-stablecoin currency, or a batch that spans multiple currencies (not yet supported).", + "nullable": true + }, + "network": { + "type": "string", + "description": "Request destination network. Dashboard uses this as an advisory multicall selection hint; creation and /pay still revalidate server-side." + }, + "currency": { + "type": "string", + "description": "Request payment currency ID, when available. Null means the row predates the hint or has malformed stored currency data.", + "nullable": true + }, + "executionKind": { + "type": "string", + "enum": [ + "evm_same_chain", + "evm_cross_chain", + "tron_batch" + ], + "description": "Per-row execution-family hint for Dashboard selection. EVM rows can form same-chain or cross-chain multicalls depending on the selected set; Tron rows can only form Tron batches. Null means unsupported or inconsistent stored route data.", + "nullable": true + }, + "identityMode": { + "type": "string", + "enum": [ + "manual_dashboard", + "client_id" + ], + "description": "Backend-derived identity bucket hint for multicall selection. Dashboard may use it to prevent mixed manual/clientId selections, but creation remains authoritative." + }, + "clientId": { + "type": "string", + "description": "ClientId identity bucket when identityMode is client_id.", + "nullable": true + }, + "branding": { + "type": "object", + "properties": { + "whitelabelEnabled": { + "type": "boolean" + }, + "source": { + "type": "string", + "enum": [ + "client_id", + "request_network" + ] + } + }, + "required": [ + "whitelabelEnabled", + "source" + ], + "description": "Dashboard selection hint for neutral versus clientId-backed branding. Lets Dashboard distinguish neutral rows from clientId-backed rows so it can prevent mixed-branding selections at the UI level; creation remains authoritative." + }, + "childExecutable": { + "type": "boolean", + "description": "Whether this secure-payment child currently passes creation-time child validation." + }, + "blockReason": { + "type": "string", + "enum": [ + "not_found", + "not_owned", + "not_outgoing", + "not_single_payment", + "invalid_child_linkage", + "already_paid", + "request_processing", + "secure_payment_expired", + "secure_payment_not_pending", + "compliance_failed", + "not_payable_child" + ], + "description": "Creation-validation block reason when childExecutable is false. Null when the child is currently executable.", + "nullable": true + } + }, + "required": [ + "token", + "securePaymentUrl", + "status", + "paymentType", + "createdAt", + "expiresAt", + "redirectUrl", + "redirectLabel", + "completedAt", + "payerAddress", + "payerKytResults", + "payeeKytResults", + "destination", + "claimedDestination", + "orchestratorId", + "feePlan", + "network", + "currency", + "executionKind", + "identityMode", + "clientId", + "branding", + "childExecutable", + "blockReason" + ] + }, + "examples": { + "found": { + "summary": "Secure payment found for request", + "value": { + "token": "01ABC123DEF456GHI789JKL", + "securePaymentUrl": "https://secure.request.network/?token=01ABC123DEF456GHI789JKL", + "status": "pending", + "paymentType": "single", + "createdAt": "2025-01-15T10:30:00.000Z", + "expiresAt": "2025-01-15T10:45:00.000Z", + "redirectUrl": "https://merchant.example.com/thank-you", + "redirectLabel": "Back to merchant" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "No secure payment found for this request ID" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Find secure payment by request ID", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/payouts": { + "post": { + "description": "Creates a single-payment secure-payment link for an outgoing payout. The caller provides the raw recipient details (wallet, network, currency, amount); the API resolves or creates the wallet/network/currency destination tuple and links the payout to that tuple. Returns the same response shape as POST /v2/secure-payments/ so the resulting link loads on the secure payment page without a separate code path.", + "operationId": "SecurePaymentController_createPayoutSecurePayment_v2", + "parameters": [ + { + "name": "x-api-key", + "in": "header", + "description": "API key for authentication (optional if using Client ID, session, or orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication (required when paired with orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-orchestrator-key", + "in": "header", + "description": "Orchestrator key for authentication (must be paired with Client ID)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "Bearer token for session authentication (or use the session_token cookie). Only consulted when no x-orchestrator-key, x-api-key, or x-client-id header is present.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (required for Client ID / orchestrator auth, automatically set by browser)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "recipient": { + "type": "string", + "description": "Recipient wallet address (EVM 0x... or TRON T...)" + }, + "creatorWalletAddress": { + "type": "string", + "description": "Wallet address that created the payout link. This is not necessarily the wallet that will execute the payment." + }, + "network": { + "type": "string", + "minLength": 1, + "description": "Blockchain network the payout targets (e.g., 'mainnet', 'sepolia', 'tron')" + }, + "currency": { + "type": "string", + "minLength": 1, + "description": "Currency ID in the '-' format (e.g., 'USDC-mainnet', 'FAU-sepolia')" + }, + "amount": { + "type": "string", + "description": "The payout amount, in human readable format" + }, + "reference": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Merchant reference for receipt tracking and identification" + }, + "recipientIdentifier": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Recipient identifier for tracking outgoing payout recipients" + }, + "feePercentage": { + "type": "string", + "description": "DEPRECATED. Legacy fee percentage; ignored. Fees are now resolved server-side from the fee plan snapshot." + }, + "feeAddress": { + "type": "string", + "description": "DEPRECATED. Legacy fee recipient; ignored. Fees are now resolved server-side from the fee plan snapshot." + }, + "redirectUrl": { + "type": "string", + "description": "URL the payer is redirected to after a successful payment" + }, + "redirectLabel": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "pattern": "^[^<>&\"'`]*$", + "description": "Optional label describing the redirect destination" + }, + "accessPolicy": { + "type": "object", + "properties": { + "mode": { + "type": "string", + "enum": [ + "inherit", + "off", + "kyt_all_wallets" + ] + }, + "screeningProvider": { + "type": "string", + "enum": [ + "hypernative", + "merklescience" + ], + "nullable": true + }, + "hideUntilApproved": { + "type": "boolean" + }, + "hidePayeeAddress": { + "type": "boolean" + }, + "allowedPayerAddresses": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "description": "Optional per-payment access policy override." + } + }, + "required": [ + "recipient", + "creatorWalletAddress", + "network", + "currency", + "amount" + ] + }, + "examples": { + "payout": { + "summary": "Payout example", + "value": { + "recipient": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7", + "network": "sepolia", + "currency": "FAU-sepolia", + "amount": "10", + "recipientIdentifier": "recipient-acme" + } + }, + "payoutWithFees": { + "summary": "Payout with fees example", + "value": { + "recipient": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7", + "network": "sepolia", + "currency": "FAU-sepolia", + "amount": "10", + "feePercentage": "2.5", + "feeAddress": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7", + "reference": "PAYOUT-2025-001" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Payout secure payment created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "requestIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of request IDs created for this secure payment" + }, + "securePaymentUrl": { + "type": "string", + "format": "uri", + "description": "URL to the secure payment page" + }, + "token": { + "type": "string", + "description": "Secure payment token" + }, + "feePlan": { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Resolved fee plan snapshot. Null when fees don't apply \u2014 e.g. non-stablecoin currency, or a batch that spans multiple currencies (not yet supported).", + "nullable": true + } + }, + "required": [ + "requestIds", + "securePaymentUrl", + "token", + "feePlan" + ] + } + } + } + }, + "400": { + "description": "Invalid payout request (e.g., unsupported network or currency)" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Platform is not allowed to create payouts" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Create a secure payment for an outgoing payout", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/fees/preview": { + "post": { + "description": "Calculation-only preview of the fee plan that would apply to a payment with the given amount, currency, and flow. Uses the same fee resolver as creation. Has no side effects: does not create a secure payment, payment request, or persist any snapshot.", + "operationId": "SecurePaymentController_previewFees_v2", + "parameters": [ + { + "name": "x-api-key", + "in": "header", + "description": "API key for authentication (optional if using Client ID, session, or orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication (required when paired with orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-orchestrator-key", + "in": "header", + "description": "Orchestrator key for authentication (must be paired with Client ID)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "Bearer token for session authentication (or use the session_token cookie). Only consulted when no x-orchestrator-key, x-api-key, or x-client-id header is present.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (required for Client ID / orchestrator auth, automatically set by browser)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "amount": { + "type": "string", + "description": "Base/displayed amount in human-readable units, as a decimal string (e.g. \"12.5\")." + }, + "currency": { + "type": "string", + "minLength": 1, + "description": "Currency symbol or currency ID (e.g. 'USDC' or 'USDC-mainnet'). Must resolve to a supported stablecoin." + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ], + "description": "`get_paid` for incoming payments (recipient creates link), `pay` for outgoing payments (payer initiates)." + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ], + "description": "Payment-level override of the flow default. Per-fee config bearer still wins." + } + }, + "required": [ + "amount", + "currency", + "flow" + ] + }, + "examples": { + "getPaid": { + "summary": "Get-paid preview (recipient bears fees by default)", + "value": { + "amount": "100", + "currency": "USDC", + "flow": "get_paid" + } + }, + "pay": { + "summary": "Pay preview (payer bears fees by default)", + "value": { + "amount": "100", + "currency": "USDC", + "flow": "pay" + } + }, + "withOverride": { + "summary": "Get-paid with payer-borne override", + "value": { + "amount": "100", + "currency": "USDC", + "flow": "get_paid", + "defaultFeeBearer": "payer" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Fee plan preview", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ] + } + } + } + }, + "400": { + "description": "Unsupported currency or invalid combination" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Preview the fee plan for a payment", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/batch-payouts": { + "post": { + "description": "Creates a single batch payout link from multiple existing pending single payout tokens. The individual tokens are invalidated and a new batch payment URL is returned. All payouts must target the same network.", + "operationId": "SecurePaymentController_createBatchPayoutSecurePayment_v2", + "parameters": [ + { + "name": "x-api-key", + "in": "header", + "description": "API key for authentication (optional if using Client ID or session)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication (optional if using API key or session)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "Bearer token for session authentication (or use the session_token cookie). Only consulted when no x-orchestrator-key, x-api-key, or x-client-id header is present.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (required for Client ID auth, automatically set by browser)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "tokens": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 2, + "description": "Tokens of existing pending single payout secure payments to combine into one batch payment link" + }, + "redirectUrl": { + "type": "string", + "description": "URL the payer is redirected to after a successful payment" + }, + "redirectLabel": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "pattern": "^[^<>&\"'`]*$", + "description": "Optional label describing the redirect destination" + } + }, + "required": [ + "tokens" + ] + } + } + } + }, + "responses": { + "201": { + "description": "Batch payout secure payment created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "requestIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of request IDs created for this secure payment" + }, + "securePaymentUrl": { + "type": "string", + "format": "uri", + "description": "URL to the secure payment page" + }, + "token": { + "type": "string", + "description": "Secure payment token" + }, + "feePlan": { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Resolved fee plan snapshot. Null when fees don't apply \u2014 e.g. non-stablecoin currency, or a batch that spans multiple currencies (not yet supported).", + "nullable": true + } + }, + "required": [ + "requestIds", + "securePaymentUrl", + "token", + "feePlan" + ] + } + } + } + }, + "400": { + "description": "Invalid request (e.g., tokens on different networks, non-pending tokens, less than 2 tokens)" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Platform is not allowed to create payouts" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Create a batch secure payment for multiple outgoing payouts", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/{token}": { + "get": { + "description": "Retrieves secure payment display data and resolved destination info. The token must be valid, not expired, and the payment must be in 'pending' status.", + "operationId": "SecurePaymentController_getSecurePaymentByToken_v2", + "parameters": [ + { + "name": "token", + "in": "path", + "description": "Secure payment token (ULID) returned by POST /v2/secure-payments, POST /v2/secure-payments/payouts, or POST /v2/secure-payments/multicall-payouts. Distinct from the `token` query parameter, which selects the crosschain source currency.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "token", + "required": false, + "in": "query", + "description": "The source token of the crosschain payment. Pair with `chain`; both must be sent together. Not the secure payment token \u2014 that is the `{token}` path parameter.", + "schema": { + "enum": [ + "USDC", + "USDT", + "EURC", + "USDT0" + ], + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (automatically set by browser)", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "wallet", + "required": false, + "in": "query", + "description": "The wallet address of the payer (optional, used to check existing approvals)", + "schema": { + "type": "string" + } + }, + { + "name": "chain", + "required": false, + "in": "query", + "description": "The source chain of the crosschain payment", + "schema": { + "enum": [ + "BASE", + "OPTIMISM", + "ARBITRUM", + "ETHEREUM", + "POLYGON", + "BNB" + ], + "type": "string" + } + }, + { + "name": "eoaWallet", + "required": false, + "in": "query", + "description": "The EOA wallet address that holds the funds. When provided, balance checks and LiFi quotes use this address while the wallet param is used for calldata building (smart account flow).", + "schema": { + "type": "string" + } + }, + { + "name": "isSafe", + "required": false, + "in": "query", + "description": "When true, prepares calldata for a Gnosis Safe multisig payer (wallet must be the Safe address). Mutually exclusive with eoaWallet.", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + } + } + ], + "responses": { + "200": { + "description": "Secure payment data retrieved successfully", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "paymentType": { + "type": "string", + "enum": [ + "single" + ], + "description": "Type of payment: single or batch" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "completed", + "expired", + "invalidated", + "compliance_failed" + ] + }, + "redirectUrl": { + "type": "string", + "description": "Optional redirect URL configured at creation time. Null when no redirect was set.", + "nullable": true + }, + "redirectLabel": { + "type": "string", + "description": "Optional label describing the redirect destination. Null when no label was provided.", + "nullable": true + }, + "orchestratorId": { + "type": "string", + "description": "Orchestrator ID associated with the secure payment, if any", + "nullable": true + }, + "branding": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "clientIdId": { + "type": "string" + }, + "orchestratorId": { + "type": "string" + }, + "logoPath": { + "type": "string" + }, + "pageBackgroundColor": { + "type": "string" + }, + "cardBackgroundColor": { + "type": "string" + }, + "primaryActionColor": { + "type": "string" + }, + "primaryTextColor": { + "type": "string" + }, + "secondaryTextColor": { + "type": "string" + }, + "termsPath": { + "type": "string" + }, + "privacyPath": { + "type": "string" + }, + "displayRequestBranding": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "nullable": true + }, + "paymentOptions": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "balance": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + }, + "neededAmount": { + "type": "string" + } + }, + "required": [ + "balance", + "hasEnoughBalance", + "neededAmount" + ] + } + } + }, + "analytics": { + "type": "object", + "properties": { + "creationTimestamp": { + "type": "string", + "format": "date-time" + }, + "totalPaymentAmountUsd": { + "type": "string" + }, + "protocolFeeAmountUsd": { + "type": "string" + }, + "orchestratorPayerFeeAmountUsd": { + "type": "string" + }, + "orchestratorRecipientFeeAmountUsd": { + "type": "string" + }, + "feeAmountsUsdUnavailableReason": { + "type": "string", + "enum": [ + "fee_plan_unavailable" + ] + }, + "numberOfPaymentsExcludingFees": { + "type": "integer", + "minimum": 0 + }, + "destinationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "payoutKytProvider": { + "type": "string" + } + }, + "description": "Vendor-neutral analytics metadata that SPP maps into Mixpanel shared properties. Amount values are decimal USD strings to avoid frontend precision loss." + }, + "requestIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request Network request IDs represented by this payment" + }, + "payee": { + "type": "string", + "description": "Payee wallet address" + }, + "network": { + "type": "string", + "description": "Blockchain network" + }, + "amount": { + "type": "string", + "description": "Payment amount" + }, + "paymentCurrency": { + "type": "string", + "description": "Payment currency ID" + }, + "isNativeCurrency": { + "type": "boolean", + "description": "Whether the payment currency is the native currency (e.g., ETH)" + }, + "destination": { + "type": "object", + "properties": { + "destinationId": { + "type": "string", + "description": "Composite destination ID: ERC-7828 payee address + token address (e.g., '0x742d...bEb0@eip155:11155111#80B12379:0x370D...623C'). Omitted when payee-address fields are masked." + }, + "payeeAddress": { + "type": "string", + "description": "Payee address in ERC-7828 human-readable format" + }, + "tokenAddress": { + "type": "string", + "description": "ERC20 token contract address" + }, + "walletAddress": { + "type": "string", + "description": "Raw wallet address" + }, + "network": { + "type": "string", + "description": "Blockchain network name" + }, + "isMasked": { + "type": "boolean", + "description": "Whether payee-address fields in this destination are intentionally masked" + } + }, + "required": [ + "payeeAddress", + "tokenAddress", + "walletAddress", + "network" + ], + "description": "Resolved destination for this payment, or null when the payment is not linked to a stored destination (e.g., payouts created from raw recipient details).", + "nullable": true + }, + "reference": { + "type": "string", + "description": "Merchant reference for the payment", + "nullable": true + }, + "isPayeeAddressMasked": { + "type": "boolean", + "description": "Whether payee-address fields are intentionally masked until access is approved" + }, + "feePlan": { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Fee plan snapshot captured at creation time. Null when fees don't apply (non-stablecoin currency, payment created before fee plan rollout, etc.).", + "nullable": true + }, + "accessDecision": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "approved", + "rejected", + "error" + ] + }, + "reasonCode": { + "type": "string" + }, + "provider": { + "type": "string", + "nullable": true + }, + "walletResults": { + "type": "array", + "items": { + "type": "object", + "properties": { + "walletAddress": { + "type": "string" + }, + "walletType": { + "type": "string", + "enum": [ + "eoa", + "smart_account" + ] + }, + "parentWalletAddress": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string", + "enum": [ + "approved", + "rejected", + "error" + ] + }, + "reasonCode": { + "type": "string" + }, + "provider": { + "type": "string", + "nullable": true + }, + "evaluatedAt": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "walletAddress", + "walletType", + "status", + "reasonCode", + "provider" + ] + } + } + }, + "required": [ + "status", + "reasonCode", + "provider", + "walletResults" + ] + } + }, + "required": [ + "paymentType", + "status", + "redirectUrl", + "redirectLabel", + "branding", + "requestIds", + "payee", + "network", + "amount", + "paymentCurrency", + "isNativeCurrency", + "destination", + "reference", + "feePlan" + ] + }, + { + "type": "object", + "properties": { + "paymentType": { + "type": "string", + "enum": [ + "batch" + ], + "description": "Type of payment: single or batch" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "completed", + "expired", + "invalidated", + "compliance_failed" + ] + }, + "redirectUrl": { + "type": "string", + "description": "Optional redirect URL configured at creation time. Null when no redirect was set.", + "nullable": true + }, + "redirectLabel": { + "type": "string", + "description": "Optional label describing the redirect destination. Null when no label was provided.", + "nullable": true + }, + "orchestratorId": { + "type": "string", + "description": "Orchestrator ID associated with the secure payment, if any", + "nullable": true + }, + "branding": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "clientIdId": { + "type": "string" + }, + "orchestratorId": { + "type": "string" + }, + "logoPath": { + "type": "string" + }, + "pageBackgroundColor": { + "type": "string" + }, + "cardBackgroundColor": { + "type": "string" + }, + "primaryActionColor": { + "type": "string" + }, + "primaryTextColor": { + "type": "string" + }, + "secondaryTextColor": { + "type": "string" + }, + "termsPath": { + "type": "string" + }, + "privacyPath": { + "type": "string" + }, + "displayRequestBranding": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "nullable": true + }, + "paymentOptions": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "balance": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + }, + "neededAmount": { + "type": "string" + } + }, + "required": [ + "balance", + "hasEnoughBalance", + "neededAmount" + ] + } + } + }, + "analytics": { + "type": "object", + "properties": { + "creationTimestamp": { + "type": "string", + "format": "date-time" + }, + "totalPaymentAmountUsd": { + "type": "string" + }, + "protocolFeeAmountUsd": { + "type": "string" + }, + "orchestratorPayerFeeAmountUsd": { + "type": "string" + }, + "orchestratorRecipientFeeAmountUsd": { + "type": "string" + }, + "feeAmountsUsdUnavailableReason": { + "type": "string", + "enum": [ + "fee_plan_unavailable" + ] + }, + "numberOfPaymentsExcludingFees": { + "type": "integer", + "minimum": 0 + }, + "destinationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "payoutKytProvider": { + "type": "string" + } + }, + "description": "Vendor-neutral analytics metadata that SPP maps into Mixpanel shared properties. Amount values are decimal USD strings to avoid frontend precision loss." + }, + "requestIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request Network request IDs represented by this payment" + }, + "payees": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of payee wallet addresses. Order matches amounts and paymentCurrencies arrays." + }, + "network": { + "type": "string", + "description": "Blockchain network" + }, + "amounts": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of payment amounts. Order matches payees and paymentCurrencies arrays." + }, + "paymentCurrencies": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of payment currency IDs. Order matches payees and amounts arrays. Each index corresponds to one payment request." + }, + "isNativeCurrency": { + "type": "array", + "items": { + "type": "boolean" + }, + "description": "Array indicating whether each payment currency is native. Order matches payees, amounts, and paymentCurrencies arrays." + }, + "destinations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "destinationId": { + "type": "string", + "description": "Composite destination ID: ERC-7828 payee address + token address (e.g., '0x742d...bEb0@eip155:11155111#80B12379:0x370D...623C'). Omitted when payee-address fields are masked." + }, + "payeeAddress": { + "type": "string", + "description": "Payee address in ERC-7828 human-readable format" + }, + "tokenAddress": { + "type": "string", + "description": "ERC20 token contract address" + }, + "walletAddress": { + "type": "string", + "description": "Raw wallet address" + }, + "network": { + "type": "string", + "description": "Blockchain network name" + }, + "isMasked": { + "type": "boolean", + "description": "Whether payee-address fields in this destination are intentionally masked" + } + }, + "required": [ + "payeeAddress", + "tokenAddress", + "walletAddress", + "network" + ], + "nullable": true + }, + "description": "Resolved destinations for each payment in the batch. Order matches payees array. Entries may be null when a payment is not linked to a stored destination." + }, + "reference": { + "type": "string", + "description": "Merchant reference for the payment", + "nullable": true + }, + "isPayeeAddressMasked": { + "type": "boolean", + "description": "Whether payee-address fields are intentionally masked until access is approved" + }, + "feePlan": { + "allOf": [ + { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Fee plan snapshot captured at creation time. Null when fees don't apply (non-stablecoin currency, payment created before fee plan rollout, etc.).", + "nullable": true + }, + { + "description": "Fee plan snapshot captured at creation time. Null when fees don't apply (non-stablecoin currency, multi-currency batch, payment created before fee plan rollout, etc.)." + } + ] + }, + "accessDecision": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "approved", + "rejected", + "error" + ] + }, + "reasonCode": { + "type": "string" + }, + "provider": { + "type": "string", + "nullable": true + }, + "walletResults": { + "type": "array", + "items": { + "type": "object", + "properties": { + "walletAddress": { + "type": "string" + }, + "walletType": { + "type": "string", + "enum": [ + "eoa", + "smart_account" + ] + }, + "parentWalletAddress": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string", + "enum": [ + "approved", + "rejected", + "error" + ] + }, + "reasonCode": { + "type": "string" + }, + "provider": { + "type": "string", + "nullable": true + }, + "evaluatedAt": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "walletAddress", + "walletType", + "status", + "reasonCode", + "provider" + ] + } + } + }, + "required": [ + "status", + "reasonCode", + "provider", + "walletResults" + ] + } + }, + "required": [ + "paymentType", + "status", + "redirectUrl", + "redirectLabel", + "branding", + "requestIds", + "payees", + "network", + "amounts", + "paymentCurrencies", + "isNativeCurrency", + "destinations", + "reference", + "feePlan" + ] + }, + { + "type": "object", + "properties": { + "paymentType": { + "type": "string", + "enum": [ + "single", + "batch" + ] + }, + "status": { + "type": "string", + "enum": [ + "pending", + "completed", + "expired", + "invalidated", + "compliance_failed" + ] + }, + "redirectUrl": { + "type": "string", + "description": "Optional redirect URL configured at creation time. Null when no redirect was set.", + "nullable": true + }, + "redirectLabel": { + "type": "string", + "description": "Optional label describing the redirect destination. Null when no label was provided.", + "nullable": true + }, + "orchestratorId": { + "type": "string", + "description": "Orchestrator ID associated with the secure payment, if any", + "nullable": true + }, + "branding": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "clientIdId": { + "type": "string" + }, + "orchestratorId": { + "type": "string" + }, + "logoPath": { + "type": "string" + }, + "pageBackgroundColor": { + "type": "string" + }, + "cardBackgroundColor": { + "type": "string" + }, + "primaryActionColor": { + "type": "string" + }, + "primaryTextColor": { + "type": "string" + }, + "secondaryTextColor": { + "type": "string" + }, + "termsPath": { + "type": "string" + }, + "privacyPath": { + "type": "string" + }, + "displayRequestBranding": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "nullable": true + }, + "paymentOptions": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "balance": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + }, + "neededAmount": { + "type": "string" + } + }, + "required": [ + "balance", + "hasEnoughBalance", + "neededAmount" + ] + } + } + }, + "analytics": { + "type": "object", + "properties": { + "creationTimestamp": { + "type": "string", + "format": "date-time" + }, + "totalPaymentAmountUsd": { + "type": "string" + }, + "protocolFeeAmountUsd": { + "type": "string" + }, + "orchestratorPayerFeeAmountUsd": { + "type": "string" + }, + "orchestratorRecipientFeeAmountUsd": { + "type": "string" + }, + "feeAmountsUsdUnavailableReason": { + "type": "string", + "enum": [ + "fee_plan_unavailable" + ] + }, + "numberOfPaymentsExcludingFees": { + "type": "integer", + "minimum": 0 + }, + "destinationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "payoutKytProvider": { + "type": "string" + } + }, + "description": "Vendor-neutral analytics metadata that SPP maps into Mixpanel shared properties. Amount values are decimal USD strings to avoid frontend precision loss." + }, + "accessDecision": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "approved", + "rejected", + "error" + ] + }, + "reasonCode": { + "type": "string" + }, + "provider": { + "type": "string", + "nullable": true + }, + "walletResults": { + "type": "array", + "items": { + "type": "object", + "properties": { + "walletAddress": { + "type": "string" + }, + "walletType": { + "type": "string", + "enum": [ + "eoa", + "smart_account" + ] + }, + "parentWalletAddress": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string", + "enum": [ + "approved", + "rejected", + "error" + ] + }, + "reasonCode": { + "type": "string" + }, + "provider": { + "type": "string", + "nullable": true + }, + "evaluatedAt": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string" + } + ] + } + }, + "required": [ + "walletAddress", + "walletType", + "status", + "reasonCode", + "provider" + ] + } + } + }, + "required": [ + "status", + "reasonCode", + "provider", + "walletResults" + ] + } + }, + "required": [ + "paymentType", + "status", + "branding" + ] + }, + { + "type": "object", + "properties": { + "paymentType": { + "type": "string", + "enum": [ + "multicall" + ] + }, + "status": { + "type": "string", + "enum": [ + "pending", + "expired", + "completed", + "partially_settled" + ] + }, + "redirectUrl": { + "type": "string", + "nullable": true + }, + "redirectLabel": { + "type": "string", + "nullable": true + }, + "orchestratorId": { + "type": "string", + "nullable": true + }, + "branding": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "clientIdId": { + "type": "string" + }, + "orchestratorId": { + "type": "string" + }, + "logoPath": { + "type": "string" + }, + "pageBackgroundColor": { + "type": "string" + }, + "cardBackgroundColor": { + "type": "string" + }, + "primaryActionColor": { + "type": "string" + }, + "primaryTextColor": { + "type": "string" + }, + "secondaryTextColor": { + "type": "string" + }, + "termsPath": { + "type": "string" + }, + "privacyPath": { + "type": "string" + }, + "displayRequestBranding": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "nullable": true + }, + "paymentOptions": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "balance": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + }, + "neededAmount": { + "type": "string" + } + }, + "required": [ + "balance", + "hasEnoughBalance", + "neededAmount" + ] + } + } + }, + "analytics": { + "type": "object", + "properties": { + "creationTimestamp": { + "type": "string", + "format": "date-time" + }, + "totalPaymentAmountUsd": { + "type": "string" + }, + "protocolFeeAmountUsd": { + "type": "string" + }, + "orchestratorPayerFeeAmountUsd": { + "type": "string" + }, + "orchestratorRecipientFeeAmountUsd": { + "type": "string" + }, + "feeAmountsUsdUnavailableReason": { + "type": "string", + "enum": [ + "fee_plan_unavailable" + ] + }, + "numberOfPaymentsExcludingFees": { + "type": "integer", + "minimum": 0 + }, + "destinationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "payoutKytProvider": { + "type": "string" + } + }, + "description": "Vendor-neutral analytics metadata that SPP maps into Mixpanel shared properties. Amount values are decimal USD strings to avoid frontend precision loss." + }, + "requestIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request Network request IDs represented by this payment" + }, + "token": { + "type": "string", + "description": "Multicall payout token" + }, + "canExecute": { + "type": "boolean" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "children": { + "type": "array", + "items": { + "type": "object", + "properties": { + "securePaymentToken": { + "type": "string", + "description": "Child secure-payment token" + }, + "requestId": { + "type": "string", + "description": "Request Network request ID for the child payout" + }, + "position": { + "type": "integer", + "minimum": 0, + "description": "0-indexed child order" + }, + "executable": { + "type": "boolean", + "description": "Whether this child can currently be executed in the multicall" + }, + "blockReason": { + "type": "string", + "enum": [ + "not_found", + "not_owned", + "not_outgoing", + "not_single_payment", + "invalid_child_linkage", + "already_paid", + "request_processing", + "secure_payment_expired", + "secure_payment_not_pending", + "compliance_failed", + "not_payable_child" + ], + "description": "Structured reason when executable is false; otherwise null", + "nullable": true + }, + "messageKey": { + "type": "string", + "description": "Stable localized-message key for the block reason", + "nullable": true + }, + "context": { + "type": "object", + "properties": { + "requestId": { + "type": "string" + }, + "securePaymentToken": { + "type": "string" + }, + "position": { + "type": "integer", + "minimum": 0 + }, + "hasBeenPaid": { + "type": "boolean" + }, + "securePaymentStatus": { + "type": "string" + }, + "requestStatus": { + "type": "string" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "network": { + "type": "string" + }, + "currency": { + "type": "string" + } + }, + "required": [ + "requestId", + "securePaymentToken", + "position", + "hasBeenPaid" + ], + "description": "Per-child block context used by SPP to render recovery details" + }, + "recoveryAction": { + "type": "string", + "enum": [ + "remove_child", + "recreate_reduced", + "wait_for_quote_refresh", + "switch_route", + "recreate_after_cooldown", + "support_required" + ], + "description": "Suggested recovery action when the child is blocked", + "nullable": true + }, + "feePlan": { + "allOf": [ + { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Fee plan snapshot captured at creation time. Null when fees don't apply (non-stablecoin currency, payment created before fee plan rollout, etc.).", + "nullable": true + }, + { + "description": "Persisted child fee-plan snapshot. Null when fees do not apply or no snapshot exists." + } + ] + }, + "amount": { + "type": "string", + "description": "Human-readable child amount in the child's payment currency. Null when unavailable.", + "nullable": true + }, + "payee": { + "type": "string", + "description": "Resolved child recipient address. Null when unavailable.", + "nullable": true + }, + "reference": { + "type": "string", + "description": "Merchant reference for the child payment. Null when none was provided.", + "nullable": true + } + }, + "required": [ + "securePaymentToken", + "requestId", + "position", + "executable", + "blockReason", + "messageKey", + "context", + "recoveryAction", + "feePlan", + "amount", + "payee", + "reference" + ] + } + }, + "totals": { + "type": "object", + "properties": { + "childCount": { + "type": "integer", + "minimum": 0 + }, + "blockedChildCount": { + "type": "integer", + "minimum": 0 + }, + "byDestinationCurrency": { + "type": "array", + "items": { + "type": "object", + "properties": { + "network": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "totalAmount": { + "type": "string" + } + }, + "required": [ + "network", + "currency", + "totalAmount" + ] + } + }, + "amountSummary": { + "type": "object", + "properties": { + "grossAmount": { + "type": "string" + }, + "netRecipientAmount": { + "type": "string" + }, + "totalFees": { + "type": "string" + }, + "payeeBorneFees": { + "type": "string" + }, + "payerBorneFees": { + "type": "string" + }, + "payerTotal": { + "type": "string" + } + }, + "required": [ + "grossAmount", + "netRecipientAmount", + "totalFees", + "payeeBorneFees", + "payerBorneFees", + "payerTotal" + ] + } + }, + "required": [ + "childCount", + "blockedChildCount", + "byDestinationCurrency", + "amountSummary" + ] + } + }, + "required": [ + "paymentType", + "status", + "redirectUrl", + "redirectLabel", + "orchestratorId", + "branding", + "analytics", + "requestIds", + "token", + "canExecute", + "expiresAt", + "createdAt", + "children", + "totals" + ] + } + ] + }, + "examples": { + "singlePayment": { + "summary": "Single payment response", + "value": { + "paymentType": "single", + "payee": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7", + "network": "sepolia", + "amount": "10000000000000000000", + "paymentCurrency": "FAU-sepolia", + "status": "pending", + "destination": { + "destinationId": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "payeeAddress": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4", + "tokenAddress": "0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "walletAddress": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7", + "network": "sepolia" + }, + "reference": "INV-2025-001" + } + }, + "batchPayment": { + "summary": "Batch payment response", + "value": { + "paymentType": "batch", + "payees": [ + "0xb07d2398d2004378cad234da0ef14f1c94a530e4", + "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7" + ], + "network": "sepolia", + "amounts": [ + "50", + "10" + ], + "paymentCurrencies": [ + "FAU-sepolia", + "FAU-sepolia" + ], + "status": "pending", + "destinations": [ + { + "destinationId": "0xb07d2398d2004378cad234da0ef14f1c94a530e4@eip155:11155111#C3D4E5F6:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "payeeAddress": "0xb07d2398d2004378cad234da0ef14f1c94a530e4@eip155:11155111#C3D4E5F6", + "tokenAddress": "0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "walletAddress": "0xb07d2398d2004378cad234da0ef14f1c94a530e4", + "network": "sepolia" + }, + { + "destinationId": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "payeeAddress": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4", + "tokenAddress": "0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "walletAddress": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7", + "network": "sepolia" + } + ], + "reference": "BATCH-REF-001" + } + } + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Secure payment token expired or invalid status" + }, + "404": { + "description": "Secure payment not found" + }, + "409": { + "description": "Secure payment has already been completed", + "content": { + "application/json": { + "examples": { + "alreadyPaid": { + "summary": "Payment already completed", + "value": { + "message": "Secure payment has already been completed", + "status": "completed", + "branding": { + "id": "brand_1", + "clientIdId": "client_1", + "logoPath": "/branding/client/logo.png", + "pageBackgroundColor": "#ffffff", + "cardBackgroundColor": "#ffffff", + "primaryActionColor": "#00d395", + "primaryTextColor": "#475569", + "secondaryTextColor": "#94a3b8", + "termsPath": "/branding/client/terms.html", + "privacyPath": "/branding/client/privacy.html", + "displayRequestBranding": false + }, + "requestStatuses": [ + { + "requestId": "01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cdb", + "hasBeenPaid": true, + "txHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" + } + ] + } + } + } + } + } + }, + "423": { + "description": "Secure payment is in progress", + "content": { + "application/json": { + "examples": { + "paymentInProgress": { + "summary": "Secure payment is in progress", + "value": { + "message": "Secure payment is in progress", + "status": "pending", + "branding": { + "id": "brand_1", + "clientIdId": "client_1", + "logoPath": "/branding/client/logo.png", + "pageBackgroundColor": "#ffffff", + "cardBackgroundColor": "#ffffff", + "primaryActionColor": "#00d395", + "primaryTextColor": "#475569", + "secondaryTextColor": "#94a3b8", + "termsPath": "/branding/client/terms.html", + "privacyPath": "/branding/client/privacy.html", + "displayRequestBranding": false + }, + "requestStatuses": [ + { + "requestId": "01e273ecc29d4b526df3a0f1f05ffc59372af8752c2b678096e49ac270416a7cdb", + "hasBeenPaid": false, + "safeTxHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "chainId": 137, + "safePaymentDeadline": 1749760800 + } + ] + } + } + } + } + } + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Get secure payment data by token", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/{token}/pay": { + "get": { + "description": "Retrieves executable payment calldata for a secure payment token. When chain and token are provided, the backend prepares a crosschain payment for the selected source asset; otherwise it returns the existing same-chain or batch payment calldata.", + "operationId": "SecurePaymentController_getSecurePaymentCalldataByToken_v2", + "parameters": [ + { + "name": "token", + "in": "path", + "description": "Secure payment token (ULID) returned by POST /v2/secure-payments, POST /v2/secure-payments/payouts, or POST /v2/secure-payments/multicall-payouts. Distinct from the `token` query parameter, which selects the crosschain source currency.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "token", + "required": false, + "in": "query", + "description": "The source token of the crosschain payment. Pair with `chain`; both must be sent together. Not the secure payment token \u2014 that is the `{token}` path parameter.", + "schema": { + "enum": [ + "USDC", + "USDT", + "EURC", + "USDT0" + ], + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (automatically set by browser)", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "wallet", + "required": false, + "in": "query", + "description": "The wallet address of the payer (optional, used to check existing approvals)", + "schema": { + "example": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7", + "type": "string" + } + }, + { + "name": "chain", + "required": false, + "in": "query", + "description": "The source chain of the crosschain payment", + "schema": { + "enum": [ + "BASE", + "OPTIMISM", + "ARBITRUM", + "ETHEREUM", + "POLYGON", + "BNB" + ], + "type": "string" + } + }, + { + "name": "eoaWallet", + "required": false, + "in": "query", + "description": "The EOA wallet address that holds the funds. When provided, balance checks and LiFi quotes use this address while the wallet param is used for calldata building (smart account flow).", + "schema": { + "type": "string" + } + }, + { + "name": "isSafe", + "required": false, + "in": "query", + "description": "When true, prepares calldata for a Gnosis Safe multisig payer (wallet must be the Safe address). Mutually exclusive with eoaWallet.", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + } + } + ], + "responses": { + "200": { + "description": "Secure payment calldata retrieved successfully", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "paymentType": { + "type": "string", + "enum": [ + "single" + ] + }, + "transactions": { + "type": "array", + "items": {}, + "description": "Flat ordered list of calls the smart account must execute atomically. Main-payment transactions come first; fee-payment transactions follow." + }, + "eoaApprovalTransactions": { + "type": "array", + "items": {} + }, + "feeBundle": { + "type": "object", + "properties": { + "bundleId": { + "type": "string", + "description": "ID of the secure_payment_bundle row. Null when fees are described by the plan snapshot but no on-chain bundle was created (e.g. no payer wallet supplied yet).", + "nullable": true + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ], + "nullable": true + }, + "amountSummary": { + "type": "object", + "properties": { + "grossAmount": { + "type": "string" + }, + "netRecipientAmount": { + "type": "string" + }, + "totalFees": { + "type": "string" + }, + "payeeBorneFees": { + "type": "string" + }, + "payerBorneFees": { + "type": "string" + }, + "payerTotal": { + "type": "string" + } + }, + "required": [ + "grossAmount", + "netRecipientAmount", + "totalFees", + "payeeBorneFees", + "payerBorneFees", + "payerTotal" + ], + "nullable": true + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "requestId": { + "type": "string" + }, + "feeComponentId": { + "type": "string", + "nullable": true + }, + "feeType": { + "type": "string", + "nullable": true + }, + "feeLabel": { + "type": "string", + "nullable": true + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ], + "nullable": true + }, + "amount": { + "type": "string" + }, + "paymentCurrencyId": { + "type": "string" + }, + "network": { + "type": "string" + }, + "chainId": { + "type": "string" + }, + "recipient": { + "type": "string" + } + }, + "required": [ + "requestId", + "feeComponentId", + "feeType", + "feeLabel", + "feeBearer", + "amount", + "paymentCurrencyId", + "network", + "chainId", + "recipient" + ] + }, + "description": "One entry per fee leg appended to transactions[]. Order matches the order of fee transactions inside transactions[]." + } + }, + "required": [ + "bundleId", + "defaultFeeBearer", + "amountSummary", + "fees" + ], + "description": "Fee bundle summary for this payment. Null when no fee plan applies.", + "nullable": true + }, + "metadata": { + "type": "object", + "properties": { + "stepsRequired": { + "type": "number" + }, + "needsApproval": { + "type": "boolean" + }, + "transactionSponsorshipFeeUsd": { + "type": "string", + "nullable": true + }, + "approvalTransactionIndex": { + "type": "number" + }, + "approvalTransactionsCount": { + "type": "number" + }, + "paymentTransactionIndex": { + "type": "number" + }, + "hasEnoughBalance": { + "type": "boolean" + }, + "hasEnoughGas": { + "type": "boolean" + }, + "hasEnoughAllowance": { + "type": "boolean" + }, + "platformFee": { + "type": "object", + "properties": { + "percentage": { + "type": "string" + }, + "address": { + "type": "string" + } + }, + "required": [ + "percentage", + "address" + ] + }, + "protocolFee": { + "type": "object", + "properties": { + "percentage": { + "type": "string" + }, + "address": { + "type": "string" + } + }, + "required": [ + "percentage", + "address" + ] + }, + "eoaApprovalRequired": { + "type": "boolean" + }, + "eoaApproval": { + "type": "object", + "properties": { + "owner": { + "type": "string" + }, + "spender": { + "type": "string" + }, + "tokenAddress": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "amount": { + "type": "string" + }, + "approvalType": { + "type": "string", + "enum": [ + "unlimited" + ] + } + }, + "required": [ + "owner", + "spender", + "tokenAddress", + "currency", + "amount", + "approvalType" + ] + }, + "balance": { + "type": "string" + }, + "allowance": { + "type": "string" + }, + "requiredAmount": { + "type": "string" + }, + "nativeBalance": { + "type": "string" + }, + "estimatedNetworkFee": { + "type": "string" + }, + "estimatedNetworkFeeUsd": { + "type": "string" + }, + "estimatedApprovalNetworkFee": { + "type": "string" + }, + "estimatedApprovalNetworkFeeUsd": { + "type": "string" + }, + "estimatedPaymentNetworkFee": { + "type": "string" + }, + "estimatedPaymentNetworkFeeUsd": { + "type": "string" + }, + "approvalFeeLimit": { + "type": "string" + }, + "paymentFeeLimit": { + "type": "string" + }, + "sourceAmount": { + "type": "string" + }, + "routeType": { + "type": "string", + "enum": [ + "crosschain", + "samechain" + ] + }, + "quoteFetchedAt": { + "type": "string", + "format": "date-time" + }, + "quoteExpiresAt": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "format": "date-time" + } + ], + "description": "Route quote expiry. Legacy single-payment routes may return a Unix timestamp; multicall cross-chain routes return an ISO date-time string." + }, + "executionDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Unix seconds \u2014 hard on-chain execution window for Safe + LiFi routes (min of bridge and swap deadlines). Advisory only.", + "minimum": 0 + }, + "executionDeadlineBreakdown": { + "type": "object", + "properties": { + "bridge": { + "type": "object", + "properties": { + "deadline": { + "type": "integer", + "exclusiveMinimum": true, + "minimum": 0 + }, + "source": { + "type": "string", + "enum": [ + "decoded", + "fallback" + ] + } + }, + "required": [ + "deadline", + "source" + ] + }, + "swap": { + "type": "object", + "properties": { + "deadline": { + "type": "integer", + "exclusiveMinimum": true, + "minimum": 0 + }, + "tool": { + "type": "string" + }, + "source": { + "type": "string", + "enum": [ + "decoded", + "fallback" + ] + } + }, + "required": [ + "deadline", + "source" + ] + } + }, + "description": "Per-leg deadline breakdown for Safe + LiFi execution window computation." + }, + "safePaymentDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Unix seconds \u2014 hard on-chain Safe execution window for the selected route.", + "minimum": 0 + }, + "rawStep": { + "type": "object", + "additionalProperties": {} + }, + "costBreakdown": { + "type": "object", + "properties": { + "approvalFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amountNative": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amountNative", + "hasEnoughBalance" + ] + }, + "paymentGasFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amountNative": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amountNative", + "hasEnoughBalance" + ] + }, + "totalGasFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amountNative": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amountNative", + "hasEnoughBalance" + ] + }, + "bridgeFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amount": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amount", + "hasEnoughBalance" + ] + }, + "fundingStatus": { + "type": "object", + "properties": { + "hasEnoughPaymentToken": { + "type": "boolean" + }, + "hasEnoughApprovalGas": { + "type": "boolean" + }, + "hasEnoughOverall": { + "type": "boolean" + } + }, + "required": [ + "hasEnoughPaymentToken", + "hasEnoughApprovalGas", + "hasEnoughOverall" + ] + }, + "totals": { + "type": "object", + "properties": { + "paymentAmount": { + "type": "string" + }, + "paymentCurrency": { + "type": "string" + }, + "sourceAmount": { + "type": "string" + } + }, + "required": [ + "paymentAmount", + "paymentCurrency", + "sourceAmount" + ] + } + }, + "required": [ + "fundingStatus" + ] + } + }, + "required": [ + "stepsRequired", + "needsApproval", + "paymentTransactionIndex" + ] + } + }, + "required": [ + "paymentType", + "transactions", + "feeBundle", + "metadata" + ] + }, + { + "type": "object", + "properties": { + "ERC20ApprovalTransactions": { + "type": "array", + "items": {} + }, + "batchPaymentTransaction": {}, + "metadata": { + "type": "object", + "properties": { + "hasEnoughBalance": { + "type": "boolean" + }, + "hasEnoughGas": { + "type": "boolean", + "nullable": true + }, + "canMakePayment": { + "type": "boolean", + "nullable": true + }, + "insufficientTokens": { + "type": "array", + "items": { + "type": "object", + "properties": { + "tokenAddress": { + "type": "string" + }, + "tokenSymbol": { + "type": "string" + }, + "paymentCurrencyId": { + "type": "string" + }, + "required": { + "type": "string" + }, + "available": { + "type": "string" + } + }, + "required": [ + "tokenAddress", + "required", + "available" + ] + } + } + }, + "required": [ + "hasEnoughBalance" + ] + } + }, + "required": [ + "ERC20ApprovalTransactions" + ] + }, + { + "type": "object", + "properties": { + "paymentType": { + "type": "string", + "enum": [ + "multicall" + ] + }, + "transactions": { + "type": "array", + "items": {}, + "description": "Flat ordered list of calls the smart account must execute atomically. Main-payment transactions come first; fee-payment transactions follow." + }, + "eoaApprovalTransactions": { + "type": "array", + "items": {} + }, + "feeBundle": { + "type": "object", + "properties": { + "bundleId": { + "type": "string", + "description": "ID of the secure_payment_bundle row. Null when fees are described by the plan snapshot but no on-chain bundle was created (e.g. no payer wallet supplied yet).", + "nullable": true + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ], + "nullable": true + }, + "amountSummary": { + "type": "object", + "properties": { + "grossAmount": { + "type": "string" + }, + "netRecipientAmount": { + "type": "string" + }, + "totalFees": { + "type": "string" + }, + "payeeBorneFees": { + "type": "string" + }, + "payerBorneFees": { + "type": "string" + }, + "payerTotal": { + "type": "string" + } + }, + "required": [ + "grossAmount", + "netRecipientAmount", + "totalFees", + "payeeBorneFees", + "payerBorneFees", + "payerTotal" + ], + "nullable": true + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "requestId": { + "type": "string" + }, + "feeComponentId": { + "type": "string", + "nullable": true + }, + "feeType": { + "type": "string", + "nullable": true + }, + "feeLabel": { + "type": "string", + "nullable": true + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ], + "nullable": true + }, + "amount": { + "type": "string" + }, + "paymentCurrencyId": { + "type": "string" + }, + "network": { + "type": "string" + }, + "chainId": { + "type": "string" + }, + "recipient": { + "type": "string" + } + }, + "required": [ + "requestId", + "feeComponentId", + "feeType", + "feeLabel", + "feeBearer", + "amount", + "paymentCurrencyId", + "network", + "chainId", + "recipient" + ] + }, + "description": "One entry per fee leg appended to transactions[]. Order matches the order of fee transactions inside transactions[]." + } + }, + "required": [ + "bundleId", + "defaultFeeBearer", + "amountSummary", + "fees" + ], + "description": "Fee bundle summary for this payment. Null when no fee plan applies.", + "nullable": true + }, + "executionKind": { + "type": "string", + "enum": [ + "evm_same_chain", + "evm_cross_chain" + ] + }, + "token": { + "type": "string", + "description": "Multicall parent secure-payment token" + }, + "network": { + "type": "string", + "description": "Same-chain destination network" + }, + "chainId": { + "type": "integer" + }, + "childTokens": { + "type": "array", + "items": { + "type": "string" + } + }, + "requestIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "children": { + "type": "array", + "items": { + "type": "object", + "properties": { + "position": { + "type": "integer", + "minimum": 0 + }, + "securePaymentToken": { + "type": "string" + }, + "requestId": { + "type": "string" + }, + "payee": { + "type": "string" + }, + "amount": { + "type": "string" + }, + "paymentCurrency": { + "type": "string" + }, + "paymentReference": { + "type": "string", + "nullable": true + }, + "paymentCurrencyAddress": { + "type": "string", + "nullable": true + }, + "sourceTokenAddress": { + "type": "string", + "nullable": true + }, + "tokenAddress": { + "type": "string", + "nullable": true + }, + "network": { + "type": "string" + }, + "destinationCall": { + "type": "object", + "properties": { + "network": { + "type": "string", + "description": "Destination Request Network chain name" + }, + "chain": { + "type": "string", + "description": "Destination LI.FI chain identifier from the proven quote" + }, + "chainId": { + "type": "integer" + }, + "target": { + "type": "string", + "description": "Alias of contractAddress for SPP destination-call validation" + }, + "contractAddress": { + "type": "string", + "description": "Request Network ERC20 payment proxy on the destination chain" + }, + "calldata": { + "type": "string", + "description": "RN proxy calldata proven against the LI.FI contract-call quote" + } + }, + "required": [ + "network", + "chain", + "target", + "contractAddress", + "calldata" + ], + "description": "Cross-chain only. Decoded destination-chain RN proxy call that SPP validates before enabling Pay." + } + }, + "required": [ + "position", + "securePaymentToken", + "requestId", + "payee", + "amount", + "paymentCurrency", + "paymentReference", + "paymentCurrencyAddress", + "sourceTokenAddress", + "tokenAddress", + "network" + ] + } + }, + "payees": { + "type": "array", + "items": { + "type": "string" + } + }, + "amounts": { + "type": "array", + "items": { + "type": "string" + } + }, + "references": { + "type": "array", + "items": { + "type": "string", + "nullable": true + } + }, + "ERC20ApprovalTransactions": { + "type": "array", + "items": {} + }, + "batchPaymentTransaction": {}, + "destinationCalls": { + "type": "array", + "items": { + "type": "object", + "properties": { + "network": { + "type": "string", + "description": "Destination Request Network chain name" + }, + "chain": { + "type": "string", + "description": "Destination LI.FI chain identifier from the proven quote" + }, + "chainId": { + "type": "integer" + }, + "target": { + "type": "string", + "description": "Alias of contractAddress for SPP destination-call validation" + }, + "contractAddress": { + "type": "string", + "description": "Request Network ERC20 payment proxy on the destination chain" + }, + "calldata": { + "type": "string", + "description": "RN proxy calldata proven against the LI.FI contract-call quote" + } + }, + "required": [ + "network", + "chain", + "target", + "contractAddress", + "calldata" + ] + }, + "description": "Cross-chain only. Top-level mirror of children[].destinationCall for validation diagnostics." + }, + "metadata": { + "type": "object", + "properties": { + "stepsRequired": { + "type": "number" + }, + "needsApproval": { + "type": "boolean" + }, + "transactionSponsorshipFeeUsd": { + "type": "string", + "nullable": true + }, + "approvalTransactionIndex": { + "type": "number" + }, + "approvalTransactionsCount": { + "type": "number" + }, + "paymentTransactionIndex": { + "type": "number" + }, + "hasEnoughBalance": { + "type": "boolean" + }, + "hasEnoughGas": { + "type": "boolean" + }, + "hasEnoughAllowance": { + "type": "boolean" + }, + "platformFee": { + "type": "object", + "properties": { + "percentage": { + "type": "string" + }, + "address": { + "type": "string" + } + }, + "required": [ + "percentage", + "address" + ] + }, + "protocolFee": { + "type": "object", + "properties": { + "percentage": { + "type": "string" + }, + "address": { + "type": "string" + } + }, + "required": [ + "percentage", + "address" + ] + }, + "eoaApprovalRequired": { + "type": "boolean" + }, + "eoaApproval": { + "type": "object", + "properties": { + "owner": { + "type": "string" + }, + "spender": { + "type": "string" + }, + "tokenAddress": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "amount": { + "type": "string" + }, + "approvalType": { + "type": "string", + "enum": [ + "unlimited" + ] + } + }, + "required": [ + "owner", + "spender", + "tokenAddress", + "currency", + "amount", + "approvalType" + ] + }, + "balance": { + "type": "string" + }, + "allowance": { + "type": "string" + }, + "requiredAmount": { + "type": "string" + }, + "nativeBalance": { + "type": "string" + }, + "estimatedNetworkFee": { + "type": "string" + }, + "estimatedNetworkFeeUsd": { + "type": "string" + }, + "estimatedApprovalNetworkFee": { + "type": "string" + }, + "estimatedApprovalNetworkFeeUsd": { + "type": "string" + }, + "estimatedPaymentNetworkFee": { + "type": "string" + }, + "estimatedPaymentNetworkFeeUsd": { + "type": "string" + }, + "approvalFeeLimit": { + "type": "string" + }, + "paymentFeeLimit": { + "type": "string" + }, + "sourceAmount": { + "type": "string" + }, + "routeType": { + "type": "string", + "enum": [ + "crosschain", + "samechain" + ] + }, + "quoteFetchedAt": { + "type": "string", + "format": "date-time" + }, + "quoteExpiresAt": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "format": "date-time" + } + ], + "description": "Route quote expiry. Legacy single-payment routes may return a Unix timestamp; multicall cross-chain routes return an ISO date-time string." + }, + "executionDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Unix seconds \u2014 hard on-chain execution window for Safe + LiFi routes (min of bridge and swap deadlines). Advisory only.", + "minimum": 0 + }, + "executionDeadlineBreakdown": { + "type": "object", + "properties": { + "bridge": { + "type": "object", + "properties": { + "deadline": { + "type": "integer", + "exclusiveMinimum": true, + "minimum": 0 + }, + "source": { + "type": "string", + "enum": [ + "decoded", + "fallback" + ] + } + }, + "required": [ + "deadline", + "source" + ] + }, + "swap": { + "type": "object", + "properties": { + "deadline": { + "type": "integer", + "exclusiveMinimum": true, + "minimum": 0 + }, + "tool": { + "type": "string" + }, + "source": { + "type": "string", + "enum": [ + "decoded", + "fallback" + ] + } + }, + "required": [ + "deadline", + "source" + ] + } + }, + "description": "Per-leg deadline breakdown for Safe + LiFi execution window computation." + }, + "safePaymentDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Unix seconds \u2014 hard on-chain Safe execution window for the selected route.", + "minimum": 0 + }, + "rawStep": { + "type": "object", + "additionalProperties": {} + }, + "costBreakdown": { + "type": "object", + "properties": { + "approvalFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amountNative": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amountNative", + "hasEnoughBalance" + ] + }, + "paymentGasFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amountNative": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amountNative", + "hasEnoughBalance" + ] + }, + "totalGasFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amountNative": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amountNative", + "hasEnoughBalance" + ] + }, + "bridgeFee": { + "type": "object", + "properties": { + "required": { + "type": "boolean" + }, + "currency": { + "type": "string" + }, + "amount": { + "type": "string" + }, + "amountUsd": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + } + }, + "required": [ + "required", + "currency", + "amount", + "hasEnoughBalance" + ] + }, + "fundingStatus": { + "type": "object", + "properties": { + "hasEnoughPaymentToken": { + "type": "boolean" + }, + "hasEnoughApprovalGas": { + "type": "boolean" + }, + "hasEnoughOverall": { + "type": "boolean" + } + }, + "required": [ + "hasEnoughPaymentToken", + "hasEnoughApprovalGas", + "hasEnoughOverall" + ] + }, + "totals": { + "type": "object", + "properties": { + "paymentAmount": { + "type": "string" + }, + "paymentCurrency": { + "type": "string" + }, + "sourceAmount": { + "type": "string" + } + }, + "required": [ + "paymentAmount", + "paymentCurrency", + "sourceAmount" + ] + } + }, + "required": [ + "fundingStatus" + ] + }, + "approvalTransactionIndices": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + }, + "batchPaymentTransactionIndex": { + "type": "integer", + "minimum": 0 + }, + "feeTransactionIndices": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + }, + "bridgeTxIndices": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + } + }, + "childCount": { + "type": "integer", + "minimum": 0 + }, + "executableLegCount": { + "type": "integer", + "minimum": 0 + }, + "aggregateAllowance": { + "type": "string" + }, + "paymentCurrencyId": { + "type": "string" + }, + "network": { + "type": "string" + }, + "bridgeSourceAmount": { + "type": "string" + }, + "sourceSideAmount": { + "type": "string" + }, + "bridgeFeeAmount": { + "type": "string" + }, + "sourceToken": { + "type": "string" + }, + "sourceTokenAddress": { + "type": "string" + }, + "sourceNetwork": { + "type": "string" + }, + "bridge": {}, + "feePlanCarried": { + "type": "boolean" + } + }, + "required": [ + "stepsRequired", + "needsApproval", + "paymentTransactionIndex", + "childCount", + "executableLegCount" + ] + } + }, + "required": [ + "paymentType", + "transactions", + "feeBundle", + "executionKind", + "token", + "childTokens", + "requestIds", + "children", + "payees", + "amounts", + "references", + "metadata" + ] + } + ] + } + } + } + }, + "400": { + "description": "Invalid secure payment calldata request" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Secure payment token expired or invalid status" + }, + "404": { + "description": "Secure payment not found" + }, + "409": { + "description": "Secure payment has already been completed" + }, + "423": { + "description": "Secure payment is in progress" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Get secure payment calldata by token", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/{token}/tron/broadcast": { + "post": { + "description": "Relays a locally signed TRON transaction for this secure payment through the configured CatFee Seamless Energy node. The backend rebuilds the expected secure-payment TRON transaction and only forwards the signed transaction if the payload matches.", + "operationId": "SecurePaymentController_broadcastTronTransaction_v2", + "parameters": [ + { + "name": "token", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (automatically set by browser)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "signedTransaction": { + "type": "object", + "properties": { + "raw_data_hex": { + "type": "string", + "pattern": "^[a-fA-F0-9]+$" + }, + "signature": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-fA-F0-9]+$" + }, + "minItems": 1 + }, + "txID": { + "type": "string", + "pattern": "^[a-fA-F0-9]{64}$" + }, + "raw_data": { + "type": "object", + "properties": { + "contract": { + "type": "array", + "items": {}, + "minItems": 1 + }, + "fee_limit": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "contract" + ] + } + }, + "required": [ + "raw_data_hex", + "signature", + "raw_data" + ], + "description": "Signed TronWeb transaction object compatible with /wallet/broadcasttransaction" + } + }, + "required": [ + "signedTransaction" + ] + } + } + } + }, + "responses": { + "200": { + "description": "TRON transaction broadcast response", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "result": { + "type": "boolean" + }, + "txid": { + "type": "string" + }, + "code": { + "type": "string" + }, + "message": { + "type": "string" + } + } + } + } + } + }, + "400": { + "description": "Invalid or mismatched TRON transaction" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Unauthorized or secure payment not payable" + }, + "404": { + "description": "Secure payment not found" + }, + "429": { + "description": "Too Many Requests" + }, + "502": { + "description": "CatFee broadcast failed" + } + }, + "summary": "Broadcast signed TRON secure payment transaction", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/{token}/refresh-step-transaction": { + "post": { + "description": "Re-stamps the bridge deadline to 'now' by calling LI.FI /advanced/stepTransaction for a previously selected route step. Call this in parallel for all steps immediately before bundling and submitting the UserOp to avoid deadline expiry.", + "operationId": "SecurePaymentController_refreshStepTransaction_v2", + "parameters": [ + { + "name": "token", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (automatically set by browser)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "step": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "tool": { + "type": "string" + }, + "action": { + "type": "object", + "properties": { + "toChainId": { + "type": "number" + }, + "toAddress": { + "type": "string", + "pattern": "^0x[0-9a-fA-F]{40}$" + } + }, + "required": [ + "toChainId", + "toAddress" + ] + } + }, + "required": [ + "id", + "type", + "tool", + "action" + ], + "description": "LI.FI route step object from /advanced/routes" + } + }, + "required": [ + "step" + ] + } + } + } + }, + "responses": { + "200": { + "description": "Fresh transactionRequest returned" + }, + "400": { + "description": "Route no longer available or invalid step" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Unauthorized" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Refresh bridge step transactionRequest", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/{token}/intent": { + "post": { + "description": "Records source-side execution metadata after the payer broadcasts a transaction. Single crosschain payments create or reuse a LiFi tracking intent. Multicall parent tokens create or reuse an audit-only execution receipt keyed by parent token and UserOperation hash; receipt rows are not consulted for settlement state.", + "operationId": "SecurePaymentController_recordIntent_v2", + "parameters": [ + { + "name": "token", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (automatically set by browser)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "txHash": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[a-fA-F0-9]{64}$" + }, + "safeTxHash": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[a-fA-F0-9]{64}$" + }, + "chain": { + "type": "string", + "enum": [ + "BASE", + "OPTIMISM", + "ARBITRUM", + "ETHEREUM", + "POLYGON", + "BNB" + ] + }, + "token": { + "type": "string", + "enum": [ + "USDC", + "USDT", + "EURC", + "USDT0" + ] + }, + "executionKind": { + "type": "string", + "enum": [ + "evm_same_chain", + "evm_cross_chain" + ] + }, + "safePaymentDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Unix seconds \u2014 hard on-chain execution deadline for the Safe + LiFi route. Only valid alongside safeTxHash; used to stop monitoring once crossed.", + "minimum": 0 + }, + "payerAddress": { + "type": "string" + }, + "payerEoaAddress": { + "type": "string" + }, + "sourceNetwork": { + "type": "string", + "enum": [ + "mainnet", + "optimism", + "bsc", + "xdai", + "fuse", + "matic", + "fantom", + "zksynceratestnet", + "zksyncera", + "core", + "moonbeam", + "mantle", + "mantle-testnet", + "tombchain", + "base", + "arbitrum-one", + "avalanche", + "base-sepolia", + "sepolia", + "tron", + "nile" + ] + }, + "sourceToken": { + "type": "string" + }, + "sourceAmount": { + "type": "string" + }, + "routeKind": { + "type": "string", + "enum": [ + "same_chain", + "same_chain_conversion", + "crosschain" + ] + }, + "bridgeTool": { + "type": "string", + "enum": [ + "across", + "stargate" + ], + "nullable": true + } + }, + "required": [ + "chain", + "token" + ] + }, + { + "type": "object", + "properties": { + "txHash": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[a-fA-F0-9]{64}$", + "description": "Bundler or source-chain transaction hash produced by the submitted UserOperation" + }, + "safeTxHash": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[a-fA-F0-9]{64}$", + "description": "Safe transaction hash when execution is still pending on-chain" + }, + "safePaymentDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Unix seconds \u2014 hard on-chain execution deadline for the Safe + multicall route. Only valid alongside safeTxHash.", + "minimum": 0 + }, + "chain": { + "type": "string", + "enum": [ + "BASE", + "OPTIMISM", + "ARBITRUM", + "ETHEREUM", + "POLYGON", + "BNB" + ], + "description": "Source chain where the multicall UserOperation was submitted" + }, + "smartAccountAddress": { + "type": "string", + "description": "Smart account that submitted the multicall UserOperation" + }, + "payerEoaAddress": { + "type": "string", + "description": "Connected EOA behind the submitted smart account" + }, + "userOpHash": { + "type": "string", + "minLength": 66, + "maxLength": 66, + "pattern": "^0x[a-fA-F0-9]{64}$", + "description": "UserOperation hash returned by the bundler" + }, + "transactionIndices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "childPosition": { + "type": "integer", + "minimum": 0, + "description": "Zero-based child position in the multicall parent" + }, + "transactionIndex": { + "type": "integer", + "minimum": 0, + "description": "Zero-based local transaction index in the submitted batch" + }, + "routeTool": { + "type": "string", + "description": "Per-child route tool from the multicall pay payload. Across bridge legs require LiFi status tracking; direct legs use normal payment detection.", + "nullable": true + }, + "sourceToken": { + "type": "string" + }, + "sourceAmount": { + "type": "string" + }, + "routeKind": { + "type": "string", + "enum": [ + "same_chain", + "same_chain_conversion", + "crosschain" + ] + }, + "bridgeTool": { + "type": "string", + "enum": [ + "across", + "stargate" + ], + "nullable": true + } + }, + "required": [ + "childPosition", + "transactionIndex" + ] + }, + "minItems": 1, + "maxItems": 250 + } + }, + "required": [ + "chain", + "smartAccountAddress", + "userOpHash", + "transactionIndices" + ] + } + ] + }, + "examples": { + "safePendingIntent": { + "summary": "Safe transaction pending on-chain execution", + "value": { + "safeTxHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "chain": "POLYGON", + "token": "USDC", + "executionKind": "evm_cross_chain", + "safePaymentDeadline": 1749760800, + "payerAddress": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Intent recorded successfully", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "object", + "properties": { + "intentId": { + "type": "string", + "description": "Tracking intent ID created or reused" + }, + "paymentReference": { + "type": "string", + "description": "Payment reference associated with the tracked request" + }, + "txHash": { + "type": "string", + "description": "Recorded source-chain transaction hash" + }, + "safeTxHash": { + "type": "string", + "description": "Recorded Safe transaction hash pending on-chain execution" + }, + "safePaymentDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Recorded Unix-seconds execution deadline for the Safe + LiFi route, when provided", + "minimum": 0 + }, + "isListening": { + "type": "boolean", + "description": "Whether the tracking intent is being monitored for status" + }, + "payerAddress": { + "type": "string" + } + }, + "required": [ + "intentId", + "paymentReference", + "isListening" + ] + }, + { + "type": "object", + "properties": { + "receiptId": { + "type": "string", + "description": "Audit receipt ID created or reused" + }, + "multicallId": { + "type": "string", + "description": "Multicall parent row ID" + }, + "parentToken": { + "type": "string", + "description": "Multicall parent token" + }, + "txHash": { + "type": "string", + "description": "Recorded source-chain transaction hash" + }, + "safeTxHash": { + "type": "string", + "description": "Recorded Safe transaction hash pending on-chain execution" + }, + "safePaymentDeadline": { + "type": "integer", + "exclusiveMinimum": true, + "description": "Recorded Unix-seconds execution deadline for the Safe + multicall route, when provided", + "minimum": 0 + }, + "sourceChain": { + "type": "string", + "enum": [ + "BASE", + "OPTIMISM", + "ARBITRUM", + "ETHEREUM", + "POLYGON", + "BNB" + ] + }, + "smartAccountAddress": { + "type": "string", + "description": "Submitting smart account" + }, + "userOpHash": { + "type": "string", + "description": "Recorded UserOperation hash" + }, + "transactionIndices": { + "type": "array", + "items": { + "type": "object", + "properties": { + "childPosition": { + "type": "integer", + "minimum": 0 + }, + "transactionIndex": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "childPosition", + "transactionIndex" + ] + } + }, + "isListening": { + "type": "boolean", + "enum": [ + false + ], + "description": "Multicall execution receipts are audit-only and not polled" + } + }, + "required": [ + "receiptId", + "multicallId", + "parentToken", + "sourceChain", + "smartAccountAddress", + "userOpHash", + "transactionIndices", + "isListening" + ] + } + ] + } + } + } + }, + "400": { + "description": "Invalid or unsupported crosschain execution payload" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Secure payment token expired or invalid status" + }, + "404": { + "description": "Secure payment not found" + }, + "409": { + "description": "Secure payment has already been completed" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Record secure payment intent", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "securePaymentsDisabled" + } + }, + "/v2/secure-payments/multicall-payouts": { + "post": { + "description": "Creates a multicall Secure Payment Page link from selected outgoing payout secure-payment tokens. This is distinct from legacy secure-payment batch links and persists only the parent token plus ordered child references.", + "operationId": "SecurePaymentMulticallController_createMulticallPayout_v2", + "parameters": [ + { + "name": "x-api-key", + "in": "header", + "description": "API key for authentication (optional if using Client ID, session, or orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-client-id", + "in": "header", + "description": "Client ID for frontend authentication (required when paired with orchestrator key)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "x-orchestrator-key", + "in": "header", + "description": "Orchestrator key for authentication (must be paired with Client ID)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "Bearer token for session authentication (or use the session_token cookie). Only consulted when no x-orchestrator-key, x-api-key, or x-client-id header is present.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Origin", + "in": "header", + "description": "Origin header (required for Client ID / orchestrator auth, automatically set by browser)", + "required": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "childTokens": { + "type": "array", + "items": { + "type": "string", + "minLength": 1 + }, + "minItems": 2, + "maxItems": 1000, + "description": "Ordered child secure-payment tokens selected for multicall payout" + }, + "requestedExecutionKind": { + "type": "string", + "enum": [ + "evm_same_chain", + "evm_cross_chain", + "tron_batch" + ], + "description": "Execution kind chosen at creation time. When omitted, stored as null \u2014 the SPP derives evm_same_chain or evm_cross_chain from the payer's source selection at payment time." + } + }, + "required": [ + "childTokens" + ], + "additionalProperties": false + }, + "examples": { + "payouts": { + "summary": "Create a multicall payout link", + "value": { + "childTokens": [ + "01JZ4PC7EXAMPLECHILD000001", + "01JZ4PC7EXAMPLECHILD000002" + ] + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Multicall payout link created successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "multicall" + ] + }, + "token": { + "type": "string", + "description": "Multicall payout token" + }, + "securePaymentUrl": { + "type": "string", + "format": "uri", + "description": "Secure Payment Page multicall URL returned on creation" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "expired" + ] + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "securePaymentToken": { + "type": "string", + "description": "Child secure-payment token" + }, + "requestId": { + "type": "string", + "description": "Request Network request ID for the child payout" + }, + "position": { + "type": "integer", + "minimum": 0, + "description": "0-indexed child order" + }, + "eligibility": { + "type": "string", + "enum": [ + "eligible", + "stale" + ] + }, + "staleReason": { + "type": "string", + "enum": [ + "secure_payment_expired", + "secure_payment_not_pending", + "already_paid", + "request_processing", + "not_payable_child" + ] + } + }, + "required": [ + "securePaymentToken", + "requestId", + "position" + ] + } + } + }, + "required": [ + "type", + "token", + "status", + "expiresAt", + "createdAt", + "items" + ] + } + } + } + }, + "400": { + "description": "Invalid multicall payout selection, including stale or ineligible child payout links" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Create a multicall payout link", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "multicallPayoutsDisabled" + } + }, + "/v2/secure-payments/multicall-payouts/{token}": { + "get": { + "description": "Retrieves the passive multicall payout details payload for Secure Payment Page rendering. It does not return quotes, calldata, wallet routes, or execution data.", + "operationId": "SecurePaymentMulticallController_getMulticallPayout_v2", + "parameters": [ + { + "name": "token", + "required": true, + "in": "path", + "description": "Multicall payout token returned by the create endpoint", + "schema": { + "example": "01JZ4PC7EXAMPLEMULTICALL01", + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "Bearer token for session authentication (or use session_token cookie)", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Multicall payout state retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "paymentType": { + "type": "string", + "enum": [ + "multicall" + ] + }, + "status": { + "type": "string", + "enum": [ + "pending", + "expired", + "completed", + "partially_settled" + ] + }, + "redirectUrl": { + "type": "string", + "nullable": true + }, + "redirectLabel": { + "type": "string", + "nullable": true + }, + "orchestratorId": { + "type": "string", + "nullable": true + }, + "branding": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "clientIdId": { + "type": "string" + }, + "orchestratorId": { + "type": "string" + }, + "logoPath": { + "type": "string" + }, + "pageBackgroundColor": { + "type": "string" + }, + "cardBackgroundColor": { + "type": "string" + }, + "primaryActionColor": { + "type": "string" + }, + "primaryTextColor": { + "type": "string" + }, + "secondaryTextColor": { + "type": "string" + }, + "termsPath": { + "type": "string" + }, + "privacyPath": { + "type": "string" + }, + "displayRequestBranding": { + "type": "boolean" + } + }, + "required": [ + "id" + ], + "nullable": true + }, + "paymentOptions": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "balance": { + "type": "string" + }, + "hasEnoughBalance": { + "type": "boolean" + }, + "neededAmount": { + "type": "string" + } + }, + "required": [ + "balance", + "hasEnoughBalance", + "neededAmount" + ] + } + } + }, + "analytics": { + "type": "object", + "properties": { + "creationTimestamp": { + "type": "string", + "format": "date-time" + }, + "totalPaymentAmountUsd": { + "type": "string" + }, + "protocolFeeAmountUsd": { + "type": "string" + }, + "orchestratorPayerFeeAmountUsd": { + "type": "string" + }, + "orchestratorRecipientFeeAmountUsd": { + "type": "string" + }, + "feeAmountsUsdUnavailableReason": { + "type": "string", + "enum": [ + "fee_plan_unavailable" + ] + }, + "numberOfPaymentsExcludingFees": { + "type": "integer", + "minimum": 0 + }, + "destinationIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "payoutKytProvider": { + "type": "string" + } + }, + "description": "Vendor-neutral analytics metadata that SPP maps into Mixpanel shared properties. Amount values are decimal USD strings to avoid frontend precision loss." + }, + "requestIds": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Request Network request IDs represented by this payment" + }, + "token": { + "type": "string", + "description": "Multicall payout token" + }, + "canExecute": { + "type": "boolean" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "children": { + "type": "array", + "items": { + "type": "object", + "properties": { + "securePaymentToken": { + "type": "string", + "description": "Child secure-payment token" + }, + "requestId": { + "type": "string", + "description": "Request Network request ID for the child payout" + }, + "position": { + "type": "integer", + "minimum": 0, + "description": "0-indexed child order" + }, + "executable": { + "type": "boolean", + "description": "Whether this child can currently be executed in the multicall" + }, + "blockReason": { + "type": "string", + "enum": [ + "not_found", + "not_owned", + "not_outgoing", + "not_single_payment", + "invalid_child_linkage", + "already_paid", + "request_processing", + "secure_payment_expired", + "secure_payment_not_pending", + "compliance_failed", + "not_payable_child" + ], + "description": "Structured reason when executable is false; otherwise null", + "nullable": true + }, + "messageKey": { + "type": "string", + "description": "Stable localized-message key for the block reason", + "nullable": true + }, + "context": { + "type": "object", + "properties": { + "requestId": { + "type": "string" + }, + "securePaymentToken": { + "type": "string" + }, + "position": { + "type": "integer", + "minimum": 0 + }, + "hasBeenPaid": { + "type": "boolean" + }, + "securePaymentStatus": { + "type": "string" + }, + "requestStatus": { + "type": "string" + }, + "expiresAt": { + "type": "string", + "format": "date-time" + }, + "network": { + "type": "string" + }, + "currency": { + "type": "string" + } + }, + "required": [ + "requestId", + "securePaymentToken", + "position", + "hasBeenPaid" + ], + "description": "Per-child block context used by SPP to render recovery details" + }, + "recoveryAction": { + "type": "string", + "enum": [ + "remove_child", + "recreate_reduced", + "wait_for_quote_refresh", + "switch_route", + "recreate_after_cooldown", + "support_required" + ], + "description": "Suggested recovery action when the child is blocked", + "nullable": true + }, + "feePlan": { + "type": "object", + "properties": { + "version": { + "type": "number", + "enum": [ + 1 + ] + }, + "flow": { + "type": "string", + "enum": [ + "get_paid", + "pay" + ] + }, + "defaultFeeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "grossAmountUsd": { + "type": "string" + }, + "netRecipientAmountUsd": { + "type": "string" + }, + "payerTotalAmountUsd": { + "type": "string" + }, + "totalFeesUsd": { + "type": "string" + }, + "payeeBorneFeesUsd": { + "type": "string" + }, + "payerBorneFeesUsd": { + "type": "string" + }, + "fees": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "label": { + "type": "string" + }, + "feeBearer": { + "type": "string", + "enum": [ + "payer", + "payee" + ] + }, + "feeBearerSource": { + "type": "string", + "enum": [ + "fee_config", + "payment_default_override", + "flow_default", + "forced_fee_policy" + ] + }, + "percentageBps": { + "type": "number" + }, + "capUsd": { + "type": "string", + "nullable": true + }, + "fixedAmountUsd": { + "type": "string", + "nullable": true + }, + "calculatedAmountUsd": { + "type": "string" + }, + "destinationResolver": { + "type": "string" + }, + "destinationRef": { + "type": "object", + "properties": { + "evmAddress": { + "type": "string" + }, + "tronAddress": { + "type": "string" + } + } + }, + "configSource": { + "type": "string" + } + }, + "required": [ + "type", + "label", + "feeBearer", + "feeBearerSource", + "percentageBps", + "capUsd", + "calculatedAmountUsd", + "destinationResolver", + "destinationRef", + "configSource" + ] + } + } + }, + "required": [ + "version", + "flow", + "defaultFeeBearer", + "grossAmountUsd", + "netRecipientAmountUsd", + "payerTotalAmountUsd", + "totalFeesUsd", + "payeeBorneFeesUsd", + "payerBorneFeesUsd", + "fees" + ], + "description": "Persisted child fee-plan snapshot. Null when fees do not apply or no snapshot exists.", + "nullable": true + }, + "amount": { + "type": "string", + "description": "Human-readable child amount in the child's payment currency. Null when unavailable.", + "nullable": true + }, + "payee": { + "type": "string", + "description": "Resolved child recipient address. Null when unavailable.", + "nullable": true + }, + "reference": { + "type": "string", + "description": "Merchant reference for the child payment. Null when none was provided.", + "nullable": true + } + }, + "required": [ + "securePaymentToken", + "requestId", + "position", + "executable", + "blockReason", + "messageKey", + "context", + "recoveryAction", + "feePlan", + "amount", + "payee", + "reference" + ] + } + }, + "totals": { + "type": "object", + "properties": { + "childCount": { + "type": "integer", + "minimum": 0 + }, + "blockedChildCount": { + "type": "integer", + "minimum": 0 + }, + "byDestinationCurrency": { + "type": "array", + "items": { + "type": "object", + "properties": { + "network": { + "type": "string" + }, + "currency": { + "type": "string" + }, + "totalAmount": { + "type": "string" + } + }, + "required": [ + "network", + "currency", + "totalAmount" + ] + } + }, + "amountSummary": { + "type": "object", + "properties": { + "grossAmount": { + "type": "string" + }, + "netRecipientAmount": { + "type": "string" + }, + "totalFees": { + "type": "string" + }, + "payeeBorneFees": { + "type": "string" + }, + "payerBorneFees": { + "type": "string" + }, + "payerTotal": { + "type": "string" + } + }, + "required": [ + "grossAmount", + "netRecipientAmount", + "totalFees", + "payeeBorneFees", + "payerBorneFees", + "payerTotal" + ] + } + }, + "required": [ + "childCount", + "blockedChildCount", + "byDestinationCurrency", + "amountSummary" + ] + } + }, + "required": [ + "paymentType", + "status", + "redirectUrl", + "redirectLabel", + "orchestratorId", + "branding", + "analytics", + "requestIds", + "token", + "canExecute", + "expiresAt", + "createdAt", + "children", + "totals" + ] + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Multicall payout not found" + }, + "429": { + "description": "Too Many Requests" + } + }, + "summary": "Get multicall payout state", + "tags": [ + "V2/Secure Payment" + ], + "x-feature-flag": "multicallPayoutsDisabled" + } + }, "/v2/payee-destination/signing-data": { "get": { "description": "Generate a nonce and return the complete EIP-712 signing data structure for payee destination creation or deactivation", @@ -5780,6 +12579,10 @@ "name": "V2/Client IDs", "description": "Client ID management (V2)" }, + { + "name": "V2/Secure Payment", + "description": "Secure payment operations with token-based access (V2)" + }, { "name": "V2/Payee Destination", "description": "Payee destination management (V2)" From 6f1b6b6944d426e7e0215e0105589e9f9e5b82d8 Mon Sep 17 00:00:00 2001 From: rodrigopavezi Date: Tue, 28 Jul 2026 11:37:57 -0300 Subject: [PATCH 2/2] docs: fix the batch example to respect the single-destination invariant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The batchPayment example, copied verbatim from the @Route decorator in request-api, gave its two items different destinationId values. Since createSecurePayment resolves one destination for the caller and rejects any supplied destinationId that differs from it, copying that example produces a 403 "Destination does not match the configured payment destination." rather than a batch payment. Both items now use the same destinationId, and the summary says so. Also states the constraint on the requests[] array itself, so it is visible to callers who omit destinationId and never read that field's description, and adds an example of the omitted form — the flow the destinationId docs describe but had no example for. --- api-reference/openapi.v2.json | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/api-reference/openapi.v2.json b/api-reference/openapi.v2.json index 4f9ec7e..b090e58 100644 --- a/api-reference/openapi.v2.json +++ b/api-reference/openapi.v2.json @@ -5533,7 +5533,7 @@ ] }, "minItems": 1, - "description": "Array of payment requests. Single item = single incoming payment. Multiple items preserve the legacy incoming-payment batch shape and are unrelated to multicall payout parents." + "description": "Array of payment requests. Single item = single incoming payment. Multiple items preserve the legacy incoming-payment batch shape and are unrelated to multicall payout parents. A batch varies only the amounts: every item resolves to the caller's single configured destination, so one create call cannot collect into several different payee destinations." }, "feePercentage": { "type": "string", @@ -5617,6 +5617,16 @@ ] } }, + "singlePaymentResolvedDestination": { + "summary": "Single payment, destination resolved from the Client ID", + "value": { + "requests": [ + { + "amount": "10" + } + ] + } + }, "singlePaymentWithFees": { "summary": "Single payment with fees example", "value": { @@ -5631,7 +5641,7 @@ } }, "batchPayment": { - "summary": "Legacy incoming batch payment example", + "summary": "Legacy incoming batch payment example (every item resolves to the same destination)", "value": { "requests": [ { @@ -5639,7 +5649,7 @@ "amount": "10" }, { - "destinationId": "0xb07d2398d2004378cad234da0ef14f1c94a530e4@eip155:11155111#E5F6A7B8:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", + "destinationId": "0x6923831ACf5c327260D7ac7C9DfF5b1c3cB3C7D7@eip155:11155111#A1B2C3D4:0x370DE27fdb7D1Ff1e1BaA7D11c5820a324Cf623C", "amount": "5" } ]