diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 059e09dd..aad86dfb 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -55,6 +55,8 @@ tags: description: Endpoints called by the agent itself using its own credentials (obtained via device code redemption). Scoped to the agent's associated customer — all requests automatically operate on behalf of that customer and are subject to the agent's policy. When an action requires approval, the resulting transaction enters a pending state and must be approved by the platform via `POST /transactions/{transactionId}/approve`. - name: Cards description: Card management endpoints. Issue debit cards against an internal account, freeze / unfreeze, close, manage card funding sources, and list card transactions. + - name: Stablecoins + description: Stablecoin issuance endpoints. Register provider-created stablecoins, link provider accounts and external bank accounts, create mint/burn quotes, execute them, and track the resulting operations. paths: /config: get: @@ -6864,357 +6866,191 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' -webhooks: - agent-action: + /stablecoin-provider-accounts: post: - summary: Agent action pending approval webhook + summary: Link a stablecoin provider account description: | - Fired when an agent submits an action that requires platform approval before Grid will execute it. Use this to send a push notification to the customer so they can review and approve or reject the action in your app. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - The payload contains the full `AgentAction` — including the embedded quote or transfer details — so you can render the approval UI without a second API call. Approve or reject via `POST /agents/{agentId}/actions/{actionId}/approve` or `POST /agents/{agentId}/actions/{actionId}/reject`. - operationId: agentActionWebhook + Link provider API credentials for the authenticated platform. Provider credentials are account-scoped and can be reused for multiple stablecoins. In V1 the only supported provider is `BRALE`; the provider environment is derived from the authenticated Grid platform mode. + operationId: linkStablecoinProviderAccount tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/AgentActionWebhook' - examples: - pendingApproval: - summary: Agent action pending approval - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000020 - type: AGENT_ACTION.PENDING_APPROVAL - timestamp: '2025-10-03T15:00:00Z' - data: - id: AgentAction:019542f5-b3e7-1d02-0000-000000000099 - agentId: Agent:019542f5-b3e7-1d02-0000-000000000042 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000010 - platformCustomerId: user-a1b2c3 - status: PENDING_APPROVAL - type: EXECUTE_QUOTE - quote: - id: Quote:019542f5-b3e7-1d02-0000-000000000006 - status: PENDING - expiresAt: '2025-10-03T15:00:30Z' - createdAt: '2025-10-03T15:00:00Z' - source: - sourceType: ACCOUNT - accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - sendingCurrency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - receivingCurrency: - code: INR - name: Indian Rupee - symbol: ₹ - decimals: 2 - totalSendingAmount: 50000 - totalReceivingAmount: 4625000 - exchangeRate: 92.5 - feesIncluded: 250 - transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 - createdAt: '2025-10-03T15:00:00Z' - updatedAt: '2025-10-03T15:00:00Z' + $ref: '#/components/schemas/StablecoinProviderAccountLinkRequest' responses: - '200': - description: Webhook received and acknowledged. + '201': + description: Stablecoin provider account linked + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinProviderAccount' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - incoming-payment: - post: - summary: Incoming payment webhook and approval mechanism - description: | - Webhook that is called when an incoming payment is received by a customer's UMA address. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - ### Payment Approval Flow - When a transaction has `status: "PENDING"`, this webhook serves as an approval mechanism: - - 1. The client should check the `counterpartyInformation` against their requirements - 2. To APPROVE the payment synchronously, return a 200 OK response - 3. To REJECT the payment, return a 403 Forbidden response with an Error object - 4. To request more information, return a 422 Unprocessable Entity with specific missing fields - 5. To process the payment asynchronously, return a 202 Accepted response and then call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint within 5 seconds. Note that synchronous approval/rejection is preferred where possible. - - The Grid system will proceed or cancel the payment based on your response. - - For transactions with other statuses (COMPLETED, FAILED, REFUNDED), this webhook is purely informational. - operationId: incomingPaymentWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List stablecoin provider account links + description: Retrieve stablecoin provider account links for the authenticated platform. + operationId: listStablecoinProviderAccounts tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/IncomingPaymentWebhook' - examples: - pendingPayment: - summary: Pending payment example requiring approval - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INCOMING_PAYMENT.PENDING - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: PENDING - type: INCOMING - destination: - destinationType: UMA_ADDRESS - umaAddress: $recipient@uma.domain - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@external.domain - receiverUmaAddress: $recipient@uma.domain - receivedAmount: - amount: 50000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - counterpartyInformation: - FULL_NAME: John Sender - BIRTH_DATE: '1985-06-15' - NATIONALITY: US - reconciliationInstructions: - reference: REF-123456789 - requestedReceiverCustomerInfoFields: - - name: NATIONALITY - mandatory: true - - name: POSTAL_ADDRESS - mandatory: false - incomingCompletedPayment: - summary: Completed payment notification - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INCOMING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: COMPLETED - type: INCOMING - destination: - destinationType: UMA_ADDRESS - umaAddress: $recipient@uma.domain - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@external.domain - receiverUmaAddress: $recipient@uma.domain - receivedAmount: - amount: 50000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: Payment for services - reconciliationInstructions: - reference: REF-123456789 + - BasicAuth: [] + parameters: + - name: provider + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProvider' + - name: status + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProviderAccountStatus' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: | - Webhook received successfully. - For PENDING transactions, this indicates approval to proceed with the payment. - If `requestedReceiverCustomerInfoFields` were present in the webhook request, the corresponding fields for the recipient must be included in this response in the `receiverCustomerInfo` object. + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookResponse' - '202': - description: | - Webhook received and will be processed asynchronously. The synchronous 200 response should be preferred where possible. This asycnhronous path should only be used in - cases where the platform's architecture requires async (but still very quick) processing before approving or rejecting the payment. - The platform must call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint to approve or reject the payment within 5 seconds or the payment will be automatically rejected. + $ref: '#/components/schemas/StablecoinProviderAccountListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '403': - description: | - Forbidden - Payment rejected by the client. - Only applicable for PENDING transactions. + '500': + description: Internal service error content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookForbiddenResponse' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + $ref: '#/components/schemas/Error500' + /stablecoin-provider-accounts/{stablecoinProviderAccountId}: + parameters: + - name: stablecoinProviderAccountId + in: path + description: System-generated stablecoin provider account link identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin provider account link + operationId: getStablecoinProviderAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error409' - '422': - description: | - Unprocessable Entity - Additional counterparty information required. - Only applicable for PENDING transactions. + $ref: '#/components/schemas/StablecoinProviderAccount' + '401': + description: Unauthorized content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookUnprocessableResponse' - outgoing-payment: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin provider account link not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins: post: - summary: Outgoing payment status webhook + summary: Register an existing provider-created stablecoin description: | - Webhook that is called when an outgoing payment's status changes. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - This webhook is informational only and is sent when an outgoing payment completes successfully, fails, or is refunded. - operationId: outgoingPaymentWebhook + Register an existing provider-created stablecoin as a Grid `Stablecoin`. This endpoint links provider token metadata to Grid; it does not create the token with the provider. Grid derives the active provider account link from the authenticated platform, provider, and provider environment. + operationId: registerStablecoin tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/OutgoingPaymentWebhook' - examples: - outgoingCompletedPayment: - summary: Completed outgoing payment - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: OUTGOING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: COMPLETED - type: OUTGOING - source: - sourceType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@uma.domain - receiverUmaAddress: $recipient@external.domain - sentAmount: - amount: 10550 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - receivedAmount: - amount: 9706 - currency: - code: EUR - name: Euro - symbol: € - decimals: 2 - exchangeRate: 0.92 - quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: 'Payment for invoice #1234' - paymentInstructions: [] - rateDetails: - counterpartyMultiplier: 1.08 - counterpartyFixedFee: 10 - gridApiMultiplier: 0.925 - gridApiFixedFee: 10 - gridApiVariableFeeRate: 0.003 - gridApiVariableFeeAmount: 30 - failedPayment: - summary: Failed outgoing payment - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: OUTGOING_PAYMENT.FAILED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: FAILED - type: OUTGOING - source: - sourceType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@uma.domain - receiverUmaAddress: $recipient@external.domain - sentAmount: - amount: 10550 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - createdAt: '2025-08-15T14:25:18Z' - quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 - failureReason: QUOTE_EXECUTION_FAILED + $ref: '#/components/schemas/StablecoinRegisterRequest' responses: - '200': - description: Webhook received successfully + '201': + description: Stablecoin registered + content: + application/json: + schema: + $ref: '#/components/schemas/Stablecoin' '400': description: Bad request content: @@ -7222,219 +7058,163 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: Referenced stablecoin provider account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - test-webhook: - post: - summary: Test webhook for integration verification - description: | - Webhook that is sent once to verify your webhook endpoint is correctly set up. - This is sent when you configure or update your platform settings with a webhook URL. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by the Grid API. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - This webhook is purely for testing your endpoint integration and signature verification. - operationId: testWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List stablecoins + description: Retrieve stablecoins registered to the authenticated platform. + operationId: listStablecoins tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TestWebhookRequest' - examples: - testWebhook: - summary: Test webhook example - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000001 - type: TEST - timestamp: '2025-08-15T14:32:00Z' - data: {} + - BasicAuth: [] + parameters: + - name: issuanceStatus + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinIssuanceStatus' + - name: gridOperationsStatus + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinGridOperationsStatus' + - name: provider + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProvider' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: Webhook received successfully. This confirms your webhook endpoint is properly configured. + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '500': + description: Internal service error content: application/json: schema: - $ref: '#/components/schemas/Error409' - bulk-upload: - post: - summary: Bulk upload status webhook - description: | - Webhook that is called when a bulk customer upload job completes or fails. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - This webhook is sent when a bulk upload job completes or fails, providing detailed information about the results. - operationId: bulkUploadWebhook + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin + operationId: getStablecoin tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkUploadWebhook' - examples: - completedUpload: - summary: Successful bulk upload completion - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: BULK_UPLOAD.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Job:019542f5-b3e7-1d02-0000-000000000006 - status: COMPLETED - progress: - total: 5000 - processed: 5000 - successful: 5000 - failed: 0 - errors: [] - failedUpload: - summary: Failed bulk upload - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: BULK_UPLOAD.FAILED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Job:019542f5-b3e7-1d02-0000-000000000006 - status: FAILED - progress: - total: 5000 - processed: 5000 - successful: 0 - failed: 5000 - errors: - - correlationId: row_1 - error: - code: invalid_csv_format - message: Invalid CSV format - details: - reason: missing_required_column - column: umaAddress + - BasicAuth: [] responses: '200': - description: Webhook received successfully - '400': - description: Bad request + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error400' + $ref: '#/components/schemas/Stablecoin' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '404': + description: Stablecoin not found content: application/json: schema: - $ref: '#/components/schemas/Error409' - invitation-claimed: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-external-account-link-sessions: post: - summary: Invitation claimed webhook - description: | - Webhook that is called when an invitation is claimed by a customer. - This endpoint should be implemented by platform clients of the Grid API. - - When a customer claims an invitation, this webhook is triggered to notify the platform that: - 1. The invitation has been successfully claimed - 2. The invitee UMA address is now associated with the invitation - 3. The invitation status has changed from PENDING to CLAIMED - - This allows platforms to: - - Track invitation usage and conversion rates - - Trigger onboarding flows for new customers who joined via invitation - - Apply referral bonuses or rewards to the inviter - - Update their UI to reflect the claimed status - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: invitationClaimedWebhook + summary: Create a stablecoin external-account link session + description: Create a provider/Plaid link session for linking a bank account to the stablecoin provider. + operationId: createStablecoinExternalAccountLinkSession tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/InvitationClaimedWebhook' - examples: - claimedInvitation: - summary: Invitation claimed notification - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: INVITATION.CLAIMED - timestamp: '2025-09-01T15:45:00Z' - data: - code: 019542f5 - createdAt: '2025-09-01T14:30:00Z' - claimedAt: '2025-09-01T15:45:00Z' - inviterUma: $inviter@uma.domain - inviteeUma: $invitee@uma.domain - status: CLAIMED - url: https://uma.me/i/019542f5 + $ref: '#/components/schemas/StablecoinExternalAccountLinkSessionCreateRequest' responses: - '200': - description: Webhook received successfully + '201': + description: Link session created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccountLinkSession' '400': description: Bad request content: @@ -7442,158 +7222,54 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - customer-update: + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-external-accounts: post: - summary: Customer status change + summary: Link a stablecoin external account description: | - Webhook that is called when the status of a customer is updated, including KYC and KYB status changes. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid API public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: customerStatusWebhook + Link a Grid external account, provider/Plaid link result, or direct-entry bank account to the stablecoin provider. The returned resource stores provider address metadata used for stablecoin mints and burns. + operationId: linkStablecoinExternalAccount tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/CustomerWebhook' - examples: - kycApprovedWebhook: - summary: When an individual customer KYC has been approved - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: CUSTOMER.KYC_APPROVED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 9f84e0c2a72c4fa - customerType: INDIVIDUAL - region: US - currencies: - - USD - - USDC - umaAddress: $john.doe@uma.domain.com - kycStatus: APPROVED - fullName: John Michael Doe - birthDate: '1990-01-15' - nationality: US - address: - line1: 123 Main Street - line2: Apt 4B - city: San Francisco - state: CA - postalCode: '94105' - country: US - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-07-21T17:32:28Z' - isDeleted: false - kycRejectedWebhook: - summary: When an individual customer KYC has been rejected - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: CUSTOMER.KYC_REJECTED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000002 - platformCustomerId: 4b7c1e9d3f5a8e2 - customerType: INDIVIDUAL - region: US - currencies: - - USD - - USDC - umaAddress: $jane.smith@uma.domain.com - kycStatus: REJECTED - fullName: Jane Smith - birthDate: '1988-03-22' - nationality: US - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-08-15T14:32:00Z' - isDeleted: false - kybApprovedWebhook: - summary: When a business customer KYB has been approved - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000009 - type: CUSTOMER.KYB_APPROVED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000003 - platformCustomerId: 7a2f9d4e1b8c3f5 - customerType: BUSINESS - region: US - currencies: - - USD - - USDC - umaAddress: $acme.corp@uma.domain.com - kybStatus: APPROVED - address: - line1: 456 Business Ave - city: New York - state: NY - postalCode: '10001' - country: US - businessInfo: - legalName: Acme Corporation - registrationNumber: '12345678' - taxId: 98-7654321 - incorporatedOn: '2018-03-14' - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-08-15T14:32:00Z' - isDeleted: false - kybRejectedWebhook: - summary: When a business customer KYB has been rejected - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000010 - type: CUSTOMER.KYB_REJECTED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000004 - platformCustomerId: 3c8e5f2a9d1b7e4 - customerType: BUSINESS - region: US - currencies: - - USD - umaAddress: $globex.inc@uma.domain.com - kybStatus: REJECTED - address: - line1: 789 Corporate Blvd - city: Chicago - state: IL - postalCode: '60601' - country: US - businessInfo: - legalName: Globex Inc - taxId: 47-1234567 - incorporatedOn: '2015-09-01' - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-08-15T14:32:00Z' - isDeleted: false + $ref: '#/components/schemas/StablecoinExternalAccountLinkRequest' responses: - '200': - description: | - Webhook received successfully + '201': + description: Stablecoin external account linked + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccount' '400': description: Bad request content: @@ -7601,174 +7277,170 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: External account or link session not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - internal-account-status: - post: - summary: Internal account status webhook - description: | - Webhook that is called when the status of an internal account changes. This includes balance updates and may include additional account events in the future. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - ### Event types - - `INTERNAL_ACCOUNT.BALANCE_UPDATED` — Fired when the balance of an internal account changes. The `data` payload contains the full internal account object. - - `INTERNAL_ACCOUNT.STATUS_UPDATED` — Fired when the status of an internal account changes (e.g., `OPEN` → `FROZEN`). The `data` payload contains the full internal account object. - operationId: internalAccountStatusWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List stablecoin external accounts + operationId: listStablecoinExternalAccounts tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/InternalAccountStatusWebhook' - examples: - balanceDecrease: - summary: A transaction just cleared a customer account and the balance has decreased - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INTERNAL_ACCOUNT.BALANCE_UPDATED - timestamp: '2025-08-15T14:32:00Z' - data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: INTERNAL_FIAT - status: ACTIVE - balance: - amount: 10000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - fundingPaymentInstructions: [] - createdAt: '2025-08-01T10:00:00Z' - updatedAt: '2025-08-15T14:32:00Z' - statusUpdated: - summary: The status of an internal account changed (e.g., frozen by Grid) - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: INTERNAL_ACCOUNT.STATUS_UPDATED - timestamp: '2025-08-15T14:32:00Z' - data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: INTERNAL_FIAT - status: FROZEN - balance: - amount: 10000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - fundingPaymentInstructions: [] - createdAt: '2025-08-01T10:00:00Z' - updatedAt: '2025-08-15T14:32:00Z' + - BasicAuth: [] + parameters: + - name: provider + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProvider' + - name: status + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinExternalAccountStatus' + - name: gridExternalAccountId + in: query + required: false + schema: + type: string + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: | - Webhook received successfully + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccountListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '500': + description: Internal service error content: application/json: schema: - $ref: '#/components/schemas/Error409' - verification-update: + $ref: '#/components/schemas/Error500' + /stablecoin-external-accounts/{stablecoinExternalAccountId}: + parameters: + - name: stablecoinExternalAccountId + in: path + description: System-generated stablecoin external account identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin external account + operationId: getStablecoinExternalAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccount' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin external account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/quotes: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string post: - summary: Verification status change + summary: Create a stablecoin quote description: | - Webhook that is called when a customer's KYC/KYB verification status changes. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid API public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: verificationStatusWebhook + Create a MINT or BURN quote for this stablecoin. A quote is a validation preview only: it locks no exchange rate, reserves no fee, and holds no balance. Execution re-validates everything; for burns, the balance hold happens at execution time. Execute the quote with `executeStablecoinQuote` before it expires. + operationId: createStablecoinQuote tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key scoped to this quote request. Replays return the prior quote; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/VerificationWebhook' - examples: - approved: - summary: Verification approved - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: VERIFICATION.APPROVED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Verification:019542f5-b3e7-1d02-0000-000000000010 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - verificationStatus: APPROVED - errors: [] - createdAt: '2025-08-15T14:00:00Z' - resolveErrors: - summary: Verification requires action - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000031 - type: VERIFICATION.RESOLVE_ERRORS - timestamp: '2025-08-15T14:32:00Z' - data: - id: Verification:019542f5-b3e7-1d02-0000-000000000011 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - verificationStatus: RESOLVE_ERRORS - errors: - - resourceId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: MISSING_PROOF_OF_ADDRESS_DOCUMENT - acceptedDocumentTypes: - - PROOF_OF_ADDRESS - reason: Proof of address document is required - createdAt: '2025-08-15T14:00:00Z' + $ref: '#/components/schemas/StablecoinQuoteRequest' responses: - '200': - description: | - Webhook received successfully + '201': + description: Quote created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinQuote' '400': description: Bad request content: @@ -7776,113 +7448,113 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin or linked account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - card-state-change: - post: - summary: Card state change - description: | - Webhook that is called when a card's lifecycle state changes. Fires on `PENDING_ISSUE → ACTIVE`, on `PENDING_ISSUE → CLOSED (ISSUER_REJECTED)` when issuer provisioning fails, and on every subsequent `ACTIVE ⇄ FROZEN` and `→ CLOSED` transition. - - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: cardStateChangeWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/quotes/{stablecoinQuoteId}: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + - name: stablecoinQuoteId + in: path + description: System-generated stablecoin quote identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin quote + operationId: getStablecoinQuote tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CardStateChangeWebhook' - examples: - activated: - summary: Card transitioned from PENDING_ISSUE to ACTIVE - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000020 - type: CARD.STATE_CHANGE - timestamp: '2026-05-08T14:11:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: card-emp-aary-001 - state: ACTIVE - stateReason: null - brand: VISA - form: VIRTUAL - last4: '4242' - expMonth: 12 - expYear: 2029 - panEmbedUrl: https://embed.lithic.com/iframe/...?t=... - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - issuerRef: lithic_card_4f8d3a2b1c - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-08T14:11:00Z' - issuerRejected: - summary: Card rejected by issuer during provisioning - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000021 - type: CARD.STATE_CHANGE - timestamp: '2026-05-08T14:12:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000011 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - state: CLOSED - stateReason: ISSUER_REJECTED - form: VIRTUAL - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-08T14:12:00Z' - frozen: - summary: Card frozen by the platform - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000022 - type: CARD.STATE_CHANGE - timestamp: '2026-05-09T09:00:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - state: FROZEN - stateReason: null - brand: VISA - form: VIRTUAL - last4: '4242' - expMonth: 12 - expYear: 2029 - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-09T09:00:00Z' + - BasicAuth: [] responses: '200': - description: | - Webhook received successfully + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinQuote' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin or quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/quotes/{stablecoinQuoteId}/execute: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + - name: stablecoinQuoteId + in: path + description: System-generated stablecoin quote identifier + required: true + schema: + type: string + post: + summary: Execute a stablecoin quote + description: | + Execute an open, unexpired quote, creating the StablecoinOperation and the first provider side effect. Execution re-validates the quoted inputs (stablecoin state, credential status, external-account capability, and for burns the source balance). Expired or already-executed quotes are rejected; create a new quote instead. + operationId: executeStablecoinQuote + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key scoped to creating the operation and provider side effects. Replays against the same quote return the prior operation; replays against a different quote are rejected. + required: true + schema: + type: string + maxLength: 255 + responses: + '201': + description: Operation created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperation' '400': description: Bad request content: @@ -7890,107 +7562,151 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin or quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - card-funding-source-change: - post: - summary: Card funding source change - description: | - Webhook that is called when the funding sources bound to a card change. Fires whenever `PATCH /cards/{id}` updates the `fundingSources` array. The payload carries the full `Card` resource with the post-change `fundingSources` array. - - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: cardFundingSourceChangeWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/operations: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + get: + summary: List stablecoin operations + operationId: listStablecoinOperations tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CardFundingSourceChangeWebhook' - examples: - fundingSourcesReplaced: - summary: Funding sources replaced via PATCH /cards/{id} - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: CARD.FUNDING_SOURCE_CHANGE - timestamp: '2026-05-08T14:30:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - state: ACTIVE - stateReason: null - brand: VISA - form: VIRTUAL - last4: '4242' - expMonth: 12 - expYear: 2029 - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 - currency: USD - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-08T14:30:00Z' + - BasicAuth: [] + parameters: + - name: type + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinOperationType' + - name: status + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinOperationStatus' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: | - Webhook received successfully + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperationListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '404': + description: Stablecoin not found content: application/json: schema: - $ref: '#/components/schemas/Error409' -components: - securitySchemes: - BasicAuth: - type: http - scheme: basic - description: API token authentication using format `:` - AgentAuth: - type: http - scheme: bearer - description: 'Bearer token authentication for agent-scoped endpoints. The token is the `accessToken` returned when redeeming a device code via `POST /agents/device-codes/{code}/redeem`. Agent credentials are user-scoped: all requests are automatically bound to the agent''s associated customer and subject to the agent''s policy.' - WebhookSignature: - type: apiKey - in: header - name: X-Grid-Signature + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-operations/{stablecoinOperationId}: + parameters: + - name: stablecoinOperationId + in: path + description: System-generated stablecoin operation identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin operation + operationId: getStablecoinOperation + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperation' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin operation not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' +webhooks: + agent-action: + post: + summary: Agent action pending approval webhook description: | - Secp256r1 (P-256) asymmetric signature of the webhook payload, which can be used to verify that the webhook was sent by Grid. + Fired when an agent submits an action that requires platform approval before Grid will execute it. Use this to send a push notification to the customer so they can review and approve or reject the action in your app. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. To verify the signature: 1. Get the Grid public key provided to you during integration 2. Decode the base64 signature from the header @@ -7998,128 +7714,1245 @@ components: 4. Verify the signature using the public key and the hash If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - schemas: - CustomerInfoFieldName: - type: string - enum: - - FULL_NAME - - BIRTH_DATE - - NATIONALITY - - PHONE_NUMBER - - EMAIL - - POSTAL_ADDRESS - - TAX_ID - - REGISTRATION_NUMBER - - USER_TYPE - - COUNTRY_OF_RESIDENCE - - ACCOUNT_IDENTIFIER - - FI_LEGAL_ENTITY_NAME - - FI_ADDRESS - - PURPOSE_OF_PAYMENT - - ULTIMATE_INSTITUTION_COUNTRY - - IDENTIFIER - - BUSINESS_TYPE - - COMPANY_LEGAL_NAME - - ID_TYPE - - ID_NUMBER - description: Name of a type of field containing info about a platform's customer or counterparty customer. - example: FULL_NAME - CounterpartyFieldDefinition: - type: object - properties: - name: - $ref: '#/components/schemas/CustomerInfoFieldName' - mandatory: - type: boolean - description: Whether the field is mandatory - example: true - required: - - name - - mandatory - TransactionType: - type: string - enum: - - INCOMING - - OUTGOING - description: Type of transaction (incoming payment or outgoing payment) - PlatformCurrencyConfig: - type: object - properties: - currencyCode: - type: string - description: Three-letter currency code (ISO 4217) - example: USD - minAmount: - type: integer - format: int64 - description: Minimum amount that can be sent in the smallest unit of this currency - minimum: 0 - example: 100 - maxAmount: - type: integer - format: int64 - description: Maximum amount that can be sent in the smallest unit of this currency - minimum: 0 - example: 1000000 - requiredCounterpartyFields: - type: array - items: - $ref: '#/components/schemas/CounterpartyFieldDefinition' - description: List of fields which the platform requires from the counterparty institutions about counterparty customers. Platforms can set mandatory to false if the platform does not require the field, but would like to have it available. Some fields may be required by the underlying UMA provider. - example: - - name: FULL_NAME - mandatory: true - - name: BIRTH_DATE - mandatory: true - - name: NATIONALITY - mandatory: true - providerRequiredCustomerFields: - type: array - items: - $ref: '#/components/schemas/CustomerInfoFieldName' - description: List of customer info field names that are required by the underlying UMA provider when creating a customer for this currency. These fields must be supplied when creating or updating a customer if this currency is intended to be used by that customer. If no fields are required, this field is omitted. - readOnly: true - example: - - NATIONALITY - - BIRTH_DATE - providerRequiredCounterpartyCustomerFields: - type: array - items: - $ref: '#/components/schemas/CustomerInfoFieldName' - description: List of fields that are required by the underlying UMA provider for this currency. If the counterparty does not provide these fields, quote requests will fail. - readOnly: true - example: - - FULL_NAME - - COUNTRY_OF_RESIDENCE - enabledTransactionTypes: - type: array - items: - $ref: '#/components/schemas/TransactionType' - description: List of transaction types that are enabled for this currency. - example: - - OUTGOING - - INCOMING - required: - - currencyCode - - minAmount - - maxAmount - - requiredCounterpartyFields - - enabledTransactionTypes - EmbeddedWalletConfig: - type: object + + The payload contains the full `AgentAction` — including the embedded quote or transfer details — so you can render the approval UI without a second API call. Approve or reject via `POST /agents/{agentId}/actions/{actionId}/approve` or `POST /agents/{agentId}/actions/{actionId}/reject`. + operationId: agentActionWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentActionWebhook' + examples: + pendingApproval: + summary: Agent action pending approval + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: AGENT_ACTION.PENDING_APPROVAL + timestamp: '2025-10-03T15:00:00Z' + data: + id: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: user-a1b2c3 + status: PENDING_APPROVAL + type: EXECUTE_QUOTE + quote: + id: Quote:019542f5-b3e7-1d02-0000-000000000006 + status: PENDING + expiresAt: '2025-10-03T15:00:30Z' + createdAt: '2025-10-03T15:00:00Z' + source: + sourceType: ACCOUNT + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + sendingCurrency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + receivingCurrency: + code: INR + name: Indian Rupee + symbol: ₹ + decimals: 2 + totalSendingAmount: 50000 + totalReceivingAmount: 4625000 + exchangeRate: 92.5 + feesIncluded: 250 + transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 + createdAt: '2025-10-03T15:00:00Z' + updatedAt: '2025-10-03T15:00:00Z' + responses: + '200': + description: Webhook received and acknowledged. + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + incoming-payment: + post: + summary: Incoming payment webhook and approval mechanism description: | - Per-platform embedded-wallet configuration. Controls branding and OTP - behavior for the email sent when a customer authenticates with an - EMAIL_OTP credential. Fields omitted from a request are left unchanged. - properties: - appName: - type: string - maxLength: 255 - description: App name displayed in the default OTP email template. - example: Acme Wallet - otpLength: - type: integer - minimum: 4 + Webhook that is called when an incoming payment is received by a customer's UMA address. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + ### Payment Approval Flow + When a transaction has `status: "PENDING"`, this webhook serves as an approval mechanism: + + 1. The client should check the `counterpartyInformation` against their requirements + 2. To APPROVE the payment synchronously, return a 200 OK response + 3. To REJECT the payment, return a 403 Forbidden response with an Error object + 4. To request more information, return a 422 Unprocessable Entity with specific missing fields + 5. To process the payment asynchronously, return a 202 Accepted response and then call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint within 5 seconds. Note that synchronous approval/rejection is preferred where possible. + + The Grid system will proceed or cancel the payment based on your response. + + For transactions with other statuses (COMPLETED, FAILED, REFUNDED), this webhook is purely informational. + operationId: incomingPaymentWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhook' + examples: + pendingPayment: + summary: Pending payment example requiring approval + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INCOMING_PAYMENT.PENDING + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: PENDING + type: INCOMING + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + counterpartyInformation: + FULL_NAME: John Sender + BIRTH_DATE: '1985-06-15' + NATIONALITY: US + reconciliationInstructions: + reference: REF-123456789 + requestedReceiverCustomerInfoFields: + - name: NATIONALITY + mandatory: true + - name: POSTAL_ADDRESS + mandatory: false + incomingCompletedPayment: + summary: Completed payment notification + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INCOMING_PAYMENT.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: INCOMING + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: Payment for services + reconciliationInstructions: + reference: REF-123456789 + responses: + '200': + description: | + Webhook received successfully. + For PENDING transactions, this indicates approval to proceed with the payment. + If `requestedReceiverCustomerInfoFields` were present in the webhook request, the corresponding fields for the recipient must be included in this response in the `receiverCustomerInfo` object. + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhookResponse' + '202': + description: | + Webhook received and will be processed asynchronously. The synchronous 200 response should be preferred where possible. This asycnhronous path should only be used in + cases where the platform's architecture requires async (but still very quick) processing before approving or rejecting the payment. + The platform must call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint to approve or reject the payment within 5 seconds or the payment will be automatically rejected. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: | + Forbidden - Payment rejected by the client. + Only applicable for PENDING transactions. + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhookForbiddenResponse' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '422': + description: | + Unprocessable Entity - Additional counterparty information required. + Only applicable for PENDING transactions. + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhookUnprocessableResponse' + outgoing-payment: + post: + summary: Outgoing payment status webhook + description: | + Webhook that is called when an outgoing payment's status changes. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + This webhook is informational only and is sent when an outgoing payment completes successfully, fails, or is refunded. + operationId: outgoingPaymentWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/OutgoingPaymentWebhook' + examples: + outgoingCompletedPayment: + summary: Completed outgoing payment + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: OUTGOING_PAYMENT.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: OUTGOING + source: + sourceType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@uma.domain + receiverUmaAddress: $recipient@external.domain + sentAmount: + amount: 10550 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + receivedAmount: + amount: 9706 + currency: + code: EUR + name: Euro + symbol: € + decimals: 2 + exchangeRate: 0.92 + quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: 'Payment for invoice #1234' + paymentInstructions: [] + rateDetails: + counterpartyMultiplier: 1.08 + counterpartyFixedFee: 10 + gridApiMultiplier: 0.925 + gridApiFixedFee: 10 + gridApiVariableFeeRate: 0.003 + gridApiVariableFeeAmount: 30 + failedPayment: + summary: Failed outgoing payment + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: OUTGOING_PAYMENT.FAILED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: FAILED + type: OUTGOING + source: + sourceType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@uma.domain + receiverUmaAddress: $recipient@external.domain + sentAmount: + amount: 10550 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + createdAt: '2025-08-15T14:25:18Z' + quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 + failureReason: QUOTE_EXECUTION_FAILED + responses: + '200': + description: Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + test-webhook: + post: + summary: Test webhook for integration verification + description: | + Webhook that is sent once to verify your webhook endpoint is correctly set up. + This is sent when you configure or update your platform settings with a webhook URL. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by the Grid API. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + This webhook is purely for testing your endpoint integration and signature verification. + operationId: testWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TestWebhookRequest' + examples: + testWebhook: + summary: Test webhook example + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000001 + type: TEST + timestamp: '2025-08-15T14:32:00Z' + data: {} + responses: + '200': + description: Webhook received successfully. This confirms your webhook endpoint is properly configured. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + bulk-upload: + post: + summary: Bulk upload status webhook + description: | + Webhook that is called when a bulk customer upload job completes or fails. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + This webhook is sent when a bulk upload job completes or fails, providing detailed information about the results. + operationId: bulkUploadWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkUploadWebhook' + examples: + completedUpload: + summary: Successful bulk upload completion + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: BULK_UPLOAD.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Job:019542f5-b3e7-1d02-0000-000000000006 + status: COMPLETED + progress: + total: 5000 + processed: 5000 + successful: 5000 + failed: 0 + errors: [] + failedUpload: + summary: Failed bulk upload + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: BULK_UPLOAD.FAILED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Job:019542f5-b3e7-1d02-0000-000000000006 + status: FAILED + progress: + total: 5000 + processed: 5000 + successful: 0 + failed: 5000 + errors: + - correlationId: row_1 + error: + code: invalid_csv_format + message: Invalid CSV format + details: + reason: missing_required_column + column: umaAddress + responses: + '200': + description: Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + invitation-claimed: + post: + summary: Invitation claimed webhook + description: | + Webhook that is called when an invitation is claimed by a customer. + This endpoint should be implemented by platform clients of the Grid API. + + When a customer claims an invitation, this webhook is triggered to notify the platform that: + 1. The invitation has been successfully claimed + 2. The invitee UMA address is now associated with the invitation + 3. The invitation status has changed from PENDING to CLAIMED + + This allows platforms to: + - Track invitation usage and conversion rates + - Trigger onboarding flows for new customers who joined via invitation + - Apply referral bonuses or rewards to the inviter + - Update their UI to reflect the claimed status + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: invitationClaimedWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/InvitationClaimedWebhook' + examples: + claimedInvitation: + summary: Invitation claimed notification + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: INVITATION.CLAIMED + timestamp: '2025-09-01T15:45:00Z' + data: + code: 019542f5 + createdAt: '2025-09-01T14:30:00Z' + claimedAt: '2025-09-01T15:45:00Z' + inviterUma: $inviter@uma.domain + inviteeUma: $invitee@uma.domain + status: CLAIMED + url: https://uma.me/i/019542f5 + responses: + '200': + description: Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + customer-update: + post: + summary: Customer status change + description: | + Webhook that is called when the status of a customer is updated, including KYC and KYB status changes. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid API public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: customerStatusWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerWebhook' + examples: + kycApprovedWebhook: + summary: When an individual customer KYC has been approved + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: CUSTOMER.KYC_APPROVED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 9f84e0c2a72c4fa + customerType: INDIVIDUAL + region: US + currencies: + - USD + - USDC + umaAddress: $john.doe@uma.domain.com + kycStatus: APPROVED + fullName: John Michael Doe + birthDate: '1990-01-15' + nationality: US + address: + line1: 123 Main Street + line2: Apt 4B + city: San Francisco + state: CA + postalCode: '94105' + country: US + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-07-21T17:32:28Z' + isDeleted: false + kycRejectedWebhook: + summary: When an individual customer KYC has been rejected + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: CUSTOMER.KYC_REJECTED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000002 + platformCustomerId: 4b7c1e9d3f5a8e2 + customerType: INDIVIDUAL + region: US + currencies: + - USD + - USDC + umaAddress: $jane.smith@uma.domain.com + kycStatus: REJECTED + fullName: Jane Smith + birthDate: '1988-03-22' + nationality: US + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-08-15T14:32:00Z' + isDeleted: false + kybApprovedWebhook: + summary: When a business customer KYB has been approved + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000009 + type: CUSTOMER.KYB_APPROVED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000003 + platformCustomerId: 7a2f9d4e1b8c3f5 + customerType: BUSINESS + region: US + currencies: + - USD + - USDC + umaAddress: $acme.corp@uma.domain.com + kybStatus: APPROVED + address: + line1: 456 Business Ave + city: New York + state: NY + postalCode: '10001' + country: US + businessInfo: + legalName: Acme Corporation + registrationNumber: '12345678' + taxId: 98-7654321 + incorporatedOn: '2018-03-14' + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-08-15T14:32:00Z' + isDeleted: false + kybRejectedWebhook: + summary: When a business customer KYB has been rejected + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000010 + type: CUSTOMER.KYB_REJECTED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000004 + platformCustomerId: 3c8e5f2a9d1b7e4 + customerType: BUSINESS + region: US + currencies: + - USD + umaAddress: $globex.inc@uma.domain.com + kybStatus: REJECTED + address: + line1: 789 Corporate Blvd + city: Chicago + state: IL + postalCode: '60601' + country: US + businessInfo: + legalName: Globex Inc + taxId: 47-1234567 + incorporatedOn: '2015-09-01' + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-08-15T14:32:00Z' + isDeleted: false + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + internal-account-status: + post: + summary: Internal account status webhook + description: | + Webhook that is called when the status of an internal account changes. This includes balance updates and may include additional account events in the future. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + ### Event types + - `INTERNAL_ACCOUNT.BALANCE_UPDATED` — Fired when the balance of an internal account changes. The `data` payload contains the full internal account object. + - `INTERNAL_ACCOUNT.STATUS_UPDATED` — Fired when the status of an internal account changes (e.g., `OPEN` → `FROZEN`). The `data` payload contains the full internal account object. + operationId: internalAccountStatusWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/InternalAccountStatusWebhook' + examples: + balanceDecrease: + summary: A transaction just cleared a customer account and the balance has decreased + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INTERNAL_ACCOUNT.BALANCE_UPDATED + timestamp: '2025-08-15T14:32:00Z' + data: + id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: INTERNAL_FIAT + status: ACTIVE + balance: + amount: 10000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + fundingPaymentInstructions: [] + createdAt: '2025-08-01T10:00:00Z' + updatedAt: '2025-08-15T14:32:00Z' + statusUpdated: + summary: The status of an internal account changed (e.g., frozen by Grid) + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: INTERNAL_ACCOUNT.STATUS_UPDATED + timestamp: '2025-08-15T14:32:00Z' + data: + id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: INTERNAL_FIAT + status: FROZEN + balance: + amount: 10000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + fundingPaymentInstructions: [] + createdAt: '2025-08-01T10:00:00Z' + updatedAt: '2025-08-15T14:32:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + verification-update: + post: + summary: Verification status change + description: | + Webhook that is called when a customer's KYC/KYB verification status changes. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid API public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: verificationStatusWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/VerificationWebhook' + examples: + approved: + summary: Verification approved + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000030 + type: VERIFICATION.APPROVED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Verification:019542f5-b3e7-1d02-0000-000000000010 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + verificationStatus: APPROVED + errors: [] + createdAt: '2025-08-15T14:00:00Z' + resolveErrors: + summary: Verification requires action + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000031 + type: VERIFICATION.RESOLVE_ERRORS + timestamp: '2025-08-15T14:32:00Z' + data: + id: Verification:019542f5-b3e7-1d02-0000-000000000011 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + verificationStatus: RESOLVE_ERRORS + errors: + - resourceId: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: MISSING_PROOF_OF_ADDRESS_DOCUMENT + acceptedDocumentTypes: + - PROOF_OF_ADDRESS + reason: Proof of address document is required + createdAt: '2025-08-15T14:00:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + card-state-change: + post: + summary: Card state change + description: | + Webhook that is called when a card's lifecycle state changes. Fires on `PENDING_ISSUE → ACTIVE`, on `PENDING_ISSUE → CLOSED (ISSUER_REJECTED)` when issuer provisioning fails, and on every subsequent `ACTIVE ⇄ FROZEN` and `→ CLOSED` transition. + + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: cardStateChangeWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CardStateChangeWebhook' + examples: + activated: + summary: Card transitioned from PENDING_ISSUE to ACTIVE + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: CARD.STATE_CHANGE + timestamp: '2026-05-08T14:11:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCardId: card-emp-aary-001 + state: ACTIVE + stateReason: null + brand: VISA + form: VIRTUAL + last4: '4242' + expMonth: 12 + expYear: 2029 + panEmbedUrl: https://embed.lithic.com/iframe/...?t=... + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + issuerRef: lithic_card_4f8d3a2b1c + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-08T14:11:00Z' + issuerRejected: + summary: Card rejected by issuer during provisioning + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000021 + type: CARD.STATE_CHANGE + timestamp: '2026-05-08T14:12:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000011 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + state: CLOSED + stateReason: ISSUER_REJECTED + form: VIRTUAL + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-08T14:12:00Z' + frozen: + summary: Card frozen by the platform + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000022 + type: CARD.STATE_CHANGE + timestamp: '2026-05-09T09:00:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + state: FROZEN + stateReason: null + brand: VISA + form: VIRTUAL + last4: '4242' + expMonth: 12 + expYear: 2029 + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-09T09:00:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + card-funding-source-change: + post: + summary: Card funding source change + description: | + Webhook that is called when the funding sources bound to a card change. Fires whenever `PATCH /cards/{id}` updates the `fundingSources` array. The payload carries the full `Card` resource with the post-change `fundingSources` array. + + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: cardFundingSourceChangeWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CardFundingSourceChangeWebhook' + examples: + fundingSourcesReplaced: + summary: Funding sources replaced via PATCH /cards/{id} + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000030 + type: CARD.FUNDING_SOURCE_CHANGE + timestamp: '2026-05-08T14:30:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + state: ACTIVE + stateReason: null + brand: VISA + form: VIRTUAL + last4: '4242' + expMonth: 12 + expYear: 2029 + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 + currency: USD + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-08T14:30:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' +components: + securitySchemes: + BasicAuth: + type: http + scheme: basic + description: API token authentication using format `:` + AgentAuth: + type: http + scheme: bearer + description: 'Bearer token authentication for agent-scoped endpoints. The token is the `accessToken` returned when redeeming a device code via `POST /agents/device-codes/{code}/redeem`. Agent credentials are user-scoped: all requests are automatically bound to the agent''s associated customer and subject to the agent''s policy.' + WebhookSignature: + type: apiKey + in: header + name: X-Grid-Signature + description: | + Secp256r1 (P-256) asymmetric signature of the webhook payload, which can be used to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + schemas: + CustomerInfoFieldName: + type: string + enum: + - FULL_NAME + - BIRTH_DATE + - NATIONALITY + - PHONE_NUMBER + - EMAIL + - POSTAL_ADDRESS + - TAX_ID + - REGISTRATION_NUMBER + - USER_TYPE + - COUNTRY_OF_RESIDENCE + - ACCOUNT_IDENTIFIER + - FI_LEGAL_ENTITY_NAME + - FI_ADDRESS + - PURPOSE_OF_PAYMENT + - ULTIMATE_INSTITUTION_COUNTRY + - IDENTIFIER + - BUSINESS_TYPE + - COMPANY_LEGAL_NAME + - ID_TYPE + - ID_NUMBER + description: Name of a type of field containing info about a platform's customer or counterparty customer. + example: FULL_NAME + CounterpartyFieldDefinition: + type: object + properties: + name: + $ref: '#/components/schemas/CustomerInfoFieldName' + mandatory: + type: boolean + description: Whether the field is mandatory + example: true + required: + - name + - mandatory + TransactionType: + type: string + enum: + - INCOMING + - OUTGOING + description: Type of transaction (incoming payment or outgoing payment) + PlatformCurrencyConfig: + type: object + properties: + currencyCode: + type: string + description: Three-letter currency code (ISO 4217) + example: USD + minAmount: + type: integer + format: int64 + description: Minimum amount that can be sent in the smallest unit of this currency + minimum: 0 + example: 100 + maxAmount: + type: integer + format: int64 + description: Maximum amount that can be sent in the smallest unit of this currency + minimum: 0 + example: 1000000 + requiredCounterpartyFields: + type: array + items: + $ref: '#/components/schemas/CounterpartyFieldDefinition' + description: List of fields which the platform requires from the counterparty institutions about counterparty customers. Platforms can set mandatory to false if the platform does not require the field, but would like to have it available. Some fields may be required by the underlying UMA provider. + example: + - name: FULL_NAME + mandatory: true + - name: BIRTH_DATE + mandatory: true + - name: NATIONALITY + mandatory: true + providerRequiredCustomerFields: + type: array + items: + $ref: '#/components/schemas/CustomerInfoFieldName' + description: List of customer info field names that are required by the underlying UMA provider when creating a customer for this currency. These fields must be supplied when creating or updating a customer if this currency is intended to be used by that customer. If no fields are required, this field is omitted. + readOnly: true + example: + - NATIONALITY + - BIRTH_DATE + providerRequiredCounterpartyCustomerFields: + type: array + items: + $ref: '#/components/schemas/CustomerInfoFieldName' + description: List of fields that are required by the underlying UMA provider for this currency. If the counterparty does not provide these fields, quote requests will fail. + readOnly: true + example: + - FULL_NAME + - COUNTRY_OF_RESIDENCE + enabledTransactionTypes: + type: array + items: + $ref: '#/components/schemas/TransactionType' + description: List of transaction types that are enabled for this currency. + example: + - OUTGOING + - INCOMING + required: + - currencyCode + - minAmount + - maxAmount + - requiredCounterpartyFields + - enabledTransactionTypes + EmbeddedWalletConfig: + type: object + description: | + Per-platform embedded-wallet configuration. Controls branding and OTP + behavior for the email sent when a customer authenticates with an + EMAIL_OTP credential. Fields omitted from a request are left unchanged. + properties: + appName: + type: string + maxLength: 255 + description: App name displayed in the default OTP email template. + example: Acme Wallet + otpLength: + type: integer + minimum: 4 maximum: 12 description: | Number of digits / characters in the OTP code. Defaults to 6 when @@ -8355,6 +9188,22 @@ components: | INCOMPLETE | Document is missing pages or sides | | EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS | An EMAIL_OTP credential is already registered on the target internal account; only one email OTP credential is supported per internal account at this time | | PASSKEY_CREDENTIAL_ALREADY_EXISTS | A PASSKEY credential with the same WebAuthn credentialId is already registered on the target internal account | + | STABLECOIN_PROVIDER_ACCOUNT_INVALID | The stablecoin provider account link is not usable | + | STABLECOIN_PROVIDER_ACCOUNT_REVOKED | The stablecoin provider account link has been revoked | + | STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active provider account links exist; pass `stablecoinProviderAccountId` to select one | + | STABLECOIN_VERIFICATION_FAILED | Provider verification of the stablecoin or credentials failed | + | STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED | Linking the external account with the provider failed | + | STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED | The request must specify a supported external-account link method | + | STABLECOIN_NOT_PROVISIONED | The stablecoin is not provisioned with the provider | + | STABLECOIN_GRID_OPERATIONS_NOT_ENABLED | Grid operations are not enabled for this stablecoin | + | STABLECOIN_QUOTE_EXPIRED | The stablecoin quote has expired | + | STABLECOIN_AMOUNT_NOT_REPRESENTABLE | The amount cannot be represented in the target currency or token precision | + | STABLECOIN_OPERATION_NOT_SUPPORTED | The requested stablecoin operation is not supported | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED | The stablecoin external account is not linked or not active | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED | The stablecoin external account does not support the requested transfer type | + | STABLECOIN_BURN_SOURCE_NOT_SUPPORTED | The burn source account is not supported | + | STABLECOIN_PROVIDER_SOURCE_NOT_LINKED | The provider token-balance funding source is not linked | + | STABLECOIN_PROVIDER_ERROR | The stablecoin provider rejected or failed the request | enum: - INVALID_INPUT - MISSING_MANDATORY_USER_INFO @@ -8391,6 +9240,22 @@ components: - INCOMPLETE - EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS - PASSKEY_CREDENTIAL_ALREADY_EXISTS + - STABLECOIN_PROVIDER_ACCOUNT_INVALID + - STABLECOIN_PROVIDER_ACCOUNT_REVOKED + - STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED + - STABLECOIN_VERIFICATION_FAILED + - STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED + - STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED + - STABLECOIN_NOT_PROVISIONED + - STABLECOIN_GRID_OPERATIONS_NOT_ENABLED + - STABLECOIN_QUOTE_EXPIRED + - STABLECOIN_AMOUNT_NOT_REPRESENTABLE + - STABLECOIN_OPERATION_NOT_SUPPORTED + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED + - STABLECOIN_BURN_SOURCE_NOT_SUPPORTED + - STABLECOIN_PROVIDER_SOURCE_NOT_LINKED + - STABLECOIN_PROVIDER_ERROR message: type: string description: Error message @@ -9287,12 +10152,16 @@ components: | EMAIL_OTP_EMAIL_ALREADY_EXISTS | Email address is already associated with an EMAIL_OTP credential | | EMAIL_OTP_CREDENTIAL_SET_CHANGED | Tied EMAIL_OTP credential set changed after the signed-retry challenge was issued | | CONFLICT | Generic resource-state conflict. Returned, for example, when `platformCustomerId` on a customer create call collides with an existing active customer on the same platform | + | STABLECOIN_SYMBOL_ALREADY_EXISTS | A stablecoin with the same symbol is already registered for this platform | + | STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS | A stablecoin with the same network token identifier is already registered | enum: - TRANSACTION_NOT_PENDING_PLATFORM_APPROVAL - UMA_ADDRESS_EXISTS - EMAIL_OTP_EMAIL_ALREADY_EXISTS - EMAIL_OTP_CREDENTIAL_SET_CHANGED - CONFLICT + - STABLECOIN_SYMBOL_ALREADY_EXISTS + - STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS message: type: string description: Error message @@ -9326,6 +10195,11 @@ components: | BULK_UPLOAD_JOB_NOT_FOUND | Bulk upload job not found | | REFERENCE_NOT_FOUND | Reference not found | | UMA_NOT_FOUND | The UMA address is well-formed but no receiver exists at the counterparty VASP | + | STABLECOIN_NOT_FOUND | Stablecoin not found | + | STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND | Stablecoin provider account link not found | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND | Stablecoin external account not found | + | STABLECOIN_QUOTE_NOT_FOUND | Stablecoin quote not found | + | STABLECOIN_OPERATION_NOT_FOUND | Stablecoin operation not found | enum: - TRANSACTION_NOT_FOUND - INVITATION_NOT_FOUND @@ -9336,6 +10210,11 @@ components: - BULK_UPLOAD_JOB_NOT_FOUND - REFERENCE_NOT_FOUND - UMA_NOT_FOUND + - STABLECOIN_NOT_FOUND + - STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND + - STABLECOIN_QUOTE_NOT_FOUND + - STABLECOIN_OPERATION_NOT_FOUND message: type: string description: Error message @@ -15393,44 +16272,421 @@ components: allOf: - type: object required: - - currency - - accountInfo + - currency + - accountInfo + properties: + customerId: + type: string + description: The ID of the customer for whom to create the external account. If not provided, the external account will be created on behalf of the platform. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + currency: + type: string + description: The ISO 4217 currency code + example: USD + platformAccountId: + type: string + description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. + example: ext_acc_123456 + defaultUmaDepositAccount: + type: boolean + description: Whether to set the external account as the default UMA deposit account. When set to true, incoming payments to this customer's UMA address will be automatically deposited into this external account. False if not provided. Note that only one external account can be set as the default UMA deposit account for a customer, so if there is already a default UMA deposit account, this will override the existing default UMA deposit account. If there is no default UMA deposit account, incoming UMA payments will be deposited into the primary internal account for the customer. + default: false + accountInfo: + $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' + PlatformExternalAccountCreateRequest: + type: object + required: + - currency + - accountInfo + properties: + currency: + type: string + description: The ISO 4217 currency code + example: USD + platformAccountId: + type: string + description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. + example: ext_acc_123456 + accountInfo: + $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' + BeneficialOwnerListResponse: + type: object + required: + - data + - hasMore + properties: + data: + type: array + description: List of beneficial owners matching the filter criteria + items: + $ref: '#/components/schemas/BeneficialOwner' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of results matching the criteria + BeneficialOwnerCreateRequest: + type: object + required: + - customerId + - roles + - ownershipPercentage + - personalInfo + properties: + customerId: + type: string + description: The ID of the business customer this beneficial owner is associated with + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + roles: + type: array + items: + $ref: '#/components/schemas/BeneficialOwnerRole' + description: Roles of this person within the business + example: + - UBO + - DIRECTOR + ownershipPercentage: + type: integer + description: Percentage of ownership in the business (0-100). Relevant when role includes UBO. + minimum: 0 + maximum: 100 + example: 51 + personalInfo: + $ref: '#/components/schemas/BeneficialOwnerPersonalInfo' + BeneficialOwnerPersonalInfoUpdate: + type: object + description: Partial update for beneficial owner personal information. Only provided fields are updated. + properties: + firstName: + type: string + description: First name of the individual + example: Jane + middleName: + type: string + description: Middle name of the individual + example: Marie + lastName: + type: string + description: Last name of the individual + example: Smith + birthDate: + type: string + format: date + description: Date of birth in ISO 8601 format (YYYY-MM-DD) + example: '1978-06-15' + nationality: + type: string + description: Country of nationality (ISO 3166-1 alpha-2) + example: US + email: + type: string + format: email + description: Email address of the individual + example: jane.smith@acmecorp.com + phoneNumber: + type: string + description: Phone number in E.164 format + example: '+14155550192' + pattern: ^\+[1-9]\d{1,14}$ + address: + $ref: '#/components/schemas/Address' + idType: + $ref: '#/components/schemas/IdentificationType' + identifier: + type: string + description: The identification number or value + example: 123-45-6789 + countryOfIssuance: + type: string + description: Country that issued the identification (ISO 3166-1 alpha-2) + example: US + BeneficialOwnerUpdateRequest: + type: object + properties: + roles: + type: array + items: + $ref: '#/components/schemas/BeneficialOwnerRole' + description: Roles of this person within the business + example: + - UBO + - DIRECTOR + ownershipPercentage: + type: integer + description: Percentage of ownership in the business (0-100) + minimum: 0 + maximum: 100 + example: 51 + personalInfo: + $ref: '#/components/schemas/BeneficialOwnerPersonalInfoUpdate' + DocumentType: + type: string + enum: + - PASSPORT + - DRIVERS_LICENSE + - NATIONAL_ID + - PROOF_OF_ADDRESS + - BANK_STATEMENT + - TAX_RETURN + - CERTIFICATE_OF_INCORPORATION + - ARTICLES_OF_INCORPORATION + - ARTICLES_OF_ASSOCIATION + - STATE_REGISTRY_EXCERPT + - GOOD_STANDING_CERTIFICATE + - INFORMATION_STATEMENT + - INCUMBENCY_CERTIFICATE + - BUSINESS_LICENSE + - SHAREHOLDER_REGISTER + - POWER_OF_ATTORNEY + - UTILITY_BILL + - ELECTRICITY_BILL + - RENT_OR_LEASE_AGREEMENT + - DIRECTOR_REGISTRY + - TRUST_AGREEMENT + - STATE_COMPANY_REGISTRY + - PARTNERSHIP_CONTROL_AGREEMENT + - PARTNERSHIP_AGREEMENT + - SELFIE + - OTHER + description: |- + Type of identity or business verification document. Document types are grouped by verification category: + **Identity** — PASSPORT, DRIVERS_LICENSE, NATIONAL_ID + **Business — Legal presence** — CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT + **Business — Control structure** — DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT + **Business — Ownership structure** — SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT + **Proof of address** — UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN + example: PASSPORT + Document: + type: object + required: + - id + - documentHolder + - documentType + - country + - fileName + - createdAt + properties: + id: + type: string + description: Unique identifier for this document + example: Document:019542f5-b3e7-1d02-0000-000000000001 + documentHolder: + type: string + description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. + example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 + documentType: + $ref: '#/components/schemas/DocumentType' + side: + type: string + enum: + - FRONT + - BACK + description: Which side of the document this upload represents. Relevant for two-sided documents like driver's licenses or national IDs. + example: FRONT + country: + type: string + description: Country that issued the document (ISO 3166-1 alpha-2) + example: US + documentNumber: + type: string + description: Document identification number (e.g., passport number) + example: A12345678 + issuingAuthority: + type: string + description: Name of the government agency or organization that issued the document + example: U.S. Department of State + fileName: + type: string + description: Original file name of the uploaded document + example: passport_scan.pdf + createdAt: + type: string + format: date-time + description: When this document was uploaded + example: '2025-10-03T12:00:00Z' + updatedAt: + type: string + format: date-time + description: When this document was last updated + example: '2025-10-03T12:00:00Z' + DocumentListResponse: + type: object + required: + - data + - hasMore + properties: + data: + type: array + description: List of documents matching the filter criteria + items: + $ref: '#/components/schemas/Document' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of results matching the criteria + BaseDocumentRequest: + type: object + required: + - file + - documentType + - country + properties: + file: + type: string + format: binary + description: The document file (PDF, JPEG, or PNG, max 10 MB) + documentType: + $ref: '#/components/schemas/DocumentType' + side: + type: string + enum: + - FRONT + - BACK + description: Which side of the document (for two-sided documents like driver's licenses) + example: FRONT + country: + type: string + description: Country that issued the document (ISO 3166-1 alpha-2) + example: US + documentNumber: + type: string + description: Document identification number (e.g., passport number) + example: A12345678 + issuingAuthority: + type: string + description: Name of the government agency or organization that issued the document + example: U.S. Department of State + DocumentUploadRequest: + title: Document Upload Request + allOf: + - $ref: '#/components/schemas/BaseDocumentRequest' + - type: object + required: + - documentHolder properties: - customerId: - type: string - description: The ID of the customer for whom to create the external account. If not provided, the external account will be created on behalf of the platform. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - currency: - type: string - description: The ISO 4217 currency code - example: USD - platformAccountId: + documentHolder: type: string - description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. - example: ext_acc_123456 - defaultUmaDepositAccount: - type: boolean - description: Whether to set the external account as the default UMA deposit account. When set to true, incoming payments to this customer's UMA address will be automatically deposited into this external account. False if not provided. Note that only one external account can be set as the default UMA deposit account for a customer, so if there is already a default UMA deposit account, this will override the existing default UMA deposit account. If there is no default UMA deposit account, incoming UMA payments will be deposited into the primary internal account for the customer. - default: false - accountInfo: - $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' - PlatformExternalAccountCreateRequest: + description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. + example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 + DocumentReplaceRequest: + title: Document Replace Request + allOf: + - $ref: '#/components/schemas/BaseDocumentRequest' + VerificationStatus: + type: string + enum: + - RESOLVE_ERRORS + - PENDING_MANUAL_REVIEW + - IN_PROGRESS + - APPROVED + - REJECTED + - READY_FOR_VERIFICATION + description: Current status of the KYC/KYB verification + example: RESOLVE_ERRORS + VerificationErrorType: + type: string + enum: + - MISSING_FIELD + - INVALID_FIELD + - MISSING_LEGAL_PRESENCE_DOCUMENT + - MISSING_CONTROL_STRUCTURE_DOCUMENT + - MISSING_OWNERSHIP_STRUCTURE_DOCUMENT + - MISSING_PROOF_OF_ADDRESS_DOCUMENT + - MISSING_IDENTITY_DOCUMENT + - INVALID_DOCUMENT + - EXPIRED_DOCUMENT + - POOR_QUALITY_DOCUMENT + - SUSPECTED_FRAUD_DOCUMENT + - WRONG_DOCUMENT_TYPE + - INCOMPLETE_DOCUMENT + - UNREADABLE_DOCUMENT + - DOCUMENT_VERIFICATION_FAILED + - APPLICANT_SANCTIONED + - APPLICANT_FRAUD + - APPLICANT_CRIMINAL_RECORD + - APPLICANT_REJECTED + - MISSING_BENEFICIAL_OWNER + description: Type of verification error. The category-specific MISSING_*_DOCUMENT types indicate which document category is needed. Document quality types (POOR_QUALITY_DOCUMENT, SUSPECTED_FRAUD_DOCUMENT, etc.) indicate specific issues with uploaded documents. APPLICANT_* types indicate issues with the applicant themselves (sanctions, fraud, criminal records). + example: MISSING_FIELD + VerificationError: type: object required: - - currency - - accountInfo + - resourceId + - type + - reason properties: - currency: + resourceId: type: string - description: The ISO 4217 currency code - example: USD - platformAccountId: + description: ID of the resource with the issue (Customer, BeneficialOwner, or Document) + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: + $ref: '#/components/schemas/VerificationErrorType' + field: type: string - description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. - example: ext_acc_123456 - accountInfo: - $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' - BeneficialOwnerListResponse: + description: Dot-notation path to the field with the issue. Present when type is MISSING_FIELD or INVALID_FIELD. + example: customer.address.line1 + acceptedDocumentTypes: + type: array + items: + $ref: '#/components/schemas/DocumentType' + description: |- + Document types that would satisfy this requirement. The integrator can upload any one of the listed types. Present when type is MISSING_LEGAL_PRESENCE_DOCUMENT, MISSING_CONTROL_STRUCTURE_DOCUMENT, MISSING_OWNERSHIP_STRUCTURE_DOCUMENT, MISSING_PROOF_OF_ADDRESS_DOCUMENT, MISSING_IDENTITY_DOCUMENT, INVALID_DOCUMENT, or EXPIRED_DOCUMENT. + + | Error Type | Accepted Document Types | + |---|---| + | MISSING_LEGAL_PRESENCE_DOCUMENT | CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT | + | MISSING_CONTROL_STRUCTURE_DOCUMENT | DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT | + | MISSING_OWNERSHIP_STRUCTURE_DOCUMENT | SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT | + | MISSING_PROOF_OF_ADDRESS_DOCUMENT | UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN | + | MISSING_IDENTITY_DOCUMENT | PASSPORT, DRIVERS_LICENSE, NATIONAL_ID | + reason: + type: string + description: Human-readable description of the issue + example: Business address line 1 is required + Verification: + type: object + required: + - id + - customerId + - verificationStatus + - errors + - createdAt + properties: + id: + type: string + description: Unique identifier for this verification + example: Verification:019542f5-b3e7-1d02-0000-000000000001 + customerId: + type: string + description: The ID of the customer being verified + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + verificationStatus: + $ref: '#/components/schemas/VerificationStatus' + errors: + type: array + description: List of issues preventing verification from proceeding. Empty when verificationStatus is APPROVED or IN_PROGRESS. + items: + $ref: '#/components/schemas/VerificationError' + createdAt: + type: string + format: date-time + description: When this verification was created + example: '2025-10-03T12:00:00Z' + updatedAt: + type: string + format: date-time + description: When this verification was last updated + example: '2025-10-03T12:00:00Z' + VerificationListResponse: type: object required: - data @@ -15438,9 +16694,9 @@ components: properties: data: type: array - description: List of beneficial owners matching the filter criteria + description: List of verifications matching the filter criteria items: - $ref: '#/components/schemas/BeneficialOwner' + $ref: '#/components/schemas/Verification' hasMore: type: boolean description: Indicates if more results are available beyond this page @@ -15450,393 +16706,606 @@ components: totalCount: type: integer description: Total number of results matching the criteria - BeneficialOwnerCreateRequest: + VerificationRequest: type: object required: - customerId - - roles - - ownershipPercentage - - personalInfo properties: customerId: type: string - description: The ID of the business customer this beneficial owner is associated with + description: The ID of the customer to verify example: Customer:019542f5-b3e7-1d02-0000-000000000001 - roles: - type: array - items: - $ref: '#/components/schemas/BeneficialOwnerRole' - description: Roles of this person within the business - example: - - UBO - - DIRECTOR - ownershipPercentage: - type: integer - description: Percentage of ownership in the business (0-100). Relevant when role includes UBO. - minimum: 0 - maximum: 100 - example: 51 - personalInfo: - $ref: '#/components/schemas/BeneficialOwnerPersonalInfo' - BeneficialOwnerPersonalInfoUpdate: + ExternalAccountReference: type: object - description: Partial update for beneficial owner personal information. Only provided fields are updated. + required: + - accountId properties: - firstName: - type: string - description: First name of the individual - example: Jane - middleName: - type: string - description: Middle name of the individual - example: Marie - lastName: - type: string - description: Last name of the individual - example: Smith - birthDate: - type: string - format: date - description: Date of birth in ISO 8601 format (YYYY-MM-DD) - example: '1978-06-15' - nationality: - type: string - description: Country of nationality (ISO 3166-1 alpha-2) - example: US - email: - type: string - format: email - description: Email address of the individual - example: jane.smith@acmecorp.com - phoneNumber: + accountId: type: string - description: Phone number in E.164 format - example: '+14155550192' - pattern: ^\+[1-9]\d{1,14}$ - address: - $ref: '#/components/schemas/Address' - idType: - $ref: '#/components/schemas/IdentificationType' - identifier: + description: Reference to an external account ID + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + InternalAccountReference: + type: object + required: + - accountId + properties: + accountId: type: string - description: The identification number or value - example: 123-45-6789 - countryOfIssuance: + description: Reference to an internal account ID + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + TransferInRequest: + type: object + required: + - source + - destination + properties: + source: + $ref: '#/components/schemas/ExternalAccountReference' + description: Source external account details + destination: + $ref: '#/components/schemas/InternalAccountReference' + description: Destination internal account details + amount: + type: integer + format: int64 + description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) + example: 12550 + TransactionStatus: + type: string + enum: + - CREATED + - PENDING + - PROCESSING + - COMPLETED + - REJECTED + - FAILED + - REFUNDED + - EXPIRED + description: | + Status of a payment transaction. + + | Status | Description | + |--------|-------------| + | `CREATED` | Initial lookup has been created | + | `PENDING` | Quote has been created | + | `PROCESSING` | Funding has been received and payment initiated | + | `COMPLETED` | Cross border payment has been received, converted and payment has been sent to the offramp network | + | `REJECTED` | Receiving institution or wallet rejected payment, payment has been refunded | + | `FAILED` | An error occurred during payment | + | `REFUNDED` | Payment was unable to complete and refunded | + | `EXPIRED` | Quote has expired | + TransactionDestinationType: + type: string + enum: + - ACCOUNT + - UMA_ADDRESS + description: Type of transaction destination + example: ACCOUNT + BaseTransactionDestination: + type: object + required: + - destinationType + properties: + destinationType: + $ref: '#/components/schemas/TransactionDestinationType' + currency: type: string - description: Country that issued the identification (ISO 3166-1 alpha-2) - example: US - BeneficialOwnerUpdateRequest: + description: Currency code for the destination + example: EUR + AccountTransactionDestination: + title: Account Destination + allOf: + - $ref: '#/components/schemas/BaseTransactionDestination' + - type: object + required: + - accountId + - destinationType + properties: + destinationType: + type: string + enum: + - ACCOUNT + accountId: + type: string + description: Destination account identifier + example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + description: Destination account details + UmaAddressTransactionDestination: + title: UMA Address Destination + allOf: + - $ref: '#/components/schemas/BaseTransactionDestination' + - type: object + required: + - umaAddress + - destinationType + properties: + destinationType: + type: string + enum: + - UMA_ADDRESS + umaAddress: + type: string + description: UMA address of the recipient + example: $receiver@uma.domain.com + description: UMA address destination details + TransactionDestinationOneOf: + oneOf: + - $ref: '#/components/schemas/AccountTransactionDestination' + - $ref: '#/components/schemas/UmaAddressTransactionDestination' + discriminator: + propertyName: destinationType + mapping: + ACCOUNT: '#/components/schemas/AccountTransactionDestination' + UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionDestination' + CounterpartyInformation: type: object - properties: - roles: - type: array - items: - $ref: '#/components/schemas/BeneficialOwnerRole' - description: Roles of this person within the business - example: - - UBO - - DIRECTOR - ownershipPercentage: - type: integer - description: Percentage of ownership in the business (0-100) - minimum: 0 - maximum: 100 - example: 51 - personalInfo: - $ref: '#/components/schemas/BeneficialOwnerPersonalInfoUpdate' - DocumentType: - type: string - enum: - - PASSPORT - - DRIVERS_LICENSE - - NATIONAL_ID - - PROOF_OF_ADDRESS - - BANK_STATEMENT - - TAX_RETURN - - CERTIFICATE_OF_INCORPORATION - - ARTICLES_OF_INCORPORATION - - ARTICLES_OF_ASSOCIATION - - STATE_REGISTRY_EXCERPT - - GOOD_STANDING_CERTIFICATE - - INFORMATION_STATEMENT - - INCUMBENCY_CERTIFICATE - - BUSINESS_LICENSE - - SHAREHOLDER_REGISTER - - POWER_OF_ATTORNEY - - UTILITY_BILL - - ELECTRICITY_BILL - - RENT_OR_LEASE_AGREEMENT - - DIRECTOR_REGISTRY - - TRUST_AGREEMENT - - STATE_COMPANY_REGISTRY - - PARTNERSHIP_CONTROL_AGREEMENT - - PARTNERSHIP_AGREEMENT - - SELFIE - - OTHER - description: |- - Type of identity or business verification document. Document types are grouped by verification category: - **Identity** — PASSPORT, DRIVERS_LICENSE, NATIONAL_ID - **Business — Legal presence** — CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT - **Business — Control structure** — DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT - **Business — Ownership structure** — SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT - **Proof of address** — UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN - example: PASSPORT - Document: + description: Additional information about the counterparty, if available and relevant to the transaction and platform. + additionalProperties: true + example: + FULL_NAME: John Sender + BIRTH_DATE: '1985-06-15' + NATIONALITY: DE + Transaction: type: object required: - id - - documentHolder - - documentType - - country - - fileName - - createdAt + - status + - type + - destination + - customerId + - platformCustomerId properties: id: type: string - description: Unique identifier for this document - example: Document:019542f5-b3e7-1d02-0000-000000000001 - documentHolder: - type: string - description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. - example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 - documentType: - $ref: '#/components/schemas/DocumentType' - side: - type: string - enum: - - FRONT - - BACK - description: Which side of the document this upload represents. Relevant for two-sided documents like driver's licenses or national IDs. - example: FRONT - country: - type: string - description: Country that issued the document (ISO 3166-1 alpha-2) - example: US - documentNumber: + description: Unique identifier for the transaction + example: Transaction:019542f5-b3e7-1d02-0000-000000000004 + status: + $ref: '#/components/schemas/TransactionStatus' + type: + $ref: '#/components/schemas/TransactionType' + destination: + $ref: '#/components/schemas/TransactionDestinationOneOf' + customerId: type: string - description: Document identification number (e.g., passport number) - example: A12345678 - issuingAuthority: + description: System ID of the customer (sender for outgoing, recipient for incoming) + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: type: string - description: Name of the government agency or organization that issued the document - example: U.S. Department of State - fileName: + description: Platform-specific ID of the customer (sender for outgoing, recipient for incoming) + example: 18d3e5f7b4a9c2 + settledAt: type: string - description: Original file name of the uploaded document - example: passport_scan.pdf + format: date-time + description: When the payment was or will be settled + example: '2025-08-15T14:30:00Z' createdAt: type: string format: date-time - description: When this document was uploaded - example: '2025-10-03T12:00:00Z' + description: When the transaction was created + example: '2025-08-15T14:25:18Z' updatedAt: type: string format: date-time - description: When this document was last updated - example: '2025-10-03T12:00:00Z' - DocumentListResponse: + description: When the transaction was last updated + example: '2025-08-15T14:30:00Z' + receiptDeliveryConfirmedAt: + type: string + format: date-time + description: The time at which the platform confirmed delivery of the receipt to their customer. + example: '2025-08-15T14:31:00Z' + agentId: + type: string + description: If this transaction was initiated by an agent, the system-generated ID of that agent. Absent for platform-initiated transactions. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 + description: + type: string + description: Optional memo or description for the payment + example: 'Payment for invoice #1234' + counterpartyInformation: + $ref: '#/components/schemas/CounterpartyInformation' + TransactionSourceType: + type: string + enum: + - ACCOUNT + - UMA_ADDRESS + - REALTIME_FUNDING + description: Type of transaction source + example: ACCOUNT + BaseTransactionSource: + type: object + required: + - sourceType + properties: + sourceType: + $ref: '#/components/schemas/TransactionSourceType' + currency: + type: string + description: Currency code for the source + example: USD + AccountTransactionSource: + title: Account Source + allOf: + - $ref: '#/components/schemas/BaseTransactionSource' + - type: object + required: + - accountId + - sourceType + properties: + sourceType: + type: string + enum: + - ACCOUNT + accountId: + type: string + description: Source account identifier + example: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + description: Source account details + UmaAddressTransactionSource: + title: UMA Address Source + allOf: + - $ref: '#/components/schemas/BaseTransactionSource' + - type: object + required: + - umaAddress + - sourceType + properties: + sourceType: + type: string + enum: + - UMA_ADDRESS + umaAddress: + type: string + description: UMA address of the sender + example: $sender@uma.domain.com + description: UMA address source details + RealtimeFundingTransactionSource: + title: External Funding Source + allOf: + - $ref: '#/components/schemas/BaseTransactionSource' + - type: object + required: + - currency + - sourceType + properties: + sourceType: + type: string + enum: + - REALTIME_FUNDING + customerId: + type: string + description: The customer on whose behalf the transaction was initiated. + example: Customer:019542f5-b3e7-1d02-0000-000000000009 + currency: + type: string + description: Currency code for the funding source + example: USDC + accountHolderName: + type: string + description: The name of the originator (sender) of the payment. + example: John Sender + accountIdentifier: + type: string + description: The originator's account number or IBAN. May be masked or partial depending on the rail. + example: '****6789' + bankName: + type: string + description: The name of the originating bank. + example: Chase Bank + bankIdentifier: + type: string + description: The identifier of the originating bank, such as a routing number, BIC, or SWIFT code. + example: '021000021' + paymentRail: + description: The payment rail the funds arrived on. + allOf: + - $ref: '#/components/schemas/PaymentRail' + remittanceInformation: + type: string + description: 'Free-form information about the payment provided by the originator. The source field depends on the payment rail: the Addenda record for ACH, the OBI / beneficiary information for wires, and the remittanceInformation field for RTP and FedNow.' + example: '12345' + endToEndId: + type: string + description: The originator's own end-to-end reference for the payment. + example: E2E-9f2c6b6f + traceNumber: + type: string + description: Rail-level tracking identifier for the payment, such as an ACH trace number or a wire IMAD/OMAD, useful for reconciliation. + example: '021000020123456' + description: Transaction was funded using an external funding source. All originator fields are optional and populated on a best-effort basis depending on what the funding source provides. + TransactionSourceOneOf: + oneOf: + - $ref: '#/components/schemas/AccountTransactionSource' + - $ref: '#/components/schemas/UmaAddressTransactionSource' + - $ref: '#/components/schemas/RealtimeFundingTransactionSource' + discriminator: + propertyName: sourceType + mapping: + ACCOUNT: '#/components/schemas/AccountTransactionSource' + UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionSource' + REALTIME_FUNDING: '#/components/schemas/RealtimeFundingTransactionSource' + ReconciliationInstructions: type: object - required: - - data - - hasMore + minProperties: 1 properties: - data: - type: array - description: List of documents matching the filter criteria - items: - $ref: '#/components/schemas/Document' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: + reference: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: - type: integer - description: Total number of results matching the criteria - BaseDocumentRequest: + description: Unique reference code to include with the payment to match it with the correct incoming transaction, when available. + example: UMA-Q12345-REF + transactionHash: + type: string + description: Transaction hash for the crypto transfer that delivered funds to the transaction destination, when available. + example: '0x9f2c6b6f4b6c8f2a8d9e0b1c2d3e4f5061728394a5b6c7d8e9f00112233445566' + IncomingRateDetails: + description: 'Details about the rate and fees for an incoming transaction. Note: `gridApiFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' type: object required: - - file - - documentType - - country + - gridApiMultiplier + - gridApiFixedFee + - gridApiVariableFeeRate + - gridApiVariableFeeAmount properties: - file: - type: string - format: binary - description: The document file (PDF, JPEG, or PNG, max 10 MB) - documentType: - $ref: '#/components/schemas/DocumentType' - side: - type: string - enum: - - FRONT - - BACK - description: Which side of the document (for two-sided documents like driver's licenses) - example: FRONT - country: - type: string - description: Country that issued the document (ISO 3166-1 alpha-2) - example: US - documentNumber: - type: string - description: Document identification number (e.g., passport number) - example: A12345678 - issuingAuthority: - type: string - description: Name of the government agency or organization that issued the document - example: U.S. Department of State - DocumentUploadRequest: - title: Document Upload Request + gridApiMultiplier: + type: number + format: double + description: The underlying multiplier from the mSATS to the receiving currency, including variable fees. + exclusiveMinimum: 0 + example: 0.925 + gridApiFixedFee: + type: integer + format: int64 + description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). + minimum: 0 + example: 10 + gridApiVariableFeeRate: + type: number + format: double + description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the receiving currency amount. + minimum: 0 + example: 0.003 + gridApiVariableFeeAmount: + type: number + format: int64 + description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). This is the receiving amount times gridApiVariableFeeRate. + minimum: 0 + example: 30 + IncomingTransactionFailureReason: + type: string + enum: + - LNURLP_FAILED + - PAY_REQUEST_FAILED + - PAYMENT_APPROVAL_WEBHOOK_ERROR + - PAYMENT_APPROVAL_TIMED_OUT + - OFFRAMP_FAILED + - MISSING_MANDATORY_PAYEE_DATA + - QUOTE_EXPIRED + - QUOTE_EXECUTION_FAILED + description: Reason for failure of an incoming transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. + IncomingTransaction: + title: Incoming Transaction allOf: - - $ref: '#/components/schemas/BaseDocumentRequest' + - $ref: '#/components/schemas/Transaction' - type: object required: - - documentHolder + - type + - receivedAmount properties: - documentHolder: + type: type: string - description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. - example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 - DocumentReplaceRequest: - title: Document Replace Request - allOf: - - $ref: '#/components/schemas/BaseDocumentRequest' - VerificationStatus: - type: string - enum: - - RESOLVE_ERRORS - - PENDING_MANUAL_REVIEW - - IN_PROGRESS - - APPROVED - - REJECTED - - READY_FOR_VERIFICATION - description: Current status of the KYC/KYB verification - example: RESOLVE_ERRORS - VerificationErrorType: + enum: + - INCOMING + source: + $ref: '#/components/schemas/TransactionSourceOneOf' + receivedAmount: + $ref: '#/components/schemas/CurrencyAmount' + description: Amount received in the recipient's currency + fees: + type: integer + format: int64 + description: The total fees available from the receive quote in the smallest unit of the receiving currency (eg. cents). + minimum: 0 + example: 10 + reconciliationInstructions: + $ref: '#/components/schemas/ReconciliationInstructions' + description: Included for all transactions except those with "CREATED" status + rateDetails: + $ref: '#/components/schemas/IncomingRateDetails' + description: Details about the rate and fees for the transaction. + failureReason: + $ref: '#/components/schemas/IncomingTransactionFailureReason' + description: If the transaction failed, this field provides the reason for failure. + OutgoingTransactionStatus: type: string enum: - - MISSING_FIELD - - INVALID_FIELD - - MISSING_LEGAL_PRESENCE_DOCUMENT - - MISSING_CONTROL_STRUCTURE_DOCUMENT - - MISSING_OWNERSHIP_STRUCTURE_DOCUMENT - - MISSING_PROOF_OF_ADDRESS_DOCUMENT - - MISSING_IDENTITY_DOCUMENT - - INVALID_DOCUMENT - - EXPIRED_DOCUMENT - - POOR_QUALITY_DOCUMENT - - SUSPECTED_FRAUD_DOCUMENT - - WRONG_DOCUMENT_TYPE - - INCOMPLETE_DOCUMENT - - UNREADABLE_DOCUMENT - - DOCUMENT_VERIFICATION_FAILED - - APPLICANT_SANCTIONED - - APPLICANT_FRAUD - - APPLICANT_CRIMINAL_RECORD - - APPLICANT_REJECTED - - MISSING_BENEFICIAL_OWNER - description: Type of verification error. The category-specific MISSING_*_DOCUMENT types indicate which document category is needed. Document quality types (POOR_QUALITY_DOCUMENT, SUSPECTED_FRAUD_DOCUMENT, etc.) indicate specific issues with uploaded documents. APPLICANT_* types indicate issues with the applicant themselves (sanctions, fraud, criminal records). - example: MISSING_FIELD - VerificationError: - type: object - required: - - resourceId - - type - - reason - properties: - resourceId: - type: string - description: ID of the resource with the issue (Customer, BeneficialOwner, or Document) - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: - $ref: '#/components/schemas/VerificationErrorType' - field: - type: string - description: Dot-notation path to the field with the issue. Present when type is MISSING_FIELD or INVALID_FIELD. - example: customer.address.line1 - acceptedDocumentTypes: - type: array - items: - $ref: '#/components/schemas/DocumentType' - description: |- - Document types that would satisfy this requirement. The integrator can upload any one of the listed types. Present when type is MISSING_LEGAL_PRESENCE_DOCUMENT, MISSING_CONTROL_STRUCTURE_DOCUMENT, MISSING_OWNERSHIP_STRUCTURE_DOCUMENT, MISSING_PROOF_OF_ADDRESS_DOCUMENT, MISSING_IDENTITY_DOCUMENT, INVALID_DOCUMENT, or EXPIRED_DOCUMENT. + - PENDING + - EXPIRED + - PROCESSING + - COMPLETED + - FAILED + description: | + Status of an outgoing payment transaction. - | Error Type | Accepted Document Types | - |---|---| - | MISSING_LEGAL_PRESENCE_DOCUMENT | CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT | - | MISSING_CONTROL_STRUCTURE_DOCUMENT | DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT | - | MISSING_OWNERSHIP_STRUCTURE_DOCUMENT | SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT | - | MISSING_PROOF_OF_ADDRESS_DOCUMENT | UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN | - | MISSING_IDENTITY_DOCUMENT | PASSPORT, DRIVERS_LICENSE, NATIONAL_ID | - reason: - type: string - description: Human-readable description of the issue - example: Business address line 1 is required - Verification: + | Status | Description | + |--------|-------------| + | `PENDING` | Quote is pending confirmation | + | `EXPIRED` | Quote wasn't executed before expiry window | + | `PROCESSING` | Executing the quote after receiving funds | + | `COMPLETED` | Payout successfully reached the destination | + | `FAILED` | Something went wrong — accompanied by a `failureReason` | + Refund: type: object required: - - id - - customerId - - verificationStatus - - errors - - createdAt - properties: - id: - type: string - description: Unique identifier for this verification - example: Verification:019542f5-b3e7-1d02-0000-000000000001 - customerId: - type: string - description: The ID of the customer being verified - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - verificationStatus: - $ref: '#/components/schemas/VerificationStatus' - errors: - type: array - description: List of issues preventing verification from proceeding. Empty when verificationStatus is APPROVED or IN_PROGRESS. - items: - $ref: '#/components/schemas/VerificationError' - createdAt: + - reference + - initiatedAt + - status + properties: + reference: + type: string + description: The unique reference ID of the refund + example: UMA-Q12345-REFUND + initiatedAt: type: string format: date-time - description: When this verification was created - example: '2025-10-03T12:00:00Z' - updatedAt: + description: When the refund was initiated + example: '2025-08-15T14:30:00Z' + settledAt: type: string format: date-time - description: When this verification was last updated - example: '2025-10-03T12:00:00Z' - VerificationListResponse: - type: object - required: - - data - - hasMore - properties: - data: - type: array - description: List of verifications matching the filter criteria - items: - $ref: '#/components/schemas/Verification' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: + description: When the refund was settled + example: '2025-08-15T14:35:00Z' + status: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: - type: integer - description: Total number of results matching the criteria - VerificationRequest: + enum: + - PENDING + - COMPLETED + - FAILED + description: Current status of the refund + example: COMPLETED + reason: + type: string + enum: + - TRANSACTION_FAILED + - USER_CANCELLATION + - TIMEOUT + description: Reason for the refund + example: TRANSACTION_FAILED + OutgoingRateDetails: + description: 'Details about the rate and fees for an outgoing transaction or quote. Note: `counterpartyFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' type: object required: - - customerId + - counterpartyMultiplier + - counterpartyFixedFee + - gridApiMultiplier + - gridApiFixedFee + - gridApiVariableFeeRate + - gridApiVariableFeeAmount properties: - customerId: - type: string - description: The ID of the customer to verify - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - ExternalAccountReference: + counterpartyMultiplier: + type: number + format: double + description: The underlying multiplier from mSATs to the receiving currency as returned by the counterparty institution. + exclusiveMinimum: 0 + example: 1.08 + counterpartyFixedFee: + type: integer + format: int64 + description: The fixed fee charged by the counterparty institution to execute the quote in the smallest unit of the receiving currency (eg. cents). + minimum: 0 + example: 10 + gridApiMultiplier: + type: number + format: double + description: The underlying multiplier from the sending currency to mSATS, including variable fees. + exclusiveMinimum: 0 + example: 0.925 + gridApiFixedFee: + type: integer + format: int64 + description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). + minimum: 0 + example: 10 + gridApiVariableFeeRate: + type: number + format: double + description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the sending currency amount. + minimum: 0 + example: 0.003 + gridApiVariableFeeAmount: + type: number + format: int64 + description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). This is the sending amount times gridApiVariableFeeRate. + minimum: 0 + example: 30 + OutgoingTransactionFailureReason: + type: string + enum: + - QUOTE_EXPIRED + - QUOTE_EXECUTION_FAILED + - LIGHTNING_PAYMENT_FAILED + - FUNDING_AMOUNT_MISMATCH + - COUNTERPARTY_POST_TX_FAILED + description: Reason for failure of an outgoing transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. + OutgoingTransaction: + title: Outgoing Transaction + allOf: + - $ref: '#/components/schemas/Transaction' + - type: object + required: + - type + - sentAmount + - source + properties: + status: + $ref: '#/components/schemas/OutgoingTransactionStatus' + type: + type: string + enum: + - OUTGOING + source: + $ref: '#/components/schemas/TransactionSourceOneOf' + sentAmount: + $ref: '#/components/schemas/CurrencyAmount' + description: Amount sent in the sender's currency + receivedAmount: + $ref: '#/components/schemas/CurrencyAmount' + description: Amount to be received by recipient in the recipient's currency + exchangeRate: + type: number + description: Number of sending currency units per receiving currency unit. + exclusiveMinimum: 0 + example: 1.08 + fees: + type: integer + format: int64 + description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). + minimum: 0 + example: 10 + reconciliationInstructions: + $ref: '#/components/schemas/ReconciliationInstructions' + description: Reconciliation details for this transaction, including crypto transaction hash when available. + quoteId: + type: string + description: The ID of the quote that was used to trigger this payment + example: Quote:019542f5-b3e7-1d02-0000-000000000006 + paymentInstructions: + type: array + description: Payment instructions for executing the payment. + items: + $ref: '#/components/schemas/PaymentInstructions' + example: + - accountOrWalletInfo: + accountType: USD_ACCOUNT + paymentRails: + - ACH + - WIRE + accountNumber: '1234567890' + routingNumber: '021000021' + bankName: Chase Bank + reference: UMA-Q12345-REF + instructionsNotes: Include reference UMA-Q12345-REF in memo + - accountOrWalletInfo: + accountType: SPARK_WALLET + assetType: BTC + address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu + invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs + refund: + $ref: '#/components/schemas/Refund' + description: The refund if transaction was refunded. + rateDetails: + $ref: '#/components/schemas/OutgoingRateDetails' + description: Details about the rate and fees for the transaction. + failureReason: + $ref: '#/components/schemas/OutgoingTransactionFailureReason' + description: If the transaction failed, this field provides the reason for failure. + TransactionOneOf: + oneOf: + - $ref: '#/components/schemas/IncomingTransaction' + - $ref: '#/components/schemas/OutgoingTransaction' + discriminator: + propertyName: type + mapping: + INCOMING: '#/components/schemas/IncomingTransaction' + OUTGOING: '#/components/schemas/OutgoingTransaction' + ExternalAccountDestinationReference: type: object required: - accountId @@ -15845,208 +17314,141 @@ components: type: string description: Reference to an external account ID example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - InternalAccountReference: - type: object - required: - - accountId - properties: - accountId: - type: string - description: Reference to an internal account ID - example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - TransferInRequest: + paymentRail: + description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. + allOf: + - $ref: '#/components/schemas/PaymentRail' + TransferOutRequest: type: object required: - source - destination properties: source: - $ref: '#/components/schemas/ExternalAccountReference' - description: Source external account details - destination: $ref: '#/components/schemas/InternalAccountReference' - description: Destination internal account details + description: Source internal account details + destination: + $ref: '#/components/schemas/ExternalAccountDestinationReference' + description: Destination external account details amount: type: integer format: int64 description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) example: 12550 - TransactionStatus: - type: string - enum: - - CREATED - - PENDING - - PROCESSING - - COMPLETED - - REJECTED - - FAILED - - REFUNDED - - EXPIRED - description: | - Status of a payment transaction. - - | Status | Description | - |--------|-------------| - | `CREATED` | Initial lookup has been created | - | `PENDING` | Quote has been created | - | `PROCESSING` | Funding has been received and payment initiated | - | `COMPLETED` | Cross border payment has been received, converted and payment has been sent to the offramp network | - | `REJECTED` | Receiving institution or wallet rejected payment, payment has been refunded | - | `FAILED` | An error occurred during payment | - | `REFUNDED` | Payment was unable to complete and refunded | - | `EXPIRED` | Quote has expired | - TransactionDestinationType: - type: string - enum: - - ACCOUNT - - UMA_ADDRESS - description: Type of transaction destination - example: ACCOUNT - BaseTransactionDestination: + CurrencyPreference: + type: object + required: + - currency + - estimatedExchangeRate + - min + - max + properties: + currency: + $ref: '#/components/schemas/Currency' + estimatedExchangeRate: + type: number + description: An estimated exchange rate from the sender's currency to this currency. This is not a locked rate and is subject to change when calling the quotes endpoint. + exclusiveMinimum: 0 + example: 1.08 + min: + type: integer + format: int64 + description: The minimum amount that can be received in this currency. + exclusiveMinimum: 0 + example: 1 + max: + type: integer + format: int64 + description: The maximum amount that can be received in this currency. + exclusiveMinimum: 0 + example: 1000000 + ReceiverLookupResponse: type: object required: - - destinationType + - supportedCurrencies + - lookupId properties: - destinationType: - $ref: '#/components/schemas/TransactionDestinationType' - currency: + supportedCurrencies: + type: array + description: List of currencies supported by the receiving account + items: + $ref: '#/components/schemas/CurrencyPreference' + requiredPayerDataFields: + type: array + description: Fields required by the receiving institution about the payer before payment can be completed + items: + $ref: '#/components/schemas/CounterpartyFieldDefinition' + lookupId: type: string - description: Currency code for the destination - example: EUR - AccountTransactionDestination: - title: Account Destination - allOf: - - $ref: '#/components/schemas/BaseTransactionDestination' - - type: object - required: - - accountId - - destinationType - properties: - destinationType: - type: string - enum: - - ACCOUNT - accountId: - type: string - description: Destination account identifier - example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - description: Destination account details - UmaAddressTransactionDestination: - title: UMA Address Destination + description: Unique identifier for the lookup. Needed in the subsequent create quote request. + example: Lookup:019542f5-b3e7-1d02-0000-000000000009 + ReceiverUmaLookupResponse: allOf: - - $ref: '#/components/schemas/BaseTransactionDestination' + - $ref: '#/components/schemas/ReceiverLookupResponse' - type: object required: - - umaAddress - - destinationType + - receiverUmaAddress properties: - destinationType: - type: string - enum: - - UMA_ADDRESS - umaAddress: + receiverUmaAddress: type: string - description: UMA address of the recipient - example: $receiver@uma.domain.com - description: UMA address destination details - TransactionDestinationOneOf: - oneOf: - - $ref: '#/components/schemas/AccountTransactionDestination' - - $ref: '#/components/schemas/UmaAddressTransactionDestination' - discriminator: - propertyName: destinationType - mapping: - ACCOUNT: '#/components/schemas/AccountTransactionDestination' - UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionDestination' - CounterpartyInformation: - type: object - description: Additional information about the counterparty, if available and relevant to the transaction and platform. - additionalProperties: true - example: - FULL_NAME: John Sender - BIRTH_DATE: '1985-06-15' - NATIONALITY: DE - Transaction: + description: The UMA address that was looked up + example: $receiver@uma.domain + Error412: type: object required: - - id + - message - status - - type - - destination - - customerId - - platformCustomerId + - code properties: - id: - type: string - description: Unique identifier for the transaction - example: Transaction:019542f5-b3e7-1d02-0000-000000000004 status: - $ref: '#/components/schemas/TransactionStatus' - type: - $ref: '#/components/schemas/TransactionType' - destination: - $ref: '#/components/schemas/TransactionDestinationOneOf' - customerId: - type: string - description: System ID of the customer (sender for outgoing, recipient for incoming) - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: - type: string - description: Platform-specific ID of the customer (sender for outgoing, recipient for incoming) - example: 18d3e5f7b4a9c2 - settledAt: - type: string - format: date-time - description: When the payment was or will be settled - example: '2025-08-15T14:30:00Z' - createdAt: - type: string - format: date-time - description: When the transaction was created - example: '2025-08-15T14:25:18Z' - updatedAt: - type: string - format: date-time - description: When the transaction was last updated - example: '2025-08-15T14:30:00Z' - receiptDeliveryConfirmedAt: - type: string - format: date-time - description: The time at which the platform confirmed delivery of the receipt to their customer. - example: '2025-08-15T14:31:00Z' - agentId: + type: integer + enum: + - 412 + description: HTTP status code + code: type: string - description: If this transaction was initiated by an agent, the system-generated ID of that agent. Absent for platform-initiated transactions. - example: Agent:019542f5-b3e7-1d02-0000-000000000042 - description: + description: | + | Error Code | Description | + |------------|-------------| + | UNSUPPORTED_UMA_VERSION | Counterparty doesn't support the Grid UMA version | + enum: + - UNSUPPORTED_UMA_VERSION + message: type: string - description: Optional memo or description for the payment - example: 'Payment for invoice #1234' - counterpartyInformation: - $ref: '#/components/schemas/CounterpartyInformation' - TransactionSourceType: + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + ReceiverExternalAccountLookupResponse: + allOf: + - $ref: '#/components/schemas/ReceiverLookupResponse' + - type: object + required: + - accountId + properties: + accountId: + type: string + description: The external account ID that was looked up + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + QuoteSourceType: type: string enum: - ACCOUNT - - UMA_ADDRESS - REALTIME_FUNDING - description: Type of transaction source + description: Type of quote funding source example: ACCOUNT - BaseTransactionSource: + BaseQuoteSource: type: object required: - sourceType properties: sourceType: - $ref: '#/components/schemas/TransactionSourceType' - currency: - type: string - description: Currency code for the source - example: USD - AccountTransactionSource: - title: Account Source + $ref: '#/components/schemas/QuoteSourceType' + AccountQuoteSource: + title: Account allOf: - - $ref: '#/components/schemas/BaseTransactionSource' + - $ref: '#/components/schemas/BaseQuoteSource' - type: object required: - accountId @@ -16060,461 +17462,596 @@ components: type: string description: Source account identifier example: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + customerId: + type: string + description: Required when funding from an FBO account to identify the customer on whose behalf the transaction is being initiated. Otherwise, will default to the customerId of the account owner. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 description: Source account details - UmaAddressTransactionSource: - title: UMA Address Source + RealtimeFundingQuoteSource: + title: Real-time Funding allOf: - - $ref: '#/components/schemas/BaseTransactionSource' + - $ref: '#/components/schemas/BaseQuoteSource' - type: object required: - - umaAddress + - currency - sourceType properties: sourceType: type: string enum: - - UMA_ADDRESS - umaAddress: + - REALTIME_FUNDING + customerId: type: string - description: UMA address of the sender - example: $sender@uma.domain.com - description: UMA address source details - RealtimeFundingTransactionSource: - title: External Funding Source + description: Source customer ID. If this transaction is being initiated on behalf of a customer, this is required. If customerId is not provided, the quote will be created on behalf of the platform itself. + example: Customer:019542f5-b3e7-1d02-0000-000000000009 + currency: + type: string + description: Currency code for the funding source. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. + example: USD + cryptoNetwork: + type: string + description: 'The crypto network to use for the funding source. Required when `currency` is a stablecoin (e.g. USDC, USDT). Specifies which network the customer will deposit on, so the correct deposit address can be generated. Example values: `SOLANA`, `ETHEREUM`, `BASE`, `POLYGON`, `SPARK`, `LIGHTNING`, `BITCOIN`.' + example: SOLANA + description: Fund the quote using a real-time funding source (RTP, SEPA Instant, Spark, Stables, etc.). This will require manual just-in-time funding using `paymentInstructions` in the response. Because quotes expire quickly, this option is only valid for instant payment methods. Do not try to fund a quote with a non-instant payment method (ACH, etc.). + QuoteSourceOneOf: + oneOf: + - $ref: '#/components/schemas/AccountQuoteSource' + - $ref: '#/components/schemas/RealtimeFundingQuoteSource' + discriminator: + propertyName: sourceType + mapping: + ACCOUNT: '#/components/schemas/AccountQuoteSource' + REALTIME_FUNDING: '#/components/schemas/RealtimeFundingQuoteSource' + DestinationType: + type: string + enum: + - ACCOUNT + - UMA_ADDRESS + description: Type of payment destination + example: ACCOUNT + BaseDestination: + type: object + required: + - destinationType + properties: + destinationType: + $ref: '#/components/schemas/DestinationType' + AccountDestination: + title: Account allOf: - - $ref: '#/components/schemas/BaseTransactionSource' + - $ref: '#/components/schemas/BaseDestination' - type: object required: - - currency - - sourceType + - accountId + - destinationType properties: - sourceType: + destinationType: type: string enum: - - REALTIME_FUNDING - customerId: - type: string - description: The customer on whose behalf the transaction was initiated. - example: Customer:019542f5-b3e7-1d02-0000-000000000009 - currency: - type: string - description: Currency code for the funding source - example: USDC - accountHolderName: - type: string - description: The name of the originator (sender) of the payment. - example: John Sender - accountIdentifier: - type: string - description: The originator's account number or IBAN. May be masked or partial depending on the rail. - example: '****6789' - bankName: - type: string - description: The name of the originating bank. - example: Chase Bank - bankIdentifier: + - ACCOUNT + accountId: type: string - description: The identifier of the originating bank, such as a routing number, BIC, or SWIFT code. - example: '021000021' + description: Destination account identifier + example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 paymentRail: - description: The payment rail the funds arrived on. allOf: - $ref: '#/components/schemas/PaymentRail' - remittanceInformation: + - description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. + description: Destination account details + UmaAddressDestination: + title: UMA Address + allOf: + - $ref: '#/components/schemas/BaseDestination' + - type: object + required: + - umaAddress + - destinationType + properties: + destinationType: type: string - description: 'Free-form information about the payment provided by the originator. The source field depends on the payment rail: the Addenda record for ACH, the OBI / beneficiary information for wires, and the remittanceInformation field for RTP and FedNow.' - example: '12345' - endToEndId: + enum: + - UMA_ADDRESS + umaAddress: type: string - description: The originator's own end-to-end reference for the payment. - example: E2E-9f2c6b6f - traceNumber: + description: UMA address of the recipient + example: $receiver@uma.domain.com + currency: type: string - description: Rail-level tracking identifier for the payment, such as an ACH trace number or a wire IMAD/OMAD, useful for reconciliation. - example: '021000020123456' - description: Transaction was funded using an external funding source. All originator fields are optional and populated on a best-effort basis depending on what the funding source provides. - TransactionSourceOneOf: + description: Currency code for the destination. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. + example: EUR + description: UMA address destination details + QuoteDestinationOneOf: oneOf: - - $ref: '#/components/schemas/AccountTransactionSource' - - $ref: '#/components/schemas/UmaAddressTransactionSource' - - $ref: '#/components/schemas/RealtimeFundingTransactionSource' + - $ref: '#/components/schemas/AccountDestination' + - $ref: '#/components/schemas/UmaAddressDestination' discriminator: - propertyName: sourceType + propertyName: destinationType mapping: - ACCOUNT: '#/components/schemas/AccountTransactionSource' - UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionSource' - REALTIME_FUNDING: '#/components/schemas/RealtimeFundingTransactionSource' - ReconciliationInstructions: + ACCOUNT: '#/components/schemas/AccountDestination' + UMA_ADDRESS: '#/components/schemas/UmaAddressDestination' + Quote: + type: object + required: + - id + - status + - expiresAt + - createdAt + - source + - destination + - sendingCurrency + - receivingCurrency + - totalSendingAmount + - totalReceivingAmount + - exchangeRate + - feesIncluded + - transactionId + properties: + id: + type: string + description: Unique identifier for this quote + example: Quote:019542f5-b3e7-1d02-0000-000000000006 + status: + type: string + enum: + - PENDING + - PROCESSING + - COMPLETED + - FAILED + - EXPIRED + description: Current status of the quote + example: PENDING + createdAt: + type: string + format: date-time + description: When this quote was created + example: '2025-10-03T12:00:00Z' + expiresAt: + type: string + format: date-time + description: 'Absolute UTC timestamp when the rate locked in this quote becomes invalid and the quote can no longer be executed. The window depends on the rail and corridor: instant rails (Lightning, Spark, USDC on Solana/Base/Polygon, RTP, SEPA Instant) typically expire in 1–5 minutes; corridors with longer settlement guarantees may have longer windows. Always rely on this timestamp rather than assuming a fixed window.' + example: '2025-10-03T12:05:00Z' + source: + $ref: '#/components/schemas/QuoteSourceOneOf' + destination: + $ref: '#/components/schemas/QuoteDestinationOneOf' + sendingCurrency: + $ref: '#/components/schemas/Currency' + description: Currency for the sending amount + receivingCurrency: + $ref: '#/components/schemas/Currency' + description: Currency for the receiving amount + totalSendingAmount: + type: integer + format: int64 + description: The total amount that will be sent in the smallest unit of the sending currency (eg. cents). + exclusiveMinimum: 0 + example: 123010 + totalReceivingAmount: + type: integer + format: int64 + description: The total amount that will be received in the smallest unit of the receiving currency (eg. cents). + exclusiveMinimum: 0 + example: 1000 + exchangeRate: + type: number + description: Number of sending currency units per receiving currency unit. + exclusiveMinimum: 0 + feesIncluded: + type: integer + format: int64 + description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' + minimum: 0 + example: 10 + paymentInstructions: + type: array + description: Payment instructions for executing the payment. This is not required when using an internal account source. + items: + $ref: '#/components/schemas/PaymentInstructions' + example: + - accountOrWalletInfo: + accountType: USD_ACCOUNT + paymentRails: + - ACH + - WIRE + accountNumber: '1234567890' + routingNumber: '021000021' + bankName: Chase Bank + reference: UMA-Q12345-REF + instructionsNotes: Include reference UMA-Q12345-REF in memo + - accountOrWalletInfo: + accountType: SPARK_WALLET + assetType: BTC + address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu + invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs + transactionId: + type: string + description: The ID of the transaction created from this quote. + example: Transaction:019542f5-b3e7-1d02-0000-000000000005 + counterpartyInformation: + $ref: '#/components/schemas/CounterpartyInformation' + description: Additional information about the counterparty, if available and required by the platform in their configuration. + rateDetails: + $ref: '#/components/schemas/OutgoingRateDetails' + description: Details about the rate and fees for the transaction. + QuoteLockSide: + type: string + enum: + - SENDING + - RECEIVING + description: The side of the quote which should be locked and specified in the `lockedCurrencyAmount`. For example, if I want to send exactly $5 MXN from my wallet, I would set this to "sending", and the `lockedCurrencyAmount` to 500 (in cents). If I want the receiver to receive exactly $10 USD, I would set this to "receiving" and the `lockedCurrencyAmount` to 10000 (in cents). + PurposeOfPayment: + type: string + description: The purpose of the payment. This may be required when sending to certain geographies (e.g. India). + enum: + - GIFT + - SELF + - GOODS_OR_SERVICES + - EDUCATION + - HEALTH_OR_MEDICAL + - REAL_ESTATE_PURCHASE + - TAX_PAYMENT + - LOAN_PAYMENT + - UTILITY_BILL + - DONATION + - TRAVEL + - OTHER + QuoteRequest: + type: object + required: + - source + - destination + - lockedCurrencySide + - lockedCurrencyAmount + properties: + lookupId: + type: string + description: |- + Lookup ID from a previous receiver lookup request. If provided, this can make the quote creation more efficient by reusing cached lookup data. + NOTE: This is required for UMA destinations due to counterparty institution requirements. See `senderCustomerInfo` for more information. + example: Lookup:019542f5-b3e7-1d02-0000-000000000009 + source: + $ref: '#/components/schemas/QuoteSourceOneOf' + destination: + $ref: '#/components/schemas/QuoteDestinationOneOf' + lockedCurrencySide: + $ref: '#/components/schemas/QuoteLockSide' + lockedCurrencyAmount: + type: integer + format: int64 + description: The amount to send/receive in the smallest unit of the locked currency (eg. cents). See `lockedCurrencySide` for more information. + exclusiveMinimum: 0 + maximum: 9000000000000000 + example: 1000 + immediatelyExecute: + type: boolean + description: |- + Whether to immediately execute the quote after creation. If true, the quote will be executed and the transaction will be created at the current exchange rate. It should only be used if you don't want to lock and view rate details before executing the quote. If you are executing a pre-existing quote, use the `/quotes/{quoteId}/execute` endpoint instead. This is false by default. + This can only be used for quotes with a `source` which is either an internal account, or has direct pull functionality (e.g. ACH pull with an external account). + Not supported when the `source` is an internal account of type `EMBEDDED_WALLET`: those transfers require a `Grid-Wallet-Signature` over the `payloadToSign` returned in the quote response, which is not available in a combined create-and-execute call. Create the quote first with `immediatelyExecute: false` and then call `POST /quotes/{quoteId}/execute` with the `Grid-Wallet-Signature` stamp header. + example: false + description: + type: string + description: Optional description/memo for the transfer + example: 'Invoice #1234 payment' + purposeOfPayment: + $ref: '#/components/schemas/PurposeOfPayment' + senderCustomerInfo: + type: object + additionalProperties: true + description: | + Key-value pairs of additional information about the sender which was requested by the destination. This is relevant when the destination requires more sender info than was provided during customer creation. + Any fields specified in `requiredPayerDataFields` from the response of the `/receiver/uma/{receiverUmaAddress}` (lookupUma) or `/receiver/external-account/{accountId}` (lookupExternalAccount) endpoints MUST be provided here if they were requested. If the destination did not request any additional information, this field can be omitted. + example: + FULL_NAME: Jane Receiver + NATIONALITY: FR + TransactionListResponse: type: object - minProperties: 1 + required: + - data + - hasMore properties: - reference: + data: + type: array + description: List of transactions matching the criteria + items: + $ref: '#/components/schemas/TransactionOneOf' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: type: string - description: Unique reference code to include with the payment to match it with the correct incoming transaction, when available. - example: UMA-Q12345-REF - transactionHash: + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of transactions matching the criteria (excluding pagination) + ConfirmReceiptDeliveryRequest: + type: object + properties: + receiptDeliveryConfirmedAt: type: string - description: Transaction hash for the crypto transfer that delivered funds to the transaction destination, when available. - example: '0x9f2c6b6f4b6c8f2a8d9e0b1c2d3e4f5061728394a5b6c7d8e9f00112233445566' - IncomingRateDetails: - description: 'Details about the rate and fees for an incoming transaction. Note: `gridApiFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' + format: date-time + description: The time at which the platform delivered the transaction receipt to their customer. If omitted, the current server time is used. + example: '2025-08-15T14:31:00Z' + ApprovePaymentRequest: + type: object + properties: + receiverCustomerInfo: + type: object + additionalProperties: true + description: Information about the recipient, provided by the platform if requested in the original webhook via `requestedReceiverCustomerInfoFields`. + RejectPaymentRequest: + type: object + properties: + reason: + type: string + description: Optional reason for rejecting the payment. This is just for debugging purposes or can be used for a platform's own purposes. + example: RESTRICTED_JURISDICTION + EstimateCryptoWithdrawalFeeRequest: type: object required: - - gridApiMultiplier - - gridApiFixedFee - - gridApiVariableFeeRate - - gridApiVariableFeeAmount + - internalAccountId + - currency + - cryptoNetwork + - amount + - destinationAddress properties: - gridApiMultiplier: - type: number - format: double - description: The underlying multiplier from the mSATS to the receiving currency, including variable fees. - exclusiveMinimum: 0 - example: 0.925 - gridApiFixedFee: + internalAccountId: + type: string + description: The ID of the crypto internal account to withdraw from. + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + currency: + type: string + description: The currency code of the asset to withdraw (e.g. USDC). + example: USDC + cryptoNetwork: + type: string + description: 'The blockchain network for the withdrawal. Example values: SOLANA, ETHEREUM, BASE, POLYGON, SPARK, LIGHTNING, BITCOIN.' + example: SOLANA + amount: type: integer - format: int64 - description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). - minimum: 0 - example: 10 - gridApiVariableFeeRate: - type: number - format: double - description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the receiving currency amount. - minimum: 0 - example: 0.003 - gridApiVariableFeeAmount: - type: number - format: int64 - description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). This is the receiving amount times gridApiVariableFeeRate. - minimum: 0 - example: 30 - IncomingTransactionFailureReason: - type: string - enum: - - LNURLP_FAILED - - PAY_REQUEST_FAILED - - PAYMENT_APPROVAL_WEBHOOK_ERROR - - PAYMENT_APPROVAL_TIMED_OUT - - OFFRAMP_FAILED - - MISSING_MANDATORY_PAYEE_DATA - - QUOTE_EXPIRED - - QUOTE_EXECUTION_FAILED - description: Reason for failure of an incoming transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. - IncomingTransaction: - title: Incoming Transaction + description: The amount to withdraw in the smallest unit of the currency. + example: 1000000 + destinationAddress: + type: string + description: The blockchain address to withdraw funds to. + example: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU + EstimateCryptoWithdrawalFeeResponse: + type: object + required: + - networkFee + - networkFeeAsset + - applicationFee + - totalFee + - netAmount + properties: + networkFee: + type: integer + description: The estimated network (gas) fee in the smallest unit of the network fee asset (e.g. lamports for SOL). This is provided for informational purposes to show the raw on-chain cost. Note that this value is denominated in networkFeeAsset, not in the withdrawal currency — it cannot be directly added to applicationFee or compared to totalFee. + example: 5000 + networkFeeAsset: + type: string + description: The asset used to pay the network fee (e.g. SOL for Solana transactions). + example: SOL + applicationFee: + type: integer + description: The application fee charged by the platform in the smallest unit of the withdrawal currency. Zero if no application fee applies. + example: 0 + totalFee: + type: integer + description: The total cost of the withdrawal in the smallest unit of the withdrawal currency. This equals the network fee converted to the withdrawal currency at current rates plus the application fee. This is the amount deducted from the withdrawal in addition to netAmount. + example: 5000 + netAmount: + type: integer + description: The net amount the recipient will receive after fees, in the smallest unit of the withdrawal currency. + example: 995000 + TestWebhookResponse: + type: object + required: + - response_status + properties: + url: + type: string + format: uri + description: URL where the webhook was sent + example: https://api.mycompany.com/webhooks/uma + response_status: + type: integer + description: The HTTP status code returned by the webhook endpoint + example: 200 + response_body: + type: string + description: The raw body content returned by the webhook endpoint in response to the request + BulkCustomerImportJobAccepted: + type: object + required: + - jobId + - status + properties: + jobId: + type: string + description: Unique identifier for the bulk import job + example: Job:019542f5-b3e7-1d02-0000-000000000006 + status: + type: string + enum: + - PENDING + - PROCESSING + GridError: + type: object + title: GridError + properties: + code: + type: string + description: Error code + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + BulkCustomerImportErrorEntry: allOf: - - $ref: '#/components/schemas/Transaction' + - $ref: '#/components/schemas/GridError' - type: object + description: Error information for a failed bulk import entry required: - - type - - receivedAmount + - correlationId properties: - type: + correlationId: type: string - enum: - - INCOMING - source: - $ref: '#/components/schemas/TransactionSourceOneOf' - receivedAmount: - $ref: '#/components/schemas/CurrencyAmount' - description: Amount received in the recipient's currency - fees: - type: integer - format: int64 - description: The total fees available from the receive quote in the smallest unit of the receiving currency (eg. cents). - minimum: 0 - example: 10 - reconciliationInstructions: - $ref: '#/components/schemas/ReconciliationInstructions' - description: Included for all transactions except those with "CREATED" status - rateDetails: - $ref: '#/components/schemas/IncomingRateDetails' - description: Details about the rate and fees for the transaction. - failureReason: - $ref: '#/components/schemas/IncomingTransactionFailureReason' - description: If the transaction failed, this field provides the reason for failure. - OutgoingTransactionStatus: - type: string - enum: - - PENDING - - EXPIRED - - PROCESSING - - COMPLETED - - FAILED - description: | - Status of an outgoing payment transaction. - - | Status | Description | - |--------|-------------| - | `PENDING` | Quote is pending confirmation | - | `EXPIRED` | Quote wasn't executed before expiry window | - | `PROCESSING` | Executing the quote after receiving funds | - | `COMPLETED` | Payout successfully reached the destination | - | `FAILED` | Something went wrong — accompanied by a `failureReason` | - Refund: + description: Platform customer ID or row number for the failed entry + example: biz456 + BulkCustomerImportJob: type: object required: - - reference - - initiatedAt + - id - status + - progress properties: - reference: - type: string - description: The unique reference ID of the refund - example: UMA-Q12345-REFUND - initiatedAt: - type: string - format: date-time - description: When the refund was initiated - example: '2025-08-15T14:30:00Z' - settledAt: + id: type: string - format: date-time - description: When the refund was settled - example: '2025-08-15T14:35:00Z' + description: Unique identifier for the bulk import job + example: Job:019542f5-b3e7-1d02-0000-000000000006 status: type: string enum: - PENDING + - PROCESSING - COMPLETED - FAILED - description: Current status of the refund - example: COMPLETED - reason: - type: string - enum: - - TRANSACTION_FAILED - - USER_CANCELLATION - - TIMEOUT - description: Reason for the refund - example: TRANSACTION_FAILED - OutgoingRateDetails: - description: 'Details about the rate and fees for an outgoing transaction or quote. Note: `counterpartyFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' - type: object - required: - - counterpartyMultiplier - - counterpartyFixedFee - - gridApiMultiplier - - gridApiFixedFee - - gridApiVariableFeeRate - - gridApiVariableFeeAmount - properties: - counterpartyMultiplier: - type: number - format: double - description: The underlying multiplier from mSATs to the receiving currency as returned by the counterparty institution. - exclusiveMinimum: 0 - example: 1.08 - counterpartyFixedFee: - type: integer - format: int64 - description: The fixed fee charged by the counterparty institution to execute the quote in the smallest unit of the receiving currency (eg. cents). - minimum: 0 - example: 10 - gridApiMultiplier: - type: number - format: double - description: The underlying multiplier from the sending currency to mSATS, including variable fees. - exclusiveMinimum: 0 - example: 0.925 - gridApiFixedFee: - type: integer - format: int64 - description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). - minimum: 0 - example: 10 - gridApiVariableFeeRate: - type: number - format: double - description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the sending currency amount. - minimum: 0 - example: 0.003 - gridApiVariableFeeAmount: - type: number - format: int64 - description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). This is the sending amount times gridApiVariableFeeRate. - minimum: 0 - example: 30 - OutgoingTransactionFailureReason: - type: string - enum: - - QUOTE_EXPIRED - - QUOTE_EXECUTION_FAILED - - LIGHTNING_PAYMENT_FAILED - - FUNDING_AMOUNT_MISMATCH - - COUNTERPARTY_POST_TX_FAILED - description: Reason for failure of an outgoing transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. - OutgoingTransaction: - title: Outgoing Transaction - allOf: - - $ref: '#/components/schemas/Transaction' - - type: object + description: Current status of the job + example: PROCESSING + progress: + type: object required: - - type - - sentAmount - - source + - total + - processed + - successful + - failed properties: - status: - $ref: '#/components/schemas/OutgoingTransactionStatus' - type: - type: string - enum: - - OUTGOING - source: - $ref: '#/components/schemas/TransactionSourceOneOf' - sentAmount: - $ref: '#/components/schemas/CurrencyAmount' - description: Amount sent in the sender's currency - receivedAmount: - $ref: '#/components/schemas/CurrencyAmount' - description: Amount to be received by recipient in the recipient's currency - exchangeRate: - type: number - description: Number of sending currency units per receiving currency unit. - exclusiveMinimum: 0 - example: 1.08 - fees: + total: type: integer - format: int64 - description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). - minimum: 0 - example: 10 - reconciliationInstructions: - $ref: '#/components/schemas/ReconciliationInstructions' - description: Reconciliation details for this transaction, including crypto transaction hash when available. - quoteId: - type: string - description: The ID of the quote that was used to trigger this payment - example: Quote:019542f5-b3e7-1d02-0000-000000000006 - paymentInstructions: - type: array - description: Payment instructions for executing the payment. - items: - $ref: '#/components/schemas/PaymentInstructions' - example: - - accountOrWalletInfo: - accountType: USD_ACCOUNT - paymentRails: - - ACH - - WIRE - accountNumber: '1234567890' - routingNumber: '021000021' - bankName: Chase Bank - reference: UMA-Q12345-REF - instructionsNotes: Include reference UMA-Q12345-REF in memo - - accountOrWalletInfo: - accountType: SPARK_WALLET - assetType: BTC - address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu - invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs - refund: - $ref: '#/components/schemas/Refund' - description: The refund if transaction was refunded. - rateDetails: - $ref: '#/components/schemas/OutgoingRateDetails' - description: Details about the rate and fees for the transaction. - failureReason: - $ref: '#/components/schemas/OutgoingTransactionFailureReason' - description: If the transaction failed, this field provides the reason for failure. - TransactionOneOf: - oneOf: - - $ref: '#/components/schemas/IncomingTransaction' - - $ref: '#/components/schemas/OutgoingTransaction' - discriminator: - propertyName: type - mapping: - INCOMING: '#/components/schemas/IncomingTransaction' - OUTGOING: '#/components/schemas/OutgoingTransaction' - ExternalAccountDestinationReference: - type: object - required: - - accountId - properties: - accountId: + description: Total number of customers to process + example: 5000 + processed: + type: integer + description: Number of customers processed so far + example: 2500 + successful: + type: integer + description: Number of customers successfully created + example: 2450 + failed: + type: integer + description: Number of customers that failed to create + example: 50 + errors: + type: array + description: Detailed error information for failed entries + items: + $ref: '#/components/schemas/BulkCustomerImportErrorEntry' + completedAt: type: string - description: Reference to an external account ID - example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - paymentRail: - description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. - allOf: - - $ref: '#/components/schemas/PaymentRail' - TransferOutRequest: + format: date-time + description: Timestamp when the job completed (only present for COMPLETED or FAILED status) + example: '2025-08-15T14:32:00Z' + UmaInvitationCreateRequest: type: object required: - - source - - destination + - inviterUma properties: - source: - $ref: '#/components/schemas/InternalAccountReference' - description: Source internal account details - destination: - $ref: '#/components/schemas/ExternalAccountDestinationReference' - description: Destination external account details - amount: + inviterUma: + type: string + description: The UMA address of the customer creating the invitation + example: $inviter@uma.domain + firstName: + type: string + description: First name of the invitee to show as part of the invite + example: Alice + amountToSend: + description: | + An amount to send (in the smallest unit of the customer's currency) to the invitee when the invitation is claimed. + This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of + the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter + platform either does not send the payment or the payment fails, the invitee will not receive this amount. This + field is primarily used for display purposes on the claiming side of the invitation. type: integer format: int64 - description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) example: 12550 - CurrencyPreference: + expiresAt: + type: string + format: date-time + description: When the invitation expires (if at all) + example: '2025-09-01T14:30:00Z' + UmaInvitation: type: object required: - - currency - - estimatedExchangeRate - - min - - max - properties: - currency: - $ref: '#/components/schemas/Currency' - estimatedExchangeRate: - type: number - description: An estimated exchange rate from the sender's currency to this currency. This is not a locked rate and is subject to change when calling the quotes endpoint. - exclusiveMinimum: 0 - example: 1.08 - min: - type: integer - format: int64 - description: The minimum amount that can be received in this currency. - exclusiveMinimum: 0 - example: 1 - max: - type: integer - format: int64 - description: The maximum amount that can be received in this currency. - exclusiveMinimum: 0 - example: 1000000 - ReceiverLookupResponse: + - code + - createdAt + - inviterUma + - status + - url + properties: + code: + type: string + description: The unique code of the invitation + example: 019542f5 + createdAt: + type: string + format: date-time + description: When the invitation was created + example: '2025-09-01T14:30:00Z' + claimedAt: + type: string + format: date-time + description: When the invitation was claimed if it has been claimed + example: '2025-09-01T14:30:00Z' + url: + type: string + description: The URL where this invitation can be claimed. + example: https://uma.me/i/019542f5 + expiresAt: + type: string + format: date-time + description: When the invitation expires (if at all) + example: '2025-09-01T14:30:00Z' + inviterUma: + type: string + description: The UMA address of the inviter + example: $inviter@uma.domain + inviteeUma: + type: string + description: The UMA address of the invitee + example: $invitee@uma.domain + status: + type: string + enum: + - PENDING + - CLAIMED + - EXPIRED + - CANCELLED + description: The status of the invitation + example: PENDING + firstName: + type: string + description: The inviter's first name. Will be displayed when the recipient clicks the invite link + example: Jane + amountToSend: + $ref: '#/components/schemas/CurrencyAmount' + description: |- + The amount to send to the invitee when the invitation is claimed. This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter platform either does not send the payment or the payment fails, the invitee will not receive this amount. This field is primarily used for display purposes on the claiming side of the invitation. + This field is useful for "send-by-link" style customer flows where an inviter can send a payment simply by sharing a link without knowing the receiver's UMA address. Note that these sends can only be sender-locked, meaning that the sender will not know ahead of time how much the receiver will receive in the receiving currency. + UmaInvitationClaimRequest: type: object required: - - supportedCurrencies - - lookupId + - inviteeUma properties: - supportedCurrencies: - type: array - description: List of currencies supported by the receiving account - items: - $ref: '#/components/schemas/CurrencyPreference' - requiredPayerDataFields: - type: array - description: Fields required by the receiving institution about the payer before payment can be completed - items: - $ref: '#/components/schemas/CounterpartyFieldDefinition' - lookupId: + inviteeUma: type: string - description: Unique identifier for the lookup. Needed in the subsequent create quote request. - example: Lookup:019542f5-b3e7-1d02-0000-000000000009 - ReceiverUmaLookupResponse: - allOf: - - $ref: '#/components/schemas/ReceiverLookupResponse' - - type: object - required: - - receiverUmaAddress - properties: - receiverUmaAddress: - type: string - description: The UMA address that was looked up - example: $receiver@uma.domain - Error412: + description: The UMA address of the customer claiming the invitation + example: $invitee@uma.domain + Error403: type: object required: - message @@ -16524,348 +18061,197 @@ components: status: type: integer enum: - - 412 + - 403 description: HTTP status code code: type: string description: | | Error Code | Description | |------------|-------------| - | UNSUPPORTED_UMA_VERSION | Counterparty doesn't support the Grid UMA version | + | FORBIDDEN | Insufficient permissions | + | USER_NOT_READY | Customer exists but is not ready for operation | + | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | + | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | enum: - - UNSUPPORTED_UMA_VERSION - message: - type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true - ReceiverExternalAccountLookupResponse: - allOf: - - $ref: '#/components/schemas/ReceiverLookupResponse' - - type: object - required: - - accountId - properties: - accountId: - type: string - description: The external account ID that was looked up - example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - QuoteSourceType: - type: string - enum: - - ACCOUNT - - REALTIME_FUNDING - description: Type of quote funding source - example: ACCOUNT - BaseQuoteSource: - type: object - required: - - sourceType - properties: - sourceType: - $ref: '#/components/schemas/QuoteSourceType' - AccountQuoteSource: - title: Account - allOf: - - $ref: '#/components/schemas/BaseQuoteSource' - - type: object - required: - - accountId - - sourceType - properties: - sourceType: - type: string - enum: - - ACCOUNT - accountId: - type: string - description: Source account identifier - example: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - customerId: - type: string - description: Required when funding from an FBO account to identify the customer on whose behalf the transaction is being initiated. Otherwise, will default to the customerId of the account owner. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - description: Source account details - RealtimeFundingQuoteSource: - title: Real-time Funding - allOf: - - $ref: '#/components/schemas/BaseQuoteSource' - - type: object - required: - - currency - - sourceType - properties: - sourceType: - type: string - enum: - - REALTIME_FUNDING - customerId: - type: string - description: Source customer ID. If this transaction is being initiated on behalf of a customer, this is required. If customerId is not provided, the quote will be created on behalf of the platform itself. - example: Customer:019542f5-b3e7-1d02-0000-000000000009 - currency: - type: string - description: Currency code for the funding source. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. - example: USD - cryptoNetwork: - type: string - description: 'The crypto network to use for the funding source. Required when `currency` is a stablecoin (e.g. USDC, USDT). Specifies which network the customer will deposit on, so the correct deposit address can be generated. Example values: `SOLANA`, `ETHEREUM`, `BASE`, `POLYGON`, `SPARK`, `LIGHTNING`, `BITCOIN`.' - example: SOLANA - description: Fund the quote using a real-time funding source (RTP, SEPA Instant, Spark, Stables, etc.). This will require manual just-in-time funding using `paymentInstructions` in the response. Because quotes expire quickly, this option is only valid for instant payment methods. Do not try to fund a quote with a non-instant payment method (ACH, etc.). - QuoteSourceOneOf: - oneOf: - - $ref: '#/components/schemas/AccountQuoteSource' - - $ref: '#/components/schemas/RealtimeFundingQuoteSource' - discriminator: - propertyName: sourceType - mapping: - ACCOUNT: '#/components/schemas/AccountQuoteSource' - REALTIME_FUNDING: '#/components/schemas/RealtimeFundingQuoteSource' - DestinationType: - type: string - enum: - - ACCOUNT - - UMA_ADDRESS - description: Type of payment destination - example: ACCOUNT - BaseDestination: - type: object - required: - - destinationType - properties: - destinationType: - $ref: '#/components/schemas/DestinationType' - AccountDestination: - title: Account - allOf: - - $ref: '#/components/schemas/BaseDestination' - - type: object - required: - - accountId - - destinationType - properties: - destinationType: - type: string - enum: - - ACCOUNT - accountId: - type: string - description: Destination account identifier - example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - paymentRail: - allOf: - - $ref: '#/components/schemas/PaymentRail' - - description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. - description: Destination account details - UmaAddressDestination: - title: UMA Address - allOf: - - $ref: '#/components/schemas/BaseDestination' - - type: object - required: - - umaAddress - - destinationType - properties: - destinationType: - type: string - enum: - - UMA_ADDRESS - umaAddress: - type: string - description: UMA address of the recipient - example: $receiver@uma.domain.com - currency: - type: string - description: Currency code for the destination. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. - example: EUR - description: UMA address destination details - QuoteDestinationOneOf: - oneOf: - - $ref: '#/components/schemas/AccountDestination' - - $ref: '#/components/schemas/UmaAddressDestination' - discriminator: - propertyName: destinationType - mapping: - ACCOUNT: '#/components/schemas/AccountDestination' - UMA_ADDRESS: '#/components/schemas/UmaAddressDestination' - Quote: + - FORBIDDEN + - USER_NOT_READY + - COUNTERPARTY_NOT_ALLOWED + - VELOCITY_LIMIT_EXCEEDED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + SandboxSendRequest: type: object required: - - id - - status - - expiresAt - - createdAt - - source - - destination - - sendingCurrency - - receivingCurrency - - totalSendingAmount - - totalReceivingAmount - - exchangeRate - - feesIncluded - - transactionId + - quoteId + - currencyCode properties: - id: + quoteId: type: string - description: Unique identifier for this quote + description: The unique identifier of the quote example: Quote:019542f5-b3e7-1d02-0000-000000000006 - status: - type: string - enum: - - PENDING - - PROCESSING - - COMPLETED - - FAILED - - EXPIRED - description: Current status of the quote - example: PENDING - createdAt: - type: string - format: date-time - description: When this quote was created - example: '2025-10-03T12:00:00Z' - expiresAt: + currencyCode: type: string - format: date-time - description: 'Absolute UTC timestamp when the rate locked in this quote becomes invalid and the quote can no longer be executed. The window depends on the rail and corridor: instant rails (Lightning, Spark, USDC on Solana/Base/Polygon, RTP, SEPA Instant) typically expire in 1–5 minutes; corridors with longer settlement guarantees may have longer windows. Always rely on this timestamp rather than assuming a fixed window.' - example: '2025-10-03T12:05:00Z' - source: - $ref: '#/components/schemas/QuoteSourceOneOf' - destination: - $ref: '#/components/schemas/QuoteDestinationOneOf' - sendingCurrency: - $ref: '#/components/schemas/Currency' - description: Currency for the sending amount - receivingCurrency: - $ref: '#/components/schemas/Currency' - description: Currency for the receiving amount - totalSendingAmount: + description: Currency code for the funds to be sent + example: USD + currencyAmount: type: integer format: int64 - description: The total amount that will be sent in the smallest unit of the sending currency (eg. cents). + description: The amount to send in the smallest unit of the currency (eg. cents). If not provided, the amount will be derived from the quote. exclusiveMinimum: 0 - example: 123010 - totalReceivingAmount: + example: 1000 + SandboxUmaReceiveRequest: + type: object + required: + - senderUmaAddress + - receivingCurrencyCode + - receivingCurrencyAmount + properties: + senderUmaAddress: + type: string + description: UMA address of the sender from the sandbox + example: $success.usd@sandbox.grid.uma.money + receiverUmaAddress: + type: string + description: UMA address of the receiver (optional if customerId is provided) + example: $receiver@uma.domain + customerId: + type: string + description: System ID of the receiver (optional if receiverUmaAddress is provided) + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + receivingCurrencyCode: + type: string + description: The currency code for the receiving amount + example: USD + receivingCurrencyAmount: type: integer format: int64 - description: The total amount that will be received in the smallest unit of the receiving currency (eg. cents). + description: The amount to be received in the smallest unit of the currency (eg. cents) exclusiveMinimum: 0 example: 1000 - exchangeRate: - type: number - description: Number of sending currency units per receiving currency unit. - exclusiveMinimum: 0 - feesIncluded: + SandboxFundRequest: + type: object + required: + - amount + properties: + amount: type: integer format: int64 - description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' - minimum: 0 - example: 10 - paymentInstructions: + description: Amount to add in the smallest unit of the account's currency (e.g., cents for USD/EUR, satoshis for BTC) + exclusiveMinimum: 0 + maximum: 100000000000 + example: 100000 + UmaProvider: + type: object + properties: + name: + type: string + description: Name of the UMA Provider + example: Lightspark Group + supportedRegions: type: array - description: Payment instructions for executing the payment. This is not required when using an internal account source. items: - $ref: '#/components/schemas/PaymentInstructions' + type: string + description: Region(s) this UMA Provider operates in example: - - accountOrWalletInfo: - accountType: USD_ACCOUNT - paymentRails: - - ACH - - WIRE - accountNumber: '1234567890' - routingNumber: '021000021' - bankName: Chase Bank - reference: UMA-Q12345-REF - instructionsNotes: Include reference UMA-Q12345-REF in memo - - accountOrWalletInfo: - accountType: SPARK_WALLET - assetType: BTC - address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu - invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs - transactionId: + - US + domain: type: string - description: The ID of the transaction created from this quote. - example: Transaction:019542f5-b3e7-1d02-0000-000000000005 - counterpartyInformation: - $ref: '#/components/schemas/CounterpartyInformation' - description: Additional information about the counterparty, if available and required by the platform in their configuration. - rateDetails: - $ref: '#/components/schemas/OutgoingRateDetails' - description: Details about the rate and fees for the transaction. - QuoteLockSide: - type: string - enum: - - SENDING - - RECEIVING - description: The side of the quote which should be locked and specified in the `lockedCurrencyAmount`. For example, if I want to send exactly $5 MXN from my wallet, I would set this to "sending", and the `lockedCurrencyAmount` to 500 (in cents). If I want the receiver to receive exactly $10 USD, I would set this to "receiving" and the `lockedCurrencyAmount` to 10000 (in cents). - PurposeOfPayment: + description: Domain this VASP uses for UMA addresses + example: uma.me + logoUrl: + type: string + description: Logo URL for the VASP + format: uri + example: https://uma.me/logo.png + supportedCurrencies: + type: array + items: + $ref: '#/components/schemas/Currency' + description: List of currencies supported by this UMA Provider + example: + - code: USD + name: United States Dollar + symbol: $ + decimals: 2 + lei: + type: string + description: Legal Entity Identifier for the UMA Provider + example: 5493001KJTIIGC8Y1R12 + allowListStatus: + type: boolean + description: Whether this UMA Provider is on your allow list + example: true + UmaProviderListResponse: + type: object + properties: + data: + description: List of available UMA Providers using Grid + type: array + items: + $ref: '#/components/schemas/UmaProvider' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of transactions matching the criteria (excluding pagination) + Permission: type: string - description: The purpose of the payment. This may be required when sending to certain geographies (e.g. India). enum: - - GIFT - - SELF - - GOODS_OR_SERVICES - - EDUCATION - - HEALTH_OR_MEDICAL - - REAL_ESTATE_PURCHASE - - TAX_PAYMENT - - LOAN_PAYMENT - - UTILITY_BILL - - DONATION - - TRAVEL - - OTHER - QuoteRequest: + - VIEW + - TRANSACT + - MANAGE + description: 'Permission of an API token that determines what actions the token can perform: VIEW: Can view all data, including platform config, customers and transactions TRANSACT: Can send payments MANAGE: Can manage platform config, api tokens and customers' + ApiToken: type: object required: - - source - - destination - - lockedCurrencySide - - lockedCurrencyAmount + - id + - name + - permissions + - clientId + - createdAt + - updatedAt properties: - lookupId: - type: string - description: |- - Lookup ID from a previous receiver lookup request. If provided, this can make the quote creation more efficient by reusing cached lookup data. - NOTE: This is required for UMA destinations due to counterparty institution requirements. See `senderCustomerInfo` for more information. - example: Lookup:019542f5-b3e7-1d02-0000-000000000009 - source: - $ref: '#/components/schemas/QuoteSourceOneOf' - destination: - $ref: '#/components/schemas/QuoteDestinationOneOf' - lockedCurrencySide: - $ref: '#/components/schemas/QuoteLockSide' - lockedCurrencyAmount: - type: integer - format: int64 - description: The amount to send/receive in the smallest unit of the locked currency (eg. cents). See `lockedCurrencySide` for more information. - exclusiveMinimum: 0 - maximum: 9000000000000000 - example: 1000 - immediatelyExecute: - type: boolean - description: |- - Whether to immediately execute the quote after creation. If true, the quote will be executed and the transaction will be created at the current exchange rate. It should only be used if you don't want to lock and view rate details before executing the quote. If you are executing a pre-existing quote, use the `/quotes/{quoteId}/execute` endpoint instead. This is false by default. - This can only be used for quotes with a `source` which is either an internal account, or has direct pull functionality (e.g. ACH pull with an external account). - Not supported when the `source` is an internal account of type `EMBEDDED_WALLET`: those transfers require a `Grid-Wallet-Signature` over the `payloadToSign` returned in the quote response, which is not available in a combined create-and-execute call. Create the quote first with `immediatelyExecute: false` and then call `POST /quotes/{quoteId}/execute` with the `Grid-Wallet-Signature` stamp header. - example: false - description: + id: type: string - description: Optional description/memo for the transfer - example: 'Invoice #1234 payment' - purposeOfPayment: - $ref: '#/components/schemas/PurposeOfPayment' - senderCustomerInfo: - type: object - additionalProperties: true - description: | - Key-value pairs of additional information about the sender which was requested by the destination. This is relevant when the destination requires more sender info than was provided during customer creation. - Any fields specified in `requiredPayerDataFields` from the response of the `/receiver/uma/{receiverUmaAddress}` (lookupUma) or `/receiver/external-account/{accountId}` (lookupExternalAccount) endpoints MUST be provided here if they were requested. If the destination did not request any additional information, this field can be omitted. - example: - FULL_NAME: Jane Receiver - NATIONALITY: FR - TransactionListResponse: + description: System-generated unique identifier + example: Token:019542f5-b3e7-1d02-0000-000000000001 + name: + type: string + description: Name of the token + example: Sandbox read-only token + permissions: + type: array + description: A list of permissions granted to the token + items: + $ref: '#/components/schemas/Permission' + clientId: + type: string + description: An opaque identifier that should be used as a client_id (or username) in the HTTP Basic Authentication scheme when issuing http requests to Grid. + example: 01947d2284054f890000e63bca4810df + clientSecret: + type: string + description: The secret that should be used to authenticate against Grid API. This secret is not stored and will never be available again after creation. Platform must keep this secret secure as it grants access to the account. + example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + createdAt: + type: string + format: date-time + description: Creation timestamp + example: '2025-07-21T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + example: '2025-07-21T17:32:28Z' + TokenListResponse: type: object required: - data @@ -16873,9 +18259,9 @@ components: properties: data: type: array - description: List of transactions matching the criteria + description: List of tokens matching the filter criteria items: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/ApiToken' hasMore: type: boolean description: Indicates if more results are available beyond this page @@ -16884,295 +18270,411 @@ components: description: Cursor to retrieve the next page of results (only present if hasMore is true) totalCount: type: integer - description: Total number of transactions matching the criteria (excluding pagination) - ConfirmReceiptDeliveryRequest: + description: Total number of tokens matching the criteria (excluding pagination) + ApiTokenCreateRequest: type: object + required: + - name + - permissions properties: - receiptDeliveryConfirmedAt: + name: type: string - format: date-time - description: The time at which the platform delivered the transaction receipt to their customer. If omitted, the current server time is used. - example: '2025-08-15T14:31:00Z' - ApprovePaymentRequest: + description: Name of the token to help identify it + example: Sandbox read-only + permissions: + type: array + description: A list of permissions to grant to the token + items: + $ref: '#/components/schemas/Permission' + InternalAccountUpdateRequest: + title: Internal Account Update Request + description: Partial request body for `PATCH /internal-accounts/{id}`. At least one update field must be provided. On step 1 of the signed-retry flow Grid binds the submitted update fields into `payloadToSign`; on step 2 the client echoes the same fields back and Grid applies the update to the internal account. type: object properties: - receiverCustomerInfo: - type: object - additionalProperties: true - description: Information about the recipient, provided by the platform if requested in the original webhook via `requestedReceiverCustomerInfoFields`. - RejectPaymentRequest: + privateEnabled: + type: boolean + description: Whether wallet privacy should be enabled for the Embedded Wallet. + example: true + InternalAccountExportRequest: + title: Internal Account Export Request + description: Request body for `POST /internal-accounts/{id}/export`. The `clientPublicKey` is required on both steps of the signed-retry flow. On step 1 Grid binds it into `payloadToSign` so the subsequent stamp in `Grid-Wallet-Signature` commits to the target pubkey; on step 2 the client echoes the same `clientPublicKey` back and Grid uses it to encrypt the wallet credentials returned in the `200` response. type: object + required: + - clientPublicKey properties: - reason: + clientPublicKey: type: string - description: Optional reason for rejecting the payment. This is just for debugging purposes or can be used for a platform's own purposes. - example: RESTRICTED_JURISDICTION - EstimateCryptoWithdrawalFeeRequest: + description: Fresh P-256 public key, uncompressed SEC1 hex — 130 hex chars where the first two are `04` (the uncompressed-point indicator). Generate a new keypair for each export and discard the private key after decrypting the response. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + InternalAccountExportResponse: + title: Internal Account Export Response type: object required: - - internalAccountId - - currency - - cryptoNetwork - - amount - - destinationAddress + - id + - encryptedWalletCredentials properties: - internalAccountId: + id: type: string - description: The ID of the crypto internal account to withdraw from. - example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - currency: + description: The id of the internal account that was exported. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + encryptedWalletCredentials: type: string - description: The currency code of the asset to withdraw (e.g. USDC). - example: USDC - cryptoNetwork: + description: |- + Encrypted wallet mnemonic, sealed to the `clientPublicKey` from the request body using HPKE: DHKEM(P-256, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM. Decrypt with the matching private key, then manage the mnemonic securely because it is the master key of the self-custodial Embedded Wallet. + The value is a JSON string of the form `{"version": "v1.0.0", "data": "", "dataSignature": "", "enclaveQuorumPublic": ""}`. `data` hex-decodes to JSON `{"encappedPublic": "", "ciphertext": "", "organizationId": ""}`, where `encappedPublic` is the uncompressed SEC1 ephemeral public key. `dataSignature` is an ECDSA-P256-SHA256 signature over the `data` bytes produced by the issuer key in `enclaveQuorumPublic`; verify before decrypting. + In sandbox, `dataSignature` and `enclaveQuorumPublic` are empty strings. Clients should bypass attestation verification when calling against sandbox. + example: '{"version":"v1.0.0","data":"7b22656e6361707065645075626c6963223a22303433...","dataSignature":"3045022100c9...","enclaveQuorumPublic":"04a1b2c3..."}' + AuthMethodType: + type: string + enum: + - OAUTH + - EMAIL_OTP + - PASSKEY + description: |- + The type of authentication credential. + - `OAUTH`: OpenID Connect (OIDC) token issued by an identity provider such as Google or Apple. + - `EMAIL_OTP`: A one-time password delivered to the user's email address. + - `PASSKEY`: A WebAuthn passkey bound to the user's device. + AuthMethod: + type: object + required: + - id + - accountId + - type + - nickname + - createdAt + - updatedAt + properties: + id: type: string - description: 'The blockchain network for the withdrawal. Example values: SOLANA, ETHEREUM, BASE, POLYGON, SPARK, LIGHTNING, BITCOIN.' - example: SOLANA - amount: - type: integer - description: The amount to withdraw in the smallest unit of the currency. - example: 1000000 - destinationAddress: + description: System-generated unique identifier for the authentication credential. + example: AuthMethod:019542f5-b3e7-1d02-0000-000000000001 + accountId: type: string - description: The blockchain address to withdraw funds to. - example: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU - EstimateCryptoWithdrawalFeeResponse: + description: Identifier of the internal account that this credential authenticates. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + type: + $ref: '#/components/schemas/AuthMethodType' + credentialId: + type: string + description: Base64url-encoded WebAuthn credential identifier for this passkey. Present only for `PASSKEY` authentication credentials. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. + example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew + nickname: + type: string + description: Human-readable identifier for this credential. For EMAIL_OTP credentials this is the email address; for OAUTH credentials it is typically the email claim from the OIDC token; for PASSKEY credentials it is the validated nickname provided at registration time. + example: example@lightspark.com + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-04-08T15:30:01Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-04-08T15:35:00Z' + AuthCredentialListResponse: type: object required: - - networkFee - - networkFeeAsset - - applicationFee - - totalFee - - netAmount + - data properties: - networkFee: - type: integer - description: The estimated network (gas) fee in the smallest unit of the network fee asset (e.g. lamports for SOL). This is provided for informational purposes to show the raw on-chain cost. Note that this value is denominated in networkFeeAsset, not in the withdrawal currency — it cannot be directly added to applicationFee or compared to totalFee. - example: 5000 - networkFeeAsset: + data: + type: array + description: List of authentication credentials registered on the internal account. + items: + $ref: '#/components/schemas/AuthMethod' + AuthCredentialCreateRequest: + type: object + required: + - type + - accountId + properties: + type: + $ref: '#/components/schemas/AuthMethodType' + accountId: type: string - description: The asset used to pay the network fee (e.g. SOL for Solana transactions). - example: SOL - applicationFee: - type: integer - description: The application fee charged by the platform in the smallest unit of the withdrawal currency. Zero if no application fee applies. - example: 0 - totalFee: - type: integer - description: The total cost of the withdrawal in the smallest unit of the withdrawal currency. This equals the network fee converted to the withdrawal currency at current rates plus the application fee. This is the amount deducted from the withdrawal in addition to netAmount. - example: 5000 - netAmount: - type: integer - description: The net amount the recipient will receive after fees, in the smallest unit of the withdrawal currency. - example: 995000 - TestWebhookResponse: + description: Identifier of the internal account that this credential will authenticate. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + EmailOtpCredentialCreateRequestFields: type: object required: - - response_status + - type + properties: + type: + type: string + enum: + - EMAIL_OTP + description: Discriminator value identifying this as an email OTP credential. + EmailOtpCredentialCreateRequest: + title: Email OTP Credential Create Request + allOf: + - $ref: '#/components/schemas/AuthCredentialCreateRequest' + - $ref: '#/components/schemas/EmailOtpCredentialCreateRequestFields' + OauthCredentialCreateRequestFields: + type: object + required: + - type + - oidcToken + properties: + type: + type: string + enum: + - OAUTH + description: Discriminator value identifying this as an OAuth credential. + oidcToken: + type: string + description: OIDC ID token issued by the identity provider (e.g. Google, Apple). The token's `iss`, `aud`, and `sub` claims define the OAuth identity registered to this credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and `iat` less than 60 seconds before the request timestamp, but the signature segment may be a dummy value. + example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q + OauthCredentialCreateRequest: + title: OAuth Credential Create Request + allOf: + - $ref: '#/components/schemas/AuthCredentialCreateRequest' + - $ref: '#/components/schemas/OauthCredentialCreateRequestFields' + PasskeyAttestation: + title: Passkey Attestation + type: object + required: + - credentialId + - clientDataJson + - attestationObject properties: - url: + credentialId: type: string - format: uri - description: URL where the webhook was sent - example: https://api.mycompany.com/webhooks/uma - response_status: - type: integer - description: The HTTP status code returned by the webhook endpoint - example: 200 - response_body: + description: Base64url-encoded credential identifier produced by the authenticator at registration time. Typically the base64url of `PublicKeyCredential.rawId`. + example: AdKXJEch1aV5Wo7bj7qLHskVY4OoNaj9qu8TPdJ7kSAgUeRxWNngXlcNIGt4gexZGKVGcqZpqqWordXb_he1izY + clientDataJson: type: string - description: The raw body content returned by the webhook endpoint in response to the request - BulkCustomerImportJobAccepted: + description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.create()` call. Corresponds to `AuthenticatorAttestationResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.create"`.' + example: eyJjaGFsbGVuZ2UiOiJBcktRaTJ5QVlIUGxnbkpORkJsbmVJd2NoUWRXWEJPVHJkQi1BbU1VQjIxTHgiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0 + attestationObject: + type: string + description: Base64url-encoded CBOR attestation object produced by the authenticator during registration. Corresponds to `AuthenticatorAttestationResponse.attestationObject`. + example: o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFPdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQHSlyRHIdWleVqO24-6ix7JFWODqDWo_arvEz3Se5EgIFHkcVjZ4F5XDSBreIHsWRilRnKmaaqlqK3V2_4XtYs2pQECAyYgASFYID5PQTZQQg6haZFQWFzqfAOyQ_ENsMH8xxQ4GRiNPsqrIlggU8IVUOV8qpgk_Jh-OTaLuZL52KdX1fTht07X4DiQPow + transports: + type: array + items: + type: string + enum: + - usb + - nfc + - ble + - internal + - hybrid + description: Optional. WebAuthn transports as returned by `AuthenticatorAttestationResponse.getTransports()`. Values follow the W3C `AuthenticatorTransport` enum — pass the raw values through to Grid; provider-specific translation is handled server-side. Some authenticators return an empty array; omit the field or send `[]` in that case. + example: + - internal + - hybrid + PasskeyCredentialCreateRequestFields: type: object required: - - jobId - - status + - type + - nickname + - challenge + - attestation properties: - jobId: - type: string - description: Unique identifier for the bulk import job - example: Job:019542f5-b3e7-1d02-0000-000000000006 - status: + type: type: string enum: - - PENDING - - PROCESSING - GridError: - type: object - title: GridError - properties: - code: + - PASSKEY + description: Discriminator value identifying this as a passkey credential. + nickname: type: string - description: Error code - message: + description: 'Human-readable identifier for the passkey, chosen by the user at registration time (e.g. "iPhone Face-ID", "YubiKey 5C"). Leading and trailing whitespace is ignored. Must be 1-100 characters and may contain Unicode letters, numbers, spaces, and the following separators: period, underscore, hyphen, apostrophe, and parentheses. Shown back on AuthMethod responses and in credential listings.' + example: iPhone Face-ID + challenge: type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true - BulkCustomerImportErrorEntry: + description: Base64url-encoded WebAuthn challenge issued by the platform backend and passed to the client before `navigator.credentials.create()`. Grid verifies it matches the challenge embedded in the attestation's `clientDataJson`, binding the attestation to this registration. Must be single-use. + example: ArkQi2yAYHPlgnJNFBlneIwchQdWXBOTrdB-AmMUB21Lx + attestation: + $ref: '#/components/schemas/PasskeyAttestation' + PasskeyCredentialCreateRequest: + title: Passkey Credential Create Request allOf: - - $ref: '#/components/schemas/GridError' + - $ref: '#/components/schemas/AuthCredentialCreateRequest' + - $ref: '#/components/schemas/PasskeyCredentialCreateRequestFields' + AuthCredentialCreateRequestOneOf: + oneOf: + - $ref: '#/components/schemas/EmailOtpCredentialCreateRequest' + - $ref: '#/components/schemas/OauthCredentialCreateRequest' + - $ref: '#/components/schemas/PasskeyCredentialCreateRequest' + discriminator: + propertyName: type + mapping: + EMAIL_OTP: '#/components/schemas/EmailOtpCredentialCreateRequest' + OAUTH: '#/components/schemas/OauthCredentialCreateRequest' + PASSKEY: '#/components/schemas/PasskeyCredentialCreateRequest' + AuthMethodResponse: + title: Auth Method Response + description: |- + Strict wrapper around `AuthMethod`. Used directly as the registration response on `POST /auth/credentials` (all three credential types) and inside `AuthCredentialResponseOneOf` for the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/challenge`. The only difference from `AuthMethod` is `unevaluatedProperties: false`, which disambiguates the oneOf against `PasskeyAuthChallenge` — without the strictness, an `AuthMethod` with extra fields would ambiguously match both branches. + + For `EMAIL_OTP` credentials, responses that initiate or reissue an OTP challenge carry `otpEncryptionTargetBundle` so the client can HPKE-encrypt the OTP code in the subsequent `POST /auth/credentials/{id}/verify` call without the plaintext code ever transiting the server. First-time EMAIL_OTP wallet bootstrap registration can omit it; call `POST /auth/credentials/{id}/challenge` if it is absent. + allOf: + - $ref: '#/components/schemas/AuthMethod' - type: object - description: Error information for a failed bulk import entry - required: - - correlationId properties: - correlationId: + otpEncryptionTargetBundle: type: string - description: Platform customer ID or row number for the failed entry - example: biz456 - BulkCustomerImportJob: + description: HPKE encryption target bundle for a freshly initiated OTP challenge. Returned only on `EMAIL_OTP` responses that initiate or reissue an OTP challenge, such as `POST /auth/credentials/{id}/challenge` and the add-EMAIL_OTP signed-retry response. It is omitted from first-time EMAIL_OTP wallet bootstrap registration; call `POST /auth/credentials/{id}/challenge` for the new credential if it is absent. The client generates an ephemeral P-256 keypair (the Target Encryption Key, or TEK) and uses this bundle as the recipient when HPKE-encrypting `{otp_code, public_key}`; the encrypted payload is submitted as `encryptedOtpBundle` on `POST /auth/credentials/{id}/verify`. The bundle is one-time-use per OTP issuance — re-issue via `POST /auth/credentials/{id}/challenge` to obtain a fresh bundle. The matching TEK private key must remain on the client and is used to sign the `verificationToken` returned on the subsequent signed-retry. Treat the bundle as opaque and pass it to your HPKE library; the Global Accounts client-keys guide shows how. + example: '{"version":"v1.0.0","data":"7b227461726765745075626c6963...","dataSignature":"30450221...","enclaveQuorumPublic":"04a1b2c3..."}' + unevaluatedProperties: false + AuthSignedRequestChallenge: + title: Authentication Signed Request Challenge + description: |- + 202 response returned from Embedded Wallet Auth endpoints that require a signed retry — `POST /auth/credentials` (adding an additional credential), `DELETE /auth/credentials/{id}` (revoking a credential), `DELETE /auth/sessions/{id}` (revoking a session), and the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify` (the secure OTP login flow, where the client submits an `encryptedOtpBundle` and receives a `verificationToken` to sign for the second-leg session issuance). Carries the signing fields from `SignedRequestChallenge` plus the `type` of the authentication credential involved (being added, revoked, that issued the session being revoked, or being authenticated). The client already knows the target resource id from the request path / body it just sent, so nothing beyond `type` is echoed in the response. + + The keypair used to compute the stamp depends on the operation. For credential / session management retries, sign with the session API keypair of an existing verified credential on the same internal account. For the `EMAIL_OTP` verify retry, sign with the ephemeral Target Encryption Key (TEK) the client generated for this login — its public key is the one carried inside the `encryptedOtpBundle` and bound into the `verificationToken`, and it becomes the client's session API key on successful completion. + allOf: + - $ref: '#/components/schemas/SignedRequestChallenge' + - type: object + required: + - type + properties: + type: + $ref: '#/components/schemas/AuthMethodType' + description: 'Credential type relevant to this challenge: the credential type being added (`POST /auth/credentials`), revoked (`DELETE /auth/credentials/{id}`), or authenticated (`EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify`). For session revocation, this is the type of credential that issued the session (`DELETE /auth/sessions/{id}`).' + AuthCredentialVerifyRequest: type: object required: - - id - - status - - progress + - type properties: - id: - type: string - description: Unique identifier for the bulk import job - example: Job:019542f5-b3e7-1d02-0000-000000000006 - status: - type: string - enum: - - PENDING - - PROCESSING - - COMPLETED - - FAILED - description: Current status of the job - example: PROCESSING - progress: - type: object - required: - - total - - processed - - successful - - failed - properties: - total: - type: integer - description: Total number of customers to process - example: 5000 - processed: - type: integer - description: Number of customers processed so far - example: 2500 - successful: - type: integer - description: Number of customers successfully created - example: 2450 - failed: - type: integer - description: Number of customers that failed to create - example: 50 - errors: - type: array - description: Detailed error information for failed entries - items: - $ref: '#/components/schemas/BulkCustomerImportErrorEntry' - completedAt: - type: string - format: date-time - description: Timestamp when the job completed (only present for COMPLETED or FAILED status) - example: '2025-08-15T14:32:00Z' - UmaInvitationCreateRequest: + type: + $ref: '#/components/schemas/AuthMethodType' + EmailOtpCredentialVerifyRequestFields: type: object required: - - inviterUma + - type + - encryptedOtpBundle + description: Verify an email-OTP credential via the secure two-leg flow. The client HPKE-encrypts the OTP code (together with its public key) under the `otpEncryptionTargetBundle` returned from registration when present, or from `POST /auth/credentials/{id}/challenge` when registration omitted it or the OTP must be reissued, submits the result here, and receives `202` with a `payloadToSign` carrying a `verificationToken` bound to the client's public key. The client signs that token with the matching private key and retries this request with `Grid-Wallet-Signature` + `Request-Id` headers to obtain the session. Plaintext OTP codes are never sent over the wire. properties: - inviterUma: - type: string - description: The UMA address of the customer creating the invitation - example: $inviter@uma.domain - firstName: + type: type: string - description: First name of the invitee to show as part of the invite - example: Alice - amountToSend: - description: | - An amount to send (in the smallest unit of the customer's currency) to the invitee when the invitation is claimed. - This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of - the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter - platform either does not send the payment or the payment fails, the invitee will not receive this amount. This - field is primarily used for display purposes on the claiming side of the invitation. - type: integer - format: int64 - example: 12550 - expiresAt: + enum: + - EMAIL_OTP + description: Discriminator value identifying this as an email OTP verification. + encryptedOtpBundle: type: string - format: date-time - description: When the invitation expires (if at all) - example: '2025-09-01T14:30:00Z' - UmaInvitation: + description: |- + HPKE-sealed OTP attempt — the OTP code never reaches Grid in plaintext. The client generates a fresh ephemeral P-256 key pair (the session signing key pair it keeps once login completes), HPKE-encrypts `{otp_code, public_key}` (the code the user entered plus that key pair's public key) to the key in `otpEncryptionTargetBundle`, and submits the encrypted result here. The value is the `{encappedPublic, ciphertext}` JSON an HPKE library produces; the Global Accounts client-keys guide has a worked example. + + On success the response is `202` with a `payloadToSign` carrying a `verificationToken` bound to the public key sealed in this bundle. Sign that token with the matching private key, then retry this request with the full stamp in `Grid-Wallet-Signature` and the `requestId` in `Request-Id` to complete the flow and receive the session. The client keeps that private key as the session signing key, and its public key becomes the session API key. + example: '{"encappedPublic":"044f631a2d890bc6668d997ee184e190650d06adf970987568ec641214a00403b73effe1ef406c60a5cde8508a4484567ddb8056fbd493bee614cd727aef02a838","ciphertext":"1fa1023390a56539aa48cbb380aa28f544ed5cc04861566bb806e25ba026f14660eaf4140a05b388dd012eaa899759a6a92576cdca8c1b7d12e147bd96cc26ed9f74886794155d8ac5cf0fdc"}' + EmailOtpCredentialVerifyRequest: + title: Email OTP Credential Verify Request + allOf: + - $ref: '#/components/schemas/AuthCredentialVerifyRequest' + - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequestFields' + OauthCredentialVerifyRequestFields: type: object required: - - code - - createdAt - - inviterUma - - status - - url + - type + - oidcToken + - clientPublicKey properties: - code: - type: string - description: The unique code of the invitation - example: 019542f5 - createdAt: - type: string - format: date-time - description: When the invitation was created - example: '2025-09-01T14:30:00Z' - claimedAt: + type: type: string - format: date-time - description: When the invitation was claimed if it has been claimed - example: '2025-09-01T14:30:00Z' - url: + enum: + - OAUTH + description: Discriminator value identifying this as an OAuth verification. + oidcToken: type: string - description: The URL where this invitation can be claimed. - example: https://uma.me/i/019542f5 - expiresAt: + description: OIDC ID token issued by the identity provider. For reauthentication after a prior session expired, supply a fresh token — the token's `iat` claim must be less than 60 seconds before the request timestamp. The token identity (`iss`, `aud`, and `sub`) must match the registered OAuth credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and a `nonce` equal to `sha256(clientPublicKey)`, but the signature segment may be a dummy value. + example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q + clientPublicKey: type: string - format: date-time - description: When the invitation expires (if at all) - example: '2025-09-01T14:30:00Z' - inviterUma: + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (0x04 prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid encrypts the session signing key returned in the response to this public key. The key is ephemeral and one-time-use per verification request. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + OauthCredentialVerifyRequest: + title: OAuth Credential Verify Request + allOf: + - $ref: '#/components/schemas/AuthCredentialVerifyRequest' + - $ref: '#/components/schemas/OauthCredentialVerifyRequestFields' + PasskeyAssertion: + title: Passkey Assertion + type: object + description: WebAuthn assertion returned by `navigator.credentials.get()`. In sandbox, Grid validates the assertion against the registered passkey credential so the client-side flow can match production. In production, Turnkey validates the WebAuthn assertion. + required: + - credentialId + - clientDataJson + - authenticatorData + - signature + properties: + credentialId: type: string - description: The UMA address of the inviter - example: $inviter@uma.domain - inviteeUma: + description: Base64url-encoded credential identifier returned during the WebAuthn assertion. Corresponds to `PublicKeyCredential.rawId`. + example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew + clientDataJson: type: string - description: The UMA address of the invitee - example: $invitee@uma.domain - status: + description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.get()` call. Corresponds to `AuthenticatorAssertionResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.get"`.' + example: eyJjaGFsbGVuZ2UiOiJkRzkwWVd4c2VWVnVhWEYxWlZaaGJIVmxSWFpsY25sVWFXMWwiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uZ2V0In0 + authenticatorData: type: string - enum: - - PENDING - - CLAIMED - - EXPIRED - - CANCELLED - description: The status of the invitation - example: PENDING - firstName: + description: Base64url-encoded authenticator data returned by the authenticator during the assertion. Corresponds to `AuthenticatorAssertionResponse.authenticatorData`. + example: PdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KABAAAAkA + signature: type: string - description: The inviter's first name. Will be displayed when the recipient clicks the invite link - example: Jane - amountToSend: - $ref: '#/components/schemas/CurrencyAmount' - description: |- - The amount to send to the invitee when the invitation is claimed. This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter platform either does not send the payment or the payment fails, the invitee will not receive this amount. This field is primarily used for display purposes on the claiming side of the invitation. - This field is useful for "send-by-link" style customer flows where an inviter can send a payment simply by sharing a link without knowing the receiver's UMA address. Note that these sends can only be sender-locked, meaning that the sender will not know ahead of time how much the receiver will receive in the receiving currency. - UmaInvitationClaimRequest: + description: Base64url-encoded signature produced by the authenticator over `authenticatorData || SHA-256(clientDataJSON)`. Corresponds to `AuthenticatorAssertionResponse.signature`. The signature byte format is determined by the credential's public-key algorithm — DER-encoded ECDSA for ES256 (P-256, typical for passkeys), PKCS#1 v1.5 for RS256, or a raw 64-byte signature for EdDSA. + example: MEUCIQDYXBOpCWSWq2Ll4558GJKD2RoWg958lvJSB_GdeokxogIgWuEVQ7ee6AswQY0OsuQ6y8Ks6jhd45bDx92wjXKs900 + userHandle: + type: string + description: Base64url-encoded user handle returned by the authenticator. Corresponds to `AuthenticatorAssertionResponse.userHandle`. Populated (and required by the WebAuthn spec) for discoverable credentials — resident keys used in the "Sign in with passkey" autofill flow — and typically present for passkey registrations. Omit this field entirely for non-discoverable credentials specified via `allowCredentials` where the authenticator returns no user handle. + example: dXNlci1oYW5kbGUtZXhhbXBsZQ + PasskeyCredentialVerifyRequestFields: type: object required: - - inviteeUma + - type + - assertion properties: - inviteeUma: + type: type: string - description: The UMA address of the customer claiming the invitation - example: $invitee@uma.domain - Error403: + enum: + - PASSKEY + description: Discriminator value identifying this as a passkey verification. + assertion: + $ref: '#/components/schemas/PasskeyAssertion' + PasskeyCredentialVerifyRequest: + title: Passkey Credential Verify Request + allOf: + - $ref: '#/components/schemas/AuthCredentialVerifyRequest' + - $ref: '#/components/schemas/PasskeyCredentialVerifyRequestFields' + AuthCredentialVerifyRequestOneOf: + oneOf: + - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequest' + - $ref: '#/components/schemas/OauthCredentialVerifyRequest' + - $ref: '#/components/schemas/PasskeyCredentialVerifyRequest' + discriminator: + propertyName: type + mapping: + EMAIL_OTP: '#/components/schemas/EmailOtpCredentialVerifyRequest' + OAUTH: '#/components/schemas/OauthCredentialVerifyRequest' + PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' + AuthSession: + title: Authentication Session + description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/refresh` (on mid-session refresh). Only session-issuing responses include `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. + allOf: + - $ref: '#/components/schemas/AuthMethod' + - type: object + required: + - id + - expiresAt + properties: + id: + type: string + description: System-generated unique identifier for the session. Pass this value to `DELETE /auth/sessions/{id}` to revoke the session before `expiresAt`. Overrides the `id` inherited from `AuthMethod` so this response identifies the session rather than the authenticating credential. + example: Session:019542f5-b3e7-1d02-0000-000000000003 + encryptedSessionSigningKey: + type: string + description: |- + HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verification or refresh request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. + + Returned only by session-issuing responses for `OAUTH` and `PASSKEY` credentials. `EMAIL_OTP` sessions omit this field — the client generates a TEK keypair before verification and retains the private key throughout, so the server has nothing to deliver. Always omitted from list responses (`GET /auth/sessions`) since Grid does not retain the plaintext key after the client has decrypted it. + example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf + expiresAt: + type: string + format: date-time + description: Timestamp after which the session is no longer valid and the `encryptedSessionSigningKey` must not be used to sign further requests. + example: '2026-04-09T15:30:01Z' + Error429: type: object required: - message @@ -17182,22 +18684,16 @@ components: status: type: integer enum: - - 403 + - 429 description: HTTP status code code: type: string description: | | Error Code | Description | |------------|-------------| - | FORBIDDEN | Insufficient permissions | - | USER_NOT_READY | Customer exists but is not ready for operation | - | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | - | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | + | RATE_LIMITED | Too many requests in a short window; retry after the interval indicated by the `Retry-After` response header | enum: - - FORBIDDEN - - USER_NOT_READY - - COUNTERPARTY_NOT_ALLOWED - - VELOCITY_LIMIT_EXCEEDED + - RATE_LIMITED message: type: string description: Error message @@ -17205,1079 +18701,1048 @@ components: type: object description: Additional error details additionalProperties: true - SandboxSendRequest: - type: object - required: - - quoteId - - currencyCode - properties: - quoteId: - type: string - description: The unique identifier of the quote - example: Quote:019542f5-b3e7-1d02-0000-000000000006 - currencyCode: - type: string - description: Currency code for the funds to be sent - example: USD - currencyAmount: - type: integer - format: int64 - description: The amount to send in the smallest unit of the currency (eg. cents). If not provided, the amount will be derived from the quote. - exclusiveMinimum: 0 - example: 1000 - SandboxUmaReceiveRequest: - type: object - required: - - senderUmaAddress - - receivingCurrencyCode - - receivingCurrencyAmount - properties: - senderUmaAddress: - type: string - description: UMA address of the sender from the sandbox - example: $success.usd@sandbox.grid.uma.money - receiverUmaAddress: - type: string - description: UMA address of the receiver (optional if customerId is provided) - example: $receiver@uma.domain - customerId: - type: string - description: System ID of the receiver (optional if receiverUmaAddress is provided) - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - receivingCurrencyCode: - type: string - description: The currency code for the receiving amount - example: USD - receivingCurrencyAmount: - type: integer - format: int64 - description: The amount to be received in the smallest unit of the currency (eg. cents) - exclusiveMinimum: 0 - example: 1000 - SandboxFundRequest: - type: object - required: - - amount - properties: - amount: - type: integer - format: int64 - description: Amount to add in the smallest unit of the account's currency (e.g., cents for USD/EUR, satoshis for BTC) - exclusiveMinimum: 0 - maximum: 100000000000 - example: 100000 - UmaProvider: + AuthCredentialChallengeRequest: + title: Auth Credential Challenge Request + description: Request body for `POST /auth/credentials/{id}/challenge`. Required when re-challenging a `PASSKEY` credential — must carry `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from. Ignored for `EMAIL_OTP`, where the credential type alone is sufficient because the OTP is delivered out-of-band. OAuth credentials do not use this endpoint; authenticate or reauthenticate them with `POST /auth/credentials/{id}/verify`. type: object properties: - name: - type: string - description: Name of the UMA Provider - example: Lightspark Group - supportedRegions: - type: array - items: - type: string - description: Region(s) this UMA Provider operates in - example: - - US - domain: - type: string - description: Domain this VASP uses for UMA addresses - example: uma.me - logoUrl: - type: string - description: Logo URL for the VASP - format: uri - example: https://uma.me/logo.png - supportedCurrencies: - type: array - items: - $ref: '#/components/schemas/Currency' - description: List of currencies supported by this UMA Provider - example: - - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - lei: + clientPublicKey: type: string - description: Legal Entity Identifier for the UMA Provider - example: 5493001KJTIIGC8Y1R12 - allowListStatus: - type: boolean - description: Whether this UMA Provider is on your allow list - example: true - UmaProviderListResponse: + pattern: ^04[0-9a-fA-F]{128}$ + minLength: 130 + maxLength: 130 + description: Required for `PASSKEY` credentials. Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid bakes this key into the Turnkey session-creation payload that the returned `challenge` is computed from, so the resulting session signing key is sealed to the client. Ignored for `EMAIL_OTP`. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + PasskeyAuthChallenge: + title: Passkey Auth Challenge + description: Extended `AuthMethod` shape returned for `PASSKEY` credentials from `POST /auth/credentials/{id}/challenge`. Includes the WebAuthn `credentialId` needed to target the passkey, plus the Grid-issued `challenge`, corresponding `requestId`, and challenge `expiresAt`. The `challenge` value is the lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body, not a base64url string. The client UTF-8 encodes this string as the WebAuthn challenge and signs it with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. + allOf: + - $ref: '#/components/schemas/AuthMethod' + - type: object + required: + - credentialId + - challenge + - requestId + - expiresAt + properties: + credentialId: + type: string + description: Base64url-encoded WebAuthn credential identifier for this passkey. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. + example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew + challenge: + type: string + description: Lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body for the pending passkey authentication. Do not base64url-decode this field; pass UTF-8 bytes of the string (for example, `new TextEncoder().encode(challenge)`) as the WebAuthn challenge to `navigator.credentials.get()`. Single-use; a new challenge is issued on the next call to `POST /auth/credentials/{id}/challenge`. + example: 6b35a4c41d9aa7a2a0e742f9f9e7a1c2d65a2db33a3fb748f6d4f1ce78d9a729 + requestId: + type: string + description: Grid-issued `Request:` identifier for this pending passkey authentication request. Echo this value exactly as the `Request-Id` header on the subsequent `POST /auth/credentials/{id}/verify` call so Grid can correlate the assertion with the issued challenge. + example: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 + expiresAt: + type: string + format: date-time + description: Timestamp after which the issued challenge is no longer valid. The assertion must reach `POST /auth/credentials/{id}/verify` before this time; otherwise the client must request a fresh challenge via `POST /auth/credentials/{id}/challenge`. + example: '2026-04-08T15:35:00Z' + AuthCredentialResponseOneOf: + title: Auth Credential Response + description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. + oneOf: + - $ref: '#/components/schemas/AuthMethodResponse' + - $ref: '#/components/schemas/PasskeyAuthChallenge' + discriminator: + propertyName: type + mapping: + EMAIL_OTP: '#/components/schemas/AuthMethodResponse' + PASSKEY: '#/components/schemas/PasskeyAuthChallenge' + SessionListResponse: type: object + required: + - data properties: data: - description: List of available UMA Providers using Grid type: array + description: List of active authentication sessions for the internal account. items: - $ref: '#/components/schemas/UmaProvider' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: - type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: - type: integer - description: Total number of transactions matching the criteria (excluding pagination) - Permission: - type: string - enum: - - VIEW - - TRANSACT - - MANAGE - description: 'Permission of an API token that determines what actions the token can perform: VIEW: Can view all data, including platform config, customers and transactions TRANSACT: Can send payments MANAGE: Can manage platform config, api tokens and customers' - ApiToken: + $ref: '#/components/schemas/AuthSession' + AuthSessionRefreshRequest: + title: Auth Session Refresh Request + description: Request body for refreshing an active authentication session. The `clientPublicKey` is required on both steps of the signed-retry flow. On the initial call, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the signed retry, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. type: object required: - - id - - name - - permissions - - clientId - - createdAt - - updatedAt + - clientPublicKey properties: - id: - type: string - description: System-generated unique identifier - example: Token:019542f5-b3e7-1d02-0000-000000000001 - name: - type: string - description: Name of the token - example: Sandbox read-only token - permissions: - type: array - description: A list of permissions granted to the token - items: - $ref: '#/components/schemas/Permission' - clientId: - type: string - description: An opaque identifier that should be used as a client_id (or username) in the HTTP Basic Authentication scheme when issuing http requests to Grid. - example: 01947d2284054f890000e63bca4810df - clientSecret: - type: string - description: The secret that should be used to authenticate against Grid API. This secret is not stored and will never be available again after creation. Platform must keep this secret secure as it grants access to the account. - example: ed0ad25881e234cc28fb2dec0a4fe64e4172 - createdAt: - type: string - format: date-time - description: Creation timestamp - example: '2025-07-21T17:32:28Z' - updatedAt: + clientPublicKey: type: string - format: date-time - description: Last update timestamp - example: '2025-07-21T17:32:28Z' - TokenListResponse: + pattern: ^04[0-9a-fA-F]{128}$ + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the initial call and seals the returned `encryptedSessionSigningKey` to it on the signed retry. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + AgentPermission: + type: string + enum: + - VIEW_TRANSACTIONS + - CREATE_TRANSFERS + - CREATE_QUOTES + - EXECUTE_QUOTES + - MANAGE_EXTERNAL_ACCOUNTS + description: 'Permission granted to an agent that determines what actions it can perform. VIEW_TRANSACTIONS: Can list and retrieve transactions and account balances. CREATE_TRANSFERS: Can initiate same-currency transfers. CREATE_QUOTES: Can create cross-currency quotes. EXECUTE_QUOTES: Can execute cross-currency quotes. MANAGE_EXTERNAL_ACCOUNTS: Can create and manage external accounts.' + AgentExecutionMode: + type: string + enum: + - AUTO + - APPROVAL_REQUIRED + description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' + AgentSpendingLimits: type: object + description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: - - data - - hasMore + - currency + - perTransactionLimit properties: - data: - type: array - description: List of tokens matching the filter criteria - items: - $ref: '#/components/schemas/ApiToken' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: + currency: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: + description: ISO 4217 currency code that all amount limits are denominated in. + example: USD + perTransactionLimit: type: integer - description: Total number of tokens matching the criteria (excluding pagination) - ApiTokenCreateRequest: + description: Maximum amount the agent can transfer in a single transaction. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per day. Null means no daily limit. + example: 500000 + dailyTransactionLimit: + type: integer + description: Maximum number of transactions the agent can initiate per day. + example: 10 + monthlyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per month. Null means no monthly limit. + example: 5000000 + AgentAccountRule: type: object + description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: - - name - - permissions + - accountId properties: - name: + accountId: type: string - description: Name of the token to help identify it - example: Sandbox read-only - permissions: + description: The internal account ID this rule applies to. + example: Account:019542f5-b3e7-1d02-0000-000000000001 + executionMode: + $ref: '#/components/schemas/AgentExecutionMode' + perTransactionLimit: + type: + - integer + - 'null' + description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. + example: 10000 + AgentAccountRestrictions: + type: object + description: Optional restrictions that limit the agent to specific accounts or override policy per account. + properties: + allowedAccountIds: + type: + - array + - 'null' + description: If set, restricts the agent to operate only on the specified internal account IDs. Null means the agent can access all accounts. + items: + type: string + example: Account:019542f5-b3e7-1d02-0000-000000000001 + accountRules: type: array - description: A list of permissions to grant to the token + description: Per-account rules that override the agent's default policy for specific accounts. items: - $ref: '#/components/schemas/Permission' - InternalAccountUpdateRequest: - title: Internal Account Update Request - description: Partial request body for `PATCH /internal-accounts/{id}`. At least one update field must be provided. On step 1 of the signed-retry flow Grid binds the submitted update fields into `payloadToSign`; on step 2 the client echoes the same fields back and Grid applies the update to the internal account. + $ref: '#/components/schemas/AgentAccountRule' + AgentApprovalThresholds: type: object + description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: - privateEnabled: - type: boolean - description: Whether wallet privacy should be enabled for the Embedded Wallet. - example: true - InternalAccountExportRequest: - title: Internal Account Export Request - description: Request body for `POST /internal-accounts/{id}/export`. The `clientPublicKey` is required on both steps of the signed-retry flow. On step 1 Grid binds it into `payloadToSign` so the subsequent stamp in `Grid-Wallet-Signature` commits to the target pubkey; on step 2 the client echoes the same `clientPublicKey` back and Grid uses it to encrypt the wallet credentials returned in the `200` response. + currency: + type: string + description: ISO 4217 currency code that the amount threshold is denominated in. Required when amount is set. + example: USD + amount: + type: + - integer + - 'null' + description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. + example: 100000 + AgentPolicy: type: object + description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: - - clientPublicKey + - permissions + - defaultExecutionMode + - spendingLimits properties: - clientPublicKey: - type: string - description: Fresh P-256 public key, uncompressed SEC1 hex — 130 hex chars where the first two are `04` (the uncompressed-point indicator). Generate a new keypair for each export and discard the private key after decrypting the response. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - InternalAccountExportResponse: - title: Internal Account Export Response + permissions: + type: array + description: List of permissions granted to the agent. + items: + $ref: '#/components/schemas/AgentPermission' + defaultExecutionMode: + $ref: '#/components/schemas/AgentExecutionMode' + spendingLimits: + $ref: '#/components/schemas/AgentSpendingLimits' + accountRestrictions: + $ref: '#/components/schemas/AgentAccountRestrictions' + approvalThresholds: + $ref: '#/components/schemas/AgentApprovalThresholds' + AgentUsage: type: object + description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: - - id - - encryptedWalletCredentials + - dailyTransactionCount + - dailySpend + - monthlySpend properties: - id: + dailyTransactionCount: + type: integer + description: Number of transactions initiated by the agent today. + example: 3 + dailySpend: + type: integer + description: Total amount spent by the agent today, in the smallest unit of the policy's `spendingLimits.currency`. + example: 150000 + dailyResetDate: type: string - description: The id of the internal account that was exported. - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - encryptedWalletCredentials: + format: date + description: The date when daily usage counters will reset. + example: '2025-07-22' + monthlySpend: + type: integer + description: Total amount spent by the agent this month, in the smallest unit of the policy's `spendingLimits.currency`. + example: 750000 + monthlyResetMonth: type: string - description: |- - Encrypted wallet mnemonic, sealed to the `clientPublicKey` from the request body using HPKE: DHKEM(P-256, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM. Decrypt with the matching private key, then manage the mnemonic securely because it is the master key of the self-custodial Embedded Wallet. - The value is a JSON string of the form `{"version": "v1.0.0", "data": "", "dataSignature": "", "enclaveQuorumPublic": ""}`. `data` hex-decodes to JSON `{"encappedPublic": "", "ciphertext": "", "organizationId": ""}`, where `encappedPublic` is the uncompressed SEC1 ephemeral public key. `dataSignature` is an ECDSA-P256-SHA256 signature over the `data` bytes produced by the issuer key in `enclaveQuorumPublic`; verify before decrypting. - In sandbox, `dataSignature` and `enclaveQuorumPublic` are empty strings. Clients should bypass attestation verification when calling against sandbox. - example: '{"version":"v1.0.0","data":"7b22656e6361707065645075626c6963223a22303433...","dataSignature":"3045022100c9...","enclaveQuorumPublic":"04a1b2c3..."}' - AuthMethodType: - type: string - enum: - - OAUTH - - EMAIL_OTP - - PASSKEY - description: |- - The type of authentication credential. - - `OAUTH`: OpenID Connect (OIDC) token issued by an identity provider such as Google or Apple. - - `EMAIL_OTP`: A one-time password delivered to the user's email address. - - `PASSKEY`: A WebAuthn passkey bound to the user's device. - AuthMethod: + description: The year-month (YYYY-MM) when monthly usage counters will reset. + example: 2025-08 + Agent: type: object + description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: - id - - accountId - - type - - nickname + - name + - customerId + - isPaused + - isConnected + - policy + - usage - createdAt - updatedAt properties: id: type: string - description: System-generated unique identifier for the authentication credential. - example: AuthMethod:019542f5-b3e7-1d02-0000-000000000001 - accountId: - type: string - description: Identifier of the internal account that this credential authenticates. - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - type: - $ref: '#/components/schemas/AuthMethodType' - credentialId: + description: System-generated unique identifier for the agent. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + name: type: string - description: Base64url-encoded WebAuthn credential identifier for this passkey. Present only for `PASSKEY` authentication credentials. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. - example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew - nickname: + description: Human-readable name for the agent. + example: Payroll Automation Agent + customerId: type: string - description: Human-readable identifier for this credential. For EMAIL_OTP credentials this is the email address; for OAUTH credentials it is typically the email claim from the OIDC token; for PASSKEY credentials it is the validated nickname provided at registration time. - example: example@lightspark.com + description: The ID of the customer this agent operates on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + isPaused: + type: boolean + description: Whether the agent is currently paused. Paused agents cannot initiate any actions. + example: false + isConnected: + type: boolean + description: Whether the agent has been installed and connected (i.e., its device code has been redeemed). + example: true + policy: + $ref: '#/components/schemas/AgentPolicy' + usage: + $ref: '#/components/schemas/AgentUsage' createdAt: type: string format: date-time description: Creation timestamp. - example: '2026-04-08T15:30:01Z' + example: '2025-07-21T17:32:28Z' updatedAt: type: string format: date-time description: Last update timestamp. - example: '2026-04-08T15:35:00Z' - AuthCredentialListResponse: + example: '2025-07-21T17:32:28Z' + AgentListResponse: type: object required: - data + - hasMore properties: data: type: array - description: List of authentication credentials registered on the internal account. + description: List of agents matching the filter criteria. items: - $ref: '#/components/schemas/AuthMethod' - AuthCredentialCreateRequest: - type: object - required: - - type - - accountId - properties: - type: - $ref: '#/components/schemas/AuthMethodType' - accountId: - type: string - description: Identifier of the internal account that this credential will authenticate. - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - EmailOtpCredentialCreateRequestFields: - type: object - required: - - type - properties: - type: - type: string - enum: - - EMAIL_OTP - description: Discriminator value identifying this as an email OTP credential. - EmailOtpCredentialCreateRequest: - title: Email OTP Credential Create Request - allOf: - - $ref: '#/components/schemas/AuthCredentialCreateRequest' - - $ref: '#/components/schemas/EmailOtpCredentialCreateRequestFields' - OauthCredentialCreateRequestFields: - type: object - required: - - type - - oidcToken - properties: - type: - type: string - enum: - - OAUTH - description: Discriminator value identifying this as an OAuth credential. - oidcToken: + $ref: '#/components/schemas/Agent' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: type: string - description: OIDC ID token issued by the identity provider (e.g. Google, Apple). The token's `iss`, `aud`, and `sub` claims define the OAuth identity registered to this credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and `iat` less than 60 seconds before the request timestamp, but the signature segment may be a dummy value. - example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q - OauthCredentialCreateRequest: - title: OAuth Credential Create Request - allOf: - - $ref: '#/components/schemas/AuthCredentialCreateRequest' - - $ref: '#/components/schemas/OauthCredentialCreateRequestFields' - PasskeyAttestation: - title: Passkey Attestation + description: Cursor to retrieve the next page of results (only present if hasMore is true). + totalCount: + type: integer + description: Total number of agents matching the criteria (excluding pagination). + AgentCreateRequest: type: object required: - - credentialId - - clientDataJson - - attestationObject + - name + - customerId + - policy properties: - credentialId: - type: string - description: Base64url-encoded credential identifier produced by the authenticator at registration time. Typically the base64url of `PublicKeyCredential.rawId`. - example: AdKXJEch1aV5Wo7bj7qLHskVY4OoNaj9qu8TPdJ7kSAgUeRxWNngXlcNIGt4gexZGKVGcqZpqqWordXb_he1izY - clientDataJson: + name: type: string - description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.create()` call. Corresponds to `AuthenticatorAttestationResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.create"`.' - example: eyJjaGFsbGVuZ2UiOiJBcktRaTJ5QVlIUGxnbkpORkJsbmVJd2NoUWRXWEJPVHJkQi1BbU1VQjIxTHgiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0 - attestationObject: + description: Human-readable name to identify the agent. + example: Payroll Automation Agent + customerId: type: string - description: Base64url-encoded CBOR attestation object produced by the authenticator during registration. Corresponds to `AuthenticatorAttestationResponse.attestationObject`. - example: o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFPdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQHSlyRHIdWleVqO24-6ix7JFWODqDWo_arvEz3Se5EgIFHkcVjZ4F5XDSBreIHsWRilRnKmaaqlqK3V2_4XtYs2pQECAyYgASFYID5PQTZQQg6haZFQWFzqfAOyQ_ENsMH8xxQ4GRiNPsqrIlggU8IVUOV8qpgk_Jh-OTaLuZL52KdX1fTht07X4DiQPow - transports: - type: array - items: - type: string - enum: - - usb - - nfc - - ble - - internal - - hybrid - description: Optional. WebAuthn transports as returned by `AuthenticatorAttestationResponse.getTransports()`. Values follow the W3C `AuthenticatorTransport` enum — pass the raw values through to Grid; provider-specific translation is handled server-side. Some authenticators return an empty array; omit the field or send `[]` in that case. - example: - - internal - - hybrid - PasskeyCredentialCreateRequestFields: + description: The ID of the customer this agent will operate on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + policy: + $ref: '#/components/schemas/AgentPolicy' + AgentDeviceCode: type: object required: - - type - - nickname - - challenge - - attestation + - code + - agentId + - expiresAt + - redeemed properties: - type: + code: type: string - enum: - - PASSKEY - description: Discriminator value identifying this as a passkey credential. - nickname: + description: Human-readable device code used to install and connect the agent software. + example: GRID-AGENT-X7K9-M2P4 + agentId: type: string - description: 'Human-readable identifier for the passkey, chosen by the user at registration time (e.g. "iPhone Face-ID", "YubiKey 5C"). Leading and trailing whitespace is ignored. Must be 1-100 characters and may contain Unicode letters, numbers, spaces, and the following separators: period, underscore, hyphen, apostrophe, and parentheses. Shown back on AuthMethod responses and in credential listings.' - example: iPhone Face-ID - challenge: + description: The agent this device code belongs to. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + expiresAt: type: string - description: Base64url-encoded WebAuthn challenge issued by the platform backend and passed to the client before `navigator.credentials.create()`. Grid verifies it matches the challenge embedded in the attestation's `clientDataJson`, binding the attestation to this registration. Must be single-use. - example: ArkQi2yAYHPlgnJNFBlneIwchQdWXBOTrdB-AmMUB21Lx - attestation: - $ref: '#/components/schemas/PasskeyAttestation' - PasskeyCredentialCreateRequest: - title: Passkey Credential Create Request - allOf: - - $ref: '#/components/schemas/AuthCredentialCreateRequest' - - $ref: '#/components/schemas/PasskeyCredentialCreateRequestFields' - AuthCredentialCreateRequestOneOf: - oneOf: - - $ref: '#/components/schemas/EmailOtpCredentialCreateRequest' - - $ref: '#/components/schemas/OauthCredentialCreateRequest' - - $ref: '#/components/schemas/PasskeyCredentialCreateRequest' - discriminator: - propertyName: type - mapping: - EMAIL_OTP: '#/components/schemas/EmailOtpCredentialCreateRequest' - OAUTH: '#/components/schemas/OauthCredentialCreateRequest' - PASSKEY: '#/components/schemas/PasskeyCredentialCreateRequest' - AuthMethodResponse: - title: Auth Method Response - description: |- - Strict wrapper around `AuthMethod`. Used directly as the registration response on `POST /auth/credentials` (all three credential types) and inside `AuthCredentialResponseOneOf` for the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/challenge`. The only difference from `AuthMethod` is `unevaluatedProperties: false`, which disambiguates the oneOf against `PasskeyAuthChallenge` — without the strictness, an `AuthMethod` with extra fields would ambiguously match both branches. - - For `EMAIL_OTP` credentials, responses that initiate or reissue an OTP challenge carry `otpEncryptionTargetBundle` so the client can HPKE-encrypt the OTP code in the subsequent `POST /auth/credentials/{id}/verify` call without the plaintext code ever transiting the server. First-time EMAIL_OTP wallet bootstrap registration can omit it; call `POST /auth/credentials/{id}/challenge` if it is absent. - allOf: - - $ref: '#/components/schemas/AuthMethod' - - type: object - properties: - otpEncryptionTargetBundle: - type: string - description: HPKE encryption target bundle for a freshly initiated OTP challenge. Returned only on `EMAIL_OTP` responses that initiate or reissue an OTP challenge, such as `POST /auth/credentials/{id}/challenge` and the add-EMAIL_OTP signed-retry response. It is omitted from first-time EMAIL_OTP wallet bootstrap registration; call `POST /auth/credentials/{id}/challenge` for the new credential if it is absent. The client generates an ephemeral P-256 keypair (the Target Encryption Key, or TEK) and uses this bundle as the recipient when HPKE-encrypting `{otp_code, public_key}`; the encrypted payload is submitted as `encryptedOtpBundle` on `POST /auth/credentials/{id}/verify`. The bundle is one-time-use per OTP issuance — re-issue via `POST /auth/credentials/{id}/challenge` to obtain a fresh bundle. The matching TEK private key must remain on the client and is used to sign the `verificationToken` returned on the subsequent signed-retry. Treat the bundle as opaque and pass it to your HPKE library; the Global Accounts client-keys guide shows how. - example: '{"version":"v1.0.0","data":"7b227461726765745075626c6963...","dataSignature":"30450221...","enclaveQuorumPublic":"04a1b2c3..."}' - unevaluatedProperties: false - AuthSignedRequestChallenge: - title: Authentication Signed Request Challenge - description: |- - 202 response returned from Embedded Wallet Auth endpoints that require a signed retry — `POST /auth/credentials` (adding an additional credential), `DELETE /auth/credentials/{id}` (revoking a credential), `DELETE /auth/sessions/{id}` (revoking a session), and the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify` (the secure OTP login flow, where the client submits an `encryptedOtpBundle` and receives a `verificationToken` to sign for the second-leg session issuance). Carries the signing fields from `SignedRequestChallenge` plus the `type` of the authentication credential involved (being added, revoked, that issued the session being revoked, or being authenticated). The client already knows the target resource id from the request path / body it just sent, so nothing beyond `type` is echoed in the response. - - The keypair used to compute the stamp depends on the operation. For credential / session management retries, sign with the session API keypair of an existing verified credential on the same internal account. For the `EMAIL_OTP` verify retry, sign with the ephemeral Target Encryption Key (TEK) the client generated for this login — its public key is the one carried inside the `encryptedOtpBundle` and bound into the `verificationToken`, and it becomes the client's session API key on successful completion. - allOf: - - $ref: '#/components/schemas/SignedRequestChallenge' - - type: object - required: - - type - properties: - type: - $ref: '#/components/schemas/AuthMethodType' - description: 'Credential type relevant to this challenge: the credential type being added (`POST /auth/credentials`), revoked (`DELETE /auth/credentials/{id}`), or authenticated (`EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify`). For session revocation, this is the type of credential that issued the session (`DELETE /auth/sessions/{id}`).' - AuthCredentialVerifyRequest: + format: date-time + description: Timestamp when this device code expires. + example: '2025-07-22T17:32:28Z' + redeemed: + type: boolean + description: Whether this device code has already been redeemed by the agent. + example: false + AgentCreateResponse: type: object + description: Response returned when an agent is created, including the agent and a device code for installation. required: - - type + - agent + - deviceCode properties: - type: - $ref: '#/components/schemas/AuthMethodType' - EmailOtpCredentialVerifyRequestFields: + agent: + $ref: '#/components/schemas/Agent' + deviceCode: + $ref: '#/components/schemas/AgentDeviceCode' + AgentActionStatus: + type: string + enum: + - PENDING_APPROVAL + - APPROVED + - REJECTED + - FAILED + description: | + Status of an agent action. + + | Status | Description | + |--------|-------------| + | `PENDING_APPROVAL` | Submitted by the agent, awaiting platform approval before execution | + | `APPROVED` | Approved by the platform; execution is in progress or completed | + | `REJECTED` | Rejected by the platform; the underlying transaction was not executed | + | `FAILED` | Approved but execution failed (e.g. quote expired, insufficient funds) | + AgentActionType: + type: string + enum: + - EXECUTE_QUOTE + - TRANSFER_OUT + - TRANSFER_IN + description: | + The type of action the agent is requesting. + + | Type | Description | + |------|-------------| + | `EXECUTE_QUOTE` | Execute a cross-currency quote | + | `TRANSFER_OUT` | Transfer from an internal account to an external account | + | `TRANSFER_IN` | Transfer from an external account to an internal account | + AgentTransferDetails: type: object + description: Details of a transfer-type agent action (TRANSFER_OUT or TRANSFER_IN). required: - - type - - encryptedOtpBundle - description: Verify an email-OTP credential via the secure two-leg flow. The client HPKE-encrypts the OTP code (together with its public key) under the `otpEncryptionTargetBundle` returned from registration when present, or from `POST /auth/credentials/{id}/challenge` when registration omitted it or the OTP must be reissued, submits the result here, and receives `202` with a `payloadToSign` carrying a `verificationToken` bound to the client's public key. The client signs that token with the matching private key and retries this request with `Grid-Wallet-Signature` + `Request-Id` headers to obtain the session. Plaintext OTP codes are never sent over the wire. + - amount + - currency + - sourceAccountId + - destinationAccountId properties: - type: + amount: + type: integer + format: int64 + description: Transfer amount in the smallest unit of the specified currency. + example: 50000 + currency: type: string - enum: - - EMAIL_OTP - description: Discriminator value identifying this as an email OTP verification. - encryptedOtpBundle: + description: ISO 4217 currency code for the transfer amount. + example: USD + sourceAccountId: type: string - description: |- - HPKE-sealed OTP attempt — the OTP code never reaches Grid in plaintext. The client generates a fresh ephemeral P-256 key pair (the session signing key pair it keeps once login completes), HPKE-encrypts `{otp_code, public_key}` (the code the user entered plus that key pair's public key) to the key in `otpEncryptionTargetBundle`, and submits the encrypted result here. The value is the `{encappedPublic, ciphertext}` JSON an HPKE library produces; the Global Accounts client-keys guide has a worked example. - - On success the response is `202` with a `payloadToSign` carrying a `verificationToken` bound to the public key sealed in this bundle. Sign that token with the matching private key, then retry this request with the full stamp in `Grid-Wallet-Signature` and the `requestId` in `Request-Id` to complete the flow and receive the session. The client keeps that private key as the session signing key, and its public key becomes the session API key. - example: '{"encappedPublic":"044f631a2d890bc6668d997ee184e190650d06adf970987568ec641214a00403b73effe1ef406c60a5cde8508a4484567ddb8056fbd493bee614cd727aef02a838","ciphertext":"1fa1023390a56539aa48cbb380aa28f544ed5cc04861566bb806e25ba026f14660eaf4140a05b388dd012eaa899759a6a92576cdca8c1b7d12e147bd96cc26ed9f74886794155d8ac5cf0fdc"}' - EmailOtpCredentialVerifyRequest: - title: Email OTP Credential Verify Request - allOf: - - $ref: '#/components/schemas/AuthCredentialVerifyRequest' - - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequestFields' - OauthCredentialVerifyRequestFields: + description: ID of the source account (internal or external). + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destinationAccountId: + type: string + description: ID of the destination account (internal or external). + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + AgentAction: type: object + description: An action submitted by an agent that may require platform approval before execution. All agent-initiated operations (quote execution, transfers) are represented as AgentActions, giving the platform a consistent object to approve, reject, and audit regardless of the underlying operation type. required: + - id + - agentId + - customerId + - platformCustomerId + - status - type - - oidcToken - - clientPublicKey + - createdAt + - updatedAt properties: + id: + type: string + description: System-generated unique identifier for this action. + example: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: + type: string + description: The agent that submitted this action. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: + type: string + description: The customer on whose behalf the action was submitted. + example: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: + type: string + description: Platform-specific ID of the customer. + example: user-a1b2c3 + status: + $ref: '#/components/schemas/AgentActionStatus' type: + $ref: '#/components/schemas/AgentActionType' + quote: + allOf: + - $ref: '#/components/schemas/Quote' + description: The quote being executed. Populated for `EXECUTE_QUOTE` actions; absent for transfer actions. Contains the full amount, currency, destination, and rate details needed to present an approval decision to the user. + transferDetails: + allOf: + - $ref: '#/components/schemas/AgentTransferDetails' + description: Details of the transfer being requested. Populated for `TRANSFER_OUT` and `TRANSFER_IN` actions; absent for `EXECUTE_QUOTE` actions. + transaction: + allOf: + - $ref: '#/components/schemas/TransactionOneOf' + description: The resulting transaction, populated once the action has been approved and execution has begun. Absent while the action is `PENDING_APPROVAL` or `REJECTED`. + rejectionReason: type: string - enum: - - OAUTH - description: Discriminator value identifying this as an OAuth verification. - oidcToken: + description: Human-readable reason provided by the platform when rejecting the action. Only present when status is `REJECTED`. + example: Transaction amount exceeds customer's current risk limit. + createdAt: type: string - description: OIDC ID token issued by the identity provider. For reauthentication after a prior session expired, supply a fresh token — the token's `iat` claim must be less than 60 seconds before the request timestamp. The token identity (`iss`, `aud`, and `sub`) must match the registered OAuth credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and a `nonce` equal to `sha256(clientPublicKey)`, but the signature segment may be a dummy value. - example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q - clientPublicKey: + format: date-time + description: When the action was submitted by the agent. + example: '2025-10-03T15:00:00Z' + updatedAt: type: string - description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (0x04 prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid encrypts the session signing key returned in the response to this public key. The key is ephemeral and one-time-use per verification request. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - OauthCredentialVerifyRequest: - title: OAuth Credential Verify Request - allOf: - - $ref: '#/components/schemas/AuthCredentialVerifyRequest' - - $ref: '#/components/schemas/OauthCredentialVerifyRequestFields' - PasskeyAssertion: - title: Passkey Assertion + format: date-time + description: When the action was last updated. + example: '2025-10-03T15:02:00Z' + AgentActionListResponse: type: object - description: WebAuthn assertion returned by `navigator.credentials.get()`. In sandbox, Grid validates the assertion against the registered passkey credential so the client-side flow can match production. In production, Turnkey validates the WebAuthn assertion. required: - - credentialId - - clientDataJson - - authenticatorData - - signature + - data + - hasMore properties: - credentialId: - type: string - description: Base64url-encoded credential identifier returned during the WebAuthn assertion. Corresponds to `PublicKeyCredential.rawId`. - example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew - clientDataJson: + data: + type: array + description: List of agent actions matching the filter criteria. + items: + $ref: '#/components/schemas/AgentAction' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: type: string - description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.get()` call. Corresponds to `AuthenticatorAssertionResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.get"`.' - example: eyJjaGFsbGVuZ2UiOiJkRzkwWVd4c2VWVnVhWEYxWlZaaGJIVmxSWFpsY25sVWFXMWwiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uZ2V0In0 - authenticatorData: + description: Cursor to retrieve the next page of results (only present if hasMore is true). + totalCount: + type: integer + description: Total number of actions matching the criteria (excluding pagination). + AgentUpdateRequest: + type: object + description: Partial update to an agent's basic fields. At least one field must be provided. + properties: + name: type: string - description: Base64url-encoded authenticator data returned by the authenticator during the assertion. Corresponds to `AuthenticatorAssertionResponse.authenticatorData`. - example: PdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KABAAAAkA - signature: + description: Updated name for the agent. + example: Updated Payroll Agent + isPaused: + type: boolean + description: Set to true to pause the agent or false to resume it. + example: true + AgentSpendingLimitsUpdate: + type: object + description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. + properties: + currency: type: string - description: Base64url-encoded signature produced by the authenticator over `authenticatorData || SHA-256(clientDataJSON)`. Corresponds to `AuthenticatorAssertionResponse.signature`. The signature byte format is determined by the credential's public-key algorithm — DER-encoded ECDSA for ES256 (P-256, typical for passkeys), PKCS#1 v1.5 for RS256, or a raw 64-byte signature for EdDSA. - example: MEUCIQDYXBOpCWSWq2Ll4558GJKD2RoWg958lvJSB_GdeokxogIgWuEVQ7ee6AswQY0OsuQ6y8Ks6jhd45bDx92wjXKs900 - userHandle: + description: ISO 4217 currency code that all amount limits are denominated in. Updating this recasts all existing limits into the new currency denomination. + example: USD + perTransactionLimit: + type: integer + description: Maximum amount per transaction. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum daily spend. Set to null to remove the daily limit. + example: 500000 + dailyTransactionLimit: + type: integer + description: Maximum number of transactions per day. + example: 10 + monthlyLimit: + type: + - integer + - 'null' + description: Maximum monthly spend. Set to null to remove the monthly limit. + example: 5000000 + AgentPolicyUpdateRequest: + type: object + description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. + properties: + permissions: + type: array + description: Updated list of permissions. Replaces the entire permissions list when provided. + items: + $ref: '#/components/schemas/AgentPermission' + defaultExecutionMode: + $ref: '#/components/schemas/AgentExecutionMode' + spendingLimits: + $ref: '#/components/schemas/AgentSpendingLimitsUpdate' + accountRestrictions: + $ref: '#/components/schemas/AgentAccountRestrictions' + approvalThresholds: + $ref: '#/components/schemas/AgentApprovalThresholds' + AgentActionRejectRequest: + type: object + properties: + reason: type: string - description: Base64url-encoded user handle returned by the authenticator. Corresponds to `AuthenticatorAssertionResponse.userHandle`. Populated (and required by the WebAuthn spec) for discoverable credentials — resident keys used in the "Sign in with passkey" autofill flow — and typically present for passkey registrations. Omit this field entirely for non-discoverable credentials specified via `allowCredentials` where the authenticator returns no user handle. - example: dXNlci1oYW5kbGUtZXhhbXBsZQ - PasskeyCredentialVerifyRequestFields: + description: Optional human-readable reason for the rejection, stored on the action and visible to the platform. + example: Transaction amount exceeds customer's current risk limit. + AgentDeviceCodeStatusResponse: + type: object + required: + - code + - redeemed + properties: + code: + type: string + description: The device code. + example: GRID-AGENT-X7K9-M2P4 + redeemed: + type: boolean + description: Whether this device code has been redeemed. + example: false + AgentDeviceCodeRedeemResponse: type: object required: - - type - - assertion + - agentId + - agentName + - accessToken + - policy properties: - type: + agentId: type: string - enum: - - PASSKEY - description: Discriminator value identifying this as a passkey verification. - assertion: - $ref: '#/components/schemas/PasskeyAssertion' - PasskeyCredentialVerifyRequest: - title: Passkey Credential Verify Request - allOf: - - $ref: '#/components/schemas/AuthCredentialVerifyRequest' - - $ref: '#/components/schemas/PasskeyCredentialVerifyRequestFields' - AuthCredentialVerifyRequestOneOf: - oneOf: - - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequest' - - $ref: '#/components/schemas/OauthCredentialVerifyRequest' - - $ref: '#/components/schemas/PasskeyCredentialVerifyRequest' - discriminator: - propertyName: type - mapping: - EMAIL_OTP: '#/components/schemas/EmailOtpCredentialVerifyRequest' - OAUTH: '#/components/schemas/OauthCredentialVerifyRequest' - PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' - AuthSession: - title: Authentication Session - description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/refresh` (on mid-session refresh). Only session-issuing responses include `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. - allOf: - - $ref: '#/components/schemas/AuthMethod' - - type: object - required: - - id - - expiresAt - properties: - id: - type: string - description: System-generated unique identifier for the session. Pass this value to `DELETE /auth/sessions/{id}` to revoke the session before `expiresAt`. Overrides the `id` inherited from `AuthMethod` so this response identifies the session rather than the authenticating credential. - example: Session:019542f5-b3e7-1d02-0000-000000000003 - encryptedSessionSigningKey: - type: string - description: |- - HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verification or refresh request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. + description: The agent's system-generated ID. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + agentName: + type: string + description: The agent's name. + example: Payroll Automation Agent + accessToken: + type: string + description: 'Bearer token used to authenticate all subsequent API calls as this agent. Pass as `Authorization: Bearer `. This token is returned only once and must be stored securely — it cannot be retrieved again.' + example: gat_ed0ad25881e234cc28fb2dec0a4fe64e4172a3b9 + policy: + $ref: '#/components/schemas/AgentPolicy' + CardState: + type: string + enum: + - PENDING_KYC + - PENDING_ISSUE + - ACTIVE + - FROZEN + - CLOSED + description: | + Lifecycle state of a card. - Returned only by session-issuing responses for `OAUTH` and `PASSKEY` credentials. `EMAIL_OTP` sessions omit this field — the client generates a TEK keypair before verification and retains the private key throughout, so the server has nothing to deliver. Always omitted from list responses (`GET /auth/sessions`) since Grid does not retain the plaintext key after the client has decrypted it. - example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf - expiresAt: - type: string - format: date-time - description: Timestamp after which the session is no longer valid and the `encryptedSessionSigningKey` must not be used to sign further requests. - example: '2026-04-09T15:30:01Z' - Error429: + | State | Description | + |-------|-------------| + | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this state cannot transact. | + | `PENDING_ISSUE` | The card has been requested and is being provisioned with the issuer. | + | `ACTIVE` | The card is live and can authorize transactions. | + | `FROZEN` | The card is temporarily disabled by the platform. New authorizations are declined with `CARD_PAUSED`. Existing settlements and refunds continue to reconcile. | + | `CLOSED` | The card is permanently closed. Terminal, irreversible state. | + CardStateReason: + type: string + enum: + - ISSUER_REJECTED + - CLOSED_BY_PLATFORM + - CLOSED_BY_GRID + description: | + Reason a card reached a terminal or non-active state. Present on + `CLOSED` cards, and on cards that fail provisioning before reaching + `ACTIVE`. + + | Reason | Description | + |--------|-------------| + | `ISSUER_REJECTED` | The card issuer rejected provisioning during `PENDING_ISSUE`. | + | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`state: CLOSED`) by the platform. | + | `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or risk action). | + CardBrand: + type: string + enum: + - VISA + - MASTERCARD + description: | + Card network brand. Read-only — determined by Grid when the card is + provisioned with the issuer. + CardForm: + type: string + enum: + - VIRTUAL + description: | + Physical form factor of the card. Only `VIRTUAL` is supported in v1; + `PHYSICAL` will be added in a later release. + Card: type: object required: - - message - - status - - code + - id + - cardholderId + - state + - form + - fundingSources + - createdAt + - updatedAt properties: - status: - type: integer - enum: - - 429 - description: HTTP status code - code: + id: type: string - description: | - | Error Code | Description | - |------------|-------------| - | RATE_LIMITED | Too many requests in a short window; retry after the interval indicated by the `Retry-After` response header | - enum: - - RATE_LIMITED - message: + description: System-generated unique card identifier + readOnly: true + example: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true - AuthCredentialChallengeRequest: - title: Auth Credential Challenge Request - description: Request body for `POST /auth/credentials/{id}/challenge`. Required when re-challenging a `PASSKEY` credential — must carry `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from. Ignored for `EMAIL_OTP`, where the credential type alone is sufficient because the OTP is delivered out-of-band. OAuth credentials do not use this endpoint; authenticate or reauthenticate them with `POST /auth/credentials/{id}/verify`. - type: object - properties: - clientPublicKey: + description: The id of the `Customer` who holds this card. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCardId: type: string - pattern: ^04[0-9a-fA-F]{128}$ - minLength: 130 - maxLength: 130 - description: Required for `PASSKEY` credentials. Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid bakes this key into the Turnkey session-creation payload that the returned `challenge` is computed from, so the resulting session signing key is sealed to the client. Ignored for `EMAIL_OTP`. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - PasskeyAuthChallenge: - title: Passkey Auth Challenge - description: Extended `AuthMethod` shape returned for `PASSKEY` credentials from `POST /auth/credentials/{id}/challenge`. Includes the WebAuthn `credentialId` needed to target the passkey, plus the Grid-issued `challenge`, corresponding `requestId`, and challenge `expiresAt`. The `challenge` value is the lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body, not a base64url string. The client UTF-8 encodes this string as the WebAuthn challenge and signs it with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. - allOf: - - $ref: '#/components/schemas/AuthMethod' - - type: object - required: - - credentialId - - challenge - - requestId - - expiresAt - properties: - credentialId: - type: string - description: Base64url-encoded WebAuthn credential identifier for this passkey. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. - example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew - challenge: - type: string - description: Lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body for the pending passkey authentication. Do not base64url-decode this field; pass UTF-8 bytes of the string (for example, `new TextEncoder().encode(challenge)`) as the WebAuthn challenge to `navigator.credentials.get()`. Single-use; a new challenge is issued on the next call to `POST /auth/credentials/{id}/challenge`. - example: 6b35a4c41d9aa7a2a0e742f9f9e7a1c2d65a2db33a3fb748f6d4f1ce78d9a729 - requestId: - type: string - description: Grid-issued `Request:` identifier for this pending passkey authentication request. Echo this value exactly as the `Request-Id` header on the subsequent `POST /auth/credentials/{id}/verify` call so Grid can correlate the assertion with the issued challenge. - example: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 - expiresAt: - type: string - format: date-time - description: Timestamp after which the issued challenge is no longer valid. The assertion must reach `POST /auth/credentials/{id}/verify` before this time; otherwise the client must request a fresh challenge via `POST /auth/credentials/{id}/challenge`. - example: '2026-04-08T15:35:00Z' - AuthCredentialResponseOneOf: - title: Auth Credential Response - description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. - oneOf: - - $ref: '#/components/schemas/AuthMethodResponse' - - $ref: '#/components/schemas/PasskeyAuthChallenge' - discriminator: - propertyName: type - mapping: - EMAIL_OTP: '#/components/schemas/AuthMethodResponse' - PASSKEY: '#/components/schemas/PasskeyAuthChallenge' - SessionListResponse: + description: Platform-specific card identifier. Optional on create — system-generated if omitted, mirroring `platformCustomerId` semantics. + example: card-emp-aary-001 + state: + $ref: '#/components/schemas/CardState' + stateReason: + anyOf: + - $ref: '#/components/schemas/CardStateReason' + - type: 'null' + description: Reason associated with the current `state`. Populated when the card is `CLOSED` or when provisioning was rejected; otherwise null. + brand: + $ref: '#/components/schemas/CardBrand' + form: + $ref: '#/components/schemas/CardForm' + last4: + type: string + description: Last four digits of the card PAN. + example: '4242' + expMonth: + type: integer + minimum: 1 + maximum: 12 + description: Card expiration month (1–12). + example: 12 + expYear: + type: integer + description: Card expiration year (four digits). + example: 2029 + panEmbedUrl: + type: string + format: uri + description: URL of the card issuer's iframe that securely displays the PAN, CVV, and expiry to the cardholder. The full PAN and CVV never cross Grid's servers — render this URL in an iframe in your client to reveal card details. + example: https://embed.lithic.com/iframe/...?t=... + fundingSources: + type: array + description: Internal account ids bound to this card as funding sources, in priority order — the first entry is tried first by Authorization Decisioning. Every card has at least one funding source. + items: + type: string + example: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 + currency: + type: string + description: Currency the card transacts in (ISO 4217 for fiat, tickers for crypto). Derived from the funding sources at issue time — all funding sources bound to a card must be denominated in the same card-eligible currency. + example: USD + readOnly: true + issuerRef: + type: string + description: Opaque identifier for the card on the underlying issuer. Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. + example: lithic_card_4f8d3a2b1c + readOnly: true + createdAt: + type: string + format: date-time + description: Creation timestamp + readOnly: true + example: '2026-05-08T14:10:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + readOnly: true + example: '2026-05-08T14:11:00Z' + CardListResponse: type: object required: - data + - hasMore properties: data: type: array - description: List of active authentication sessions for the internal account. + description: List of cards matching the filter criteria items: - $ref: '#/components/schemas/AuthSession' - AuthSessionRefreshRequest: - title: Auth Session Refresh Request - description: Request body for refreshing an active authentication session. The `clientPublicKey` is required on both steps of the signed-retry flow. On the initial call, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the signed retry, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. + $ref: '#/components/schemas/Card' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of cards matching the criteria (excluding pagination) + CardCreateRequest: type: object required: - - clientPublicKey + - cardholderId + - form + - fundingSources properties: - clientPublicKey: + cardholderId: type: string - pattern: ^04[0-9a-fA-F]{128}$ - description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the initial call and seals the returned `encryptedSessionSigningKey` to it on the signed retry. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - AgentPermission: - type: string - enum: - - VIEW_TRANSACTIONS - - CREATE_TRANSFERS - - CREATE_QUOTES - - EXECUTE_QUOTES - - MANAGE_EXTERNAL_ACCOUNTS - description: 'Permission granted to an agent that determines what actions it can perform. VIEW_TRANSACTIONS: Can list and retrieve transactions and account balances. CREATE_TRANSFERS: Can initiate same-currency transfers. CREATE_QUOTES: Can create cross-currency quotes. EXECUTE_QUOTES: Can execute cross-currency quotes. MANAGE_EXTERNAL_ACCOUNTS: Can create and manage external accounts.' - AgentExecutionMode: - type: string - enum: - - AUTO - - APPROVAL_REQUIRED - description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' - AgentSpendingLimits: + description: The id of the `Customer` to issue the card to. The customer must have KYC status `APPROVED`; otherwise the request is rejected with `CARDHOLDER_KYC_NOT_APPROVED`. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCardId: + type: string + description: Optional platform-specific card identifier. System-generated when omitted, mirroring `platformCustomerId` semantics. + example: card-emp-aary-001 + form: + $ref: '#/components/schemas/CardForm' + fundingSources: + type: array + description: Internal account ids to bind as funding sources, in priority order. The first entry is tried first by Authorization Decisioning. Every card must be bound to at least one source, and every source must belong to the cardholder and be denominated in a card-eligible currency (USDB in v1); otherwise the request is rejected with `FUNDING_SOURCE_INELIGIBLE`. + minItems: 1 + items: + type: string + example: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + CardUpdateRequest: type: object - description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. - required: - - currency - - perTransactionLimit + description: Update request for `PATCH /cards/{id}`. At least one of `state` or `fundingSources` must be supplied. `state` transitions are limited to `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`; any other transition returns `409 INVALID_STATE_TRANSITION`. `CLOSED` is terminal and irreversible and cannot be combined with `fundingSources`. `fundingSources`, when supplied, fully replaces the card's bound funding sources — the array order determines the priority Authorization Decisioning tries them in. properties: - currency: + state: type: string - description: ISO 4217 currency code that all amount limits are denominated in. - example: USD - perTransactionLimit: - type: integer - description: Maximum amount the agent can transfer in a single transaction. - example: 50000 - dailyLimit: - type: - - integer - - 'null' - description: Maximum total amount the agent can transfer per day. Null means no daily limit. - example: 500000 - dailyTransactionLimit: - type: integer - description: Maximum number of transactions the agent can initiate per day. - example: 10 - monthlyLimit: - type: - - integer - - 'null' - description: Maximum total amount the agent can transfer per month. Null means no monthly limit. - example: 5000000 - AgentAccountRule: + enum: + - ACTIVE + - FROZEN + - CLOSED + description: Target state for the card. Permitted transitions are `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`. `CLOSED` is terminal and irreversible; once closed, the card stays in the system for audit and reconciliation but cannot transact again. + example: FROZEN + fundingSources: + type: array + description: 'New ordered list of internal account ids to bind as funding sources. Fully replaces the previous binding. Each id must belong to the cardholder and be denominated in the card''s currency. The list must contain at least one source — to stop a card from spending without removing all sources, transition it to `FROZEN` instead. Cannot be supplied alongside `state: CLOSED`.' + minItems: 1 + items: + type: string + example: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 + CardMerchant: type: object - description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: - - accountId + - descriptor properties: - accountId: + descriptor: type: string - description: The internal account ID this rule applies to. - example: Account:019542f5-b3e7-1d02-0000-000000000001 - executionMode: - $ref: '#/components/schemas/AgentExecutionMode' - perTransactionLimit: - type: - - integer - - 'null' - description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. - example: 10000 - AgentAccountRestrictions: + description: Merchant descriptor string captured from the card network at authorization time. + example: BLUE BOTTLE COFFEE SF + mcc: + type: string + description: Merchant Category Code (ISO 18245) — four-digit numeric string. + example: '5814' + country: + type: string + description: Two-letter ISO 3166-1 alpha-2 country code of the merchant. + example: US + SandboxCardAuthorizationRequest: type: object - description: Optional restrictions that limit the agent to specific accounts or override policy per account. + required: + - amount + - currency + - merchant + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/authorization`. Drives the same internal authorization + reconcile paths that the issuer would call in production. The decisioning outcome is controlled by the last three characters of `merchant.descriptor` — see the endpoint documentation for the suffix table. properties: - allowedAccountIds: - type: - - array - - 'null' - description: If set, restricts the agent to operate only on the specified internal account IDs. Null means the agent can access all accounts. - items: - type: string - example: Account:019542f5-b3e7-1d02-0000-000000000001 - accountRules: - type: array - description: Per-account rules that override the agent's default policy for specific accounts. - items: - $ref: '#/components/schemas/AgentAccountRule' - AgentApprovalThresholds: + amount: + type: integer + format: int64 + description: Authorization amount in the smallest unit of `currency` (e.g. cents for USD). + exclusiveMinimum: 0 + example: 1250 + currency: + $ref: '#/components/schemas/Currency' + merchant: + $ref: '#/components/schemas/CardMerchant' + CardTransactionStatus: + type: string + enum: + - AUTHORIZED + - PARTIALLY_SETTLED + - SETTLED + - REFUNDED + - EXCEPTION + description: | + Lifecycle status of a card transaction. + + | Status | Description | + |--------|-------------| + | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | + | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | + | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. | + | `REFUNDED` | A `RETURN` was received from the merchant; the net settled amount has been refunded in part or whole. | + | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. | + CardPullSummary: type: object - description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. + required: + - count + - totalAmount properties: - currency: - type: string - description: ISO 4217 currency code that the amount threshold is denominated in. Required when amount is set. - example: USD - amount: - type: - - integer - - 'null' - description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. - example: 100000 - AgentPolicy: + count: + type: integer + description: Total number of pulls (debits) executed against the funding source for this transaction. `> 1` indicates one or more post-hoc pulls — e.g. restaurant tip / over-auth clearings. + example: 2 + totalAmount: + type: integer + format: int64 + description: Sum of all pull amounts in the smallest unit of the funding source's currency. + example: 1500 + pendingCount: + type: integer + description: Number of pulls still in the `PENDING` state. Drops to zero when every pull has reached a terminal state. Non-zero values that persist beyond the expected settlement window are an early signal for the `EXCEPTION` path. + example: 0 + CardRefundSummary: type: object - description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: - - permissions - - defaultExecutionMode - - spendingLimits + - count + - totalAmount properties: - permissions: - type: array - description: List of permissions granted to the agent. - items: - $ref: '#/components/schemas/AgentPermission' - defaultExecutionMode: - $ref: '#/components/schemas/AgentExecutionMode' - spendingLimits: - $ref: '#/components/schemas/AgentSpendingLimits' - accountRestrictions: - $ref: '#/components/schemas/AgentAccountRestrictions' - approvalThresholds: - $ref: '#/components/schemas/AgentApprovalThresholds' - AgentUsage: + count: + type: integer + description: Number of refund (return) events received for this transaction. + example: 0 + totalAmount: + type: integer + format: int64 + description: Sum of all refund amounts in the smallest unit of the funding source's currency. + example: 0 + CardSettlementSummary: type: object - description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: - - dailyTransactionCount - - dailySpend - - monthlySpend + - count + - totalAmount properties: - dailyTransactionCount: - type: integer - description: Number of transactions initiated by the agent today. - example: 3 - dailySpend: + count: type: integer - description: Total amount spent by the agent today, in the smallest unit of the policy's `spendingLimits.currency`. - example: 150000 - dailyResetDate: - type: string - format: date - description: The date when daily usage counters will reset. - example: '2025-07-22' - monthlySpend: + description: Number of settlement (clearing) events received for this transaction. + example: 1 + totalAmount: type: integer - description: Total amount spent by the agent this month, in the smallest unit of the policy's `spendingLimits.currency`. - example: 750000 - monthlyResetMonth: - type: string - description: The year-month (YYYY-MM) when monthly usage counters will reset. - example: 2025-08 - Agent: + format: int64 + description: Sum of all settled amounts in the smallest unit of the funding source's currency. + example: 1500 + CardTransaction: type: object - description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: - id - - name - - customerId - - isPaused - - isConnected - - policy - - usage + - cardId + - status + - merchant + - authorizedAmount + - accountId + - pullSummary + - refundSummary + - settlementSummary + - authorizedAt - createdAt - updatedAt + description: Parent transaction row for a card authorization and all of the pulls / settlements / refunds that reconcile against it. Child events are rolled up into the `pullSummary`, `refundSummary`, and `settlementSummary` aggregates. Delivered as the payload of the generic transaction webhook stream (extends the Transaction model with a card destination type) on every transition. properties: id: type: string - description: System-generated unique identifier for the agent. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - name: + description: System-generated unique card transaction identifier + readOnly: true + example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + cardId: type: string - description: Human-readable name for the agent. - example: Payroll Automation Agent - customerId: + description: The id of the `Card` this transaction was made on. + example: Card:019542f5-b3e7-1d02-0000-000000000010 + issuerTransactionToken: type: string - description: The ID of the customer this agent operates on behalf of. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - isPaused: - type: boolean - description: Whether the agent is currently paused. Paused agents cannot initiate any actions. - example: false - isConnected: - type: boolean - description: Whether the agent has been installed and connected (i.e., its device code has been redeemed). - example: true - policy: - $ref: '#/components/schemas/AgentPolicy' - usage: - $ref: '#/components/schemas/AgentUsage' + description: Opaque identifier for the transaction on the underlying issuer. Used to cross-reference Grid records against issuer dashboards and webhooks. + example: lithic_txn_b81c2a4f + readOnly: true + status: + $ref: '#/components/schemas/CardTransactionStatus' + merchant: + $ref: '#/components/schemas/CardMerchant' + authorizedAmount: + $ref: '#/components/schemas/CurrencyAmount' + settledAmount: + $ref: '#/components/schemas/CurrencyAmount' + refundedAmount: + $ref: '#/components/schemas/CurrencyAmount' + accountId: + type: string + description: Internal account id that funded this transaction (the funding source selected by Authorization Decisioning at auth time). + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + pullSummary: + $ref: '#/components/schemas/CardPullSummary' + refundSummary: + $ref: '#/components/schemas/CardRefundSummary' + settlementSummary: + $ref: '#/components/schemas/CardSettlementSummary' + authorizedAt: + type: string + format: date-time + description: When the auth was approved. + example: '2026-05-08T14:30:00Z' + lastEventAt: + type: string + format: date-time + description: Timestamp of the most recent reconcile event (pull / clearing / refund) against this transaction. + example: '2026-05-08T15:42:11Z' createdAt: type: string format: date-time - description: Creation timestamp. - example: '2025-07-21T17:32:28Z' + description: Creation timestamp (same as `authorizedAt` for card transactions). + readOnly: true + example: '2026-05-08T14:30:00Z' updatedAt: type: string format: date-time description: Last update timestamp. - example: '2025-07-21T17:32:28Z' - AgentListResponse: + readOnly: true + example: '2026-05-08T15:42:11Z' + SandboxCardClearingRequest: type: object required: - - data - - hasMore + - cardTransactionId + - amount + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/clearing`. Drives a clearing event against an existing `CardTransaction`. Pass an `amount` greater than the authorized amount to exercise the over-auth / restaurant-tip post-hoc-pull path; pass `0` to exercise `AUTHORIZATION_EXPIRY`. Suffix-driven outcomes on the parent transaction's id govern whether the post-hoc pull succeeds. properties: - data: - type: array - description: List of agents matching the filter criteria. - items: - $ref: '#/components/schemas/Agent' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page. - nextCursor: + cardTransactionId: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true). - totalCount: + description: The id of the `CardTransaction` to clear against. Must be in `AUTHORIZED` or `PARTIALLY_SETTLED` state. + example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + amount: type: integer - description: Total number of agents matching the criteria (excluding pagination). - AgentCreateRequest: - type: object - required: - - name - - customerId - - policy - properties: - name: - type: string - description: Human-readable name to identify the agent. - example: Payroll Automation Agent - customerId: - type: string - description: The ID of the customer this agent will operate on behalf of. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - policy: - $ref: '#/components/schemas/AgentPolicy' - AgentDeviceCode: - type: object - required: - - code - - agentId - - expiresAt - - redeemed - properties: - code: - type: string - description: Human-readable device code used to install and connect the agent software. - example: GRID-AGENT-X7K9-M2P4 - agentId: - type: string - description: The agent this device code belongs to. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - expiresAt: - type: string - format: date-time - description: Timestamp when this device code expires. - example: '2025-07-22T17:32:28Z' - redeemed: - type: boolean - description: Whether this device code has already been redeemed by the agent. - example: false - AgentCreateResponse: - type: object - description: Response returned when an agent is created, including the agent and a device code for installation. - required: - - agent - - deviceCode - properties: - agent: - $ref: '#/components/schemas/Agent' - deviceCode: - $ref: '#/components/schemas/AgentDeviceCode' - AgentActionStatus: - type: string - enum: - - PENDING_APPROVAL - - APPROVED - - REJECTED - - FAILED - description: | - Status of an agent action. - - | Status | Description | - |--------|-------------| - | `PENDING_APPROVAL` | Submitted by the agent, awaiting platform approval before execution | - | `APPROVED` | Approved by the platform; execution is in progress or completed | - | `REJECTED` | Rejected by the platform; the underlying transaction was not executed | - | `FAILED` | Approved but execution failed (e.g. quote expired, insufficient funds) | - AgentActionType: - type: string - enum: - - EXECUTE_QUOTE - - TRANSFER_OUT - - TRANSFER_IN - description: | - The type of action the agent is requesting. - - | Type | Description | - |------|-------------| - | `EXECUTE_QUOTE` | Execute a cross-currency quote | - | `TRANSFER_OUT` | Transfer from an internal account to an external account | - | `TRANSFER_IN` | Transfer from an external account to an internal account | - AgentTransferDetails: + format: int64 + description: Clearing amount in the smallest unit of the transaction's currency. Set to `0` to simulate an authorization expiry with no clearing. + minimum: 0 + example: 1500 + SandboxCardReturnRequest: type: object - description: Details of a transfer-type agent action (TRANSFER_OUT or TRANSFER_IN). required: + - cardTransactionId - amount - - currency - - sourceAccountId - - destinationAccountId - properties: - amount: - type: integer - format: int64 - description: Transfer amount in the smallest unit of the specified currency. - example: 50000 - currency: - type: string - description: ISO 4217 currency code for the transfer amount. - example: USD - sourceAccountId: - type: string - description: ID of the source account (internal or external). - example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - destinationAccountId: + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and pushes the parent transaction towards `REFUNDED` (full) or keeps it `SETTLED` (partial). + properties: + cardTransactionId: type: string - description: ID of the destination account (internal or external). - example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - AgentAction: + description: The id of the `CardTransaction` to refund against. Must have at least one settled clearing. + example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + amount: + type: integer + format: int64 + description: Return amount in the smallest unit of the transaction's currency. Must be less than or equal to the net settled amount (settled minus previously-refunded). + exclusiveMinimum: 0 + example: 1500 + StablecoinProvider: + type: string + enum: + - BRALE + description: Stablecoin provider backing the linked account, stablecoin, or operation. + StablecoinProviderAccountStatus: + type: string + enum: + - ACTIVE + - INVALID + - REVOKED + description: Status of the linked stablecoin provider account credentials. + StablecoinProviderEnvironment: + type: string + enum: + - SANDBOX + - PRODUCTION + description: Provider environment derived from the authenticated Grid platform mode. + StablecoinProviderAccount: type: object - description: An action submitted by an agent that may require platform approval before execution. All agent-initiated operations (quote execution, transfers) are represented as AgentActions, giving the platform a consistent object to approve, reject, and audit regardless of the underlying operation type. required: - id - - agentId - - customerId - - platformCustomerId + - provider + - providerAccountId + - providerEnvironment - status - - type - createdAt - updatedAt properties: id: type: string - description: System-generated unique identifier for this action. - example: AgentAction:019542f5-b3e7-1d02-0000-000000000099 - agentId: - type: string - description: The agent that submitted this action. - example: Agent:019542f5-b3e7-1d02-0000-000000000042 - customerId: - type: string - description: The customer on whose behalf the action was submitted. - example: Customer:019542f5-b3e7-1d02-0000-000000000010 - platformCustomerId: + description: System-generated stablecoin provider account link identifier. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + provider: + $ref: '#/components/schemas/StablecoinProvider' + providerAccountId: type: string - description: Platform-specific ID of the customer. - example: user-a1b2c3 + description: Provider account id. + example: 2VcUIonJeVQzFoBuC7LdFT0dRe4 + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' status: - $ref: '#/components/schemas/AgentActionStatus' - type: - $ref: '#/components/schemas/AgentActionType' - quote: - allOf: - - $ref: '#/components/schemas/Quote' - description: The quote being executed. Populated for `EXECUTE_QUOTE` actions; absent for transfer actions. Contains the full amount, currency, destination, and rate details needed to present an approval decision to the user. - transferDetails: - allOf: - - $ref: '#/components/schemas/AgentTransferDetails' - description: Details of the transfer being requested. Populated for `TRANSFER_OUT` and `TRANSFER_IN` actions; absent for `EXECUTE_QUOTE` actions. - transaction: - allOf: - - $ref: '#/components/schemas/TransactionOneOf' - description: The resulting transaction, populated once the action has been approved and execution has begun. Absent while the action is `PENDING_APPROVAL` or `REJECTED`. - rejectionReason: + $ref: '#/components/schemas/StablecoinProviderAccountStatus' + lastVerifiedAt: type: string - description: Human-readable reason provided by the platform when rejecting the action. Only present when status is `REJECTED`. - example: Transaction amount exceeds customer's current risk limit. + format: date-time + description: Timestamp of the last successful provider credential verification. + example: '2026-05-20T16:35:00Z' createdAt: type: string format: date-time - description: When the action was submitted by the agent. - example: '2025-10-03T15:00:00Z' + description: Creation timestamp. + example: '2026-05-20T16:35:00Z' updatedAt: type: string format: date-time - description: When the action was last updated. - example: '2025-10-03T15:02:00Z' - AgentActionListResponse: + description: Last update timestamp. + example: '2026-05-20T16:35:00Z' + StablecoinProviderAccountListResponse: type: object required: - data @@ -18285,252 +19750,349 @@ components: properties: data: type: array - description: List of agent actions matching the filter criteria. items: - $ref: '#/components/schemas/AgentAction' + $ref: '#/components/schemas/StablecoinProviderAccount' hasMore: type: boolean description: Indicates if more results are available beyond this page. nextCursor: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true). + description: Cursor to retrieve the next page of results. totalCount: type: integer - description: Total number of actions matching the criteria (excluding pagination). - AgentUpdateRequest: + description: Total number of stablecoin provider account links matching the criteria. + StablecoinProviderAccountLinkRequest: type: object - description: Partial update to an agent's basic fields. At least one field must be provided. + required: + - provider + - apiClientId + - apiClientSecret properties: - name: + provider: + $ref: '#/components/schemas/StablecoinProvider' + apiClientId: type: string - description: Updated name for the agent. - example: Updated Payroll Agent - isPaused: - type: boolean - description: Set to true to pause the agent or false to resume it. - example: true - AgentSpendingLimitsUpdate: + description: Provider API client id used to verify and link the provider account. + example: provider_client_123 + apiClientSecret: + type: string + writeOnly: true + description: Provider API client secret. Grid verifies and stores this secret encrypted; it is never returned. + example: provider_secret_456 + providerAccountId: + type: string + description: Provider account id. Optional when the submitted credentials expose exactly one provider account. + example: 2VcUIonJeVQzFoBuC7LdFT0dRe4 + StablecoinIssuanceStatus: + type: string + enum: + - PENDING_REVIEW + - PROVISIONING + - PROVISIONED + - REJECTED + - FAILED + description: Provider issuance/linking status for the registered stablecoin. + StablecoinGridOperationsStatus: + type: string + enum: + - NOT_ENABLED + - PENDING_APPROVAL + - ENABLING + - ENABLED + - DISABLED + description: Whether the stablecoin has been enabled for normal Grid operations. + StablecoinNetwork: + type: string + enum: + - SPARK_MAINNET + description: Network namespace for the stablecoin token identifier. + Stablecoin: type: object - description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. + required: + - id + - name + - symbol + - baseCurrency + - network + - decimals + - issuanceStatus + - gridOperationsStatus + - networkTokenIdentifier + - provider + - stablecoinProviderAccountId + - providerEnvironment + - providerTokenIdentifier + - createdAt + - updatedAt properties: - currency: + id: type: string - description: ISO 4217 currency code that all amount limits are denominated in. Updating this recasts all existing limits into the new currency denomination. + description: System-generated stablecoin identifier. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + name: + type: string + description: Stablecoin display name. + example: Acme Dollar + symbol: + type: string + description: Stablecoin symbol. + example: ACME + baseCurrency: + type: string + description: Fiat currency the stablecoin is denominated against. example: USD - perTransactionLimit: - type: integer - description: Maximum amount per transaction. - example: 50000 - dailyLimit: - type: - - integer - - 'null' - description: Maximum daily spend. Set to null to remove the daily limit. - example: 500000 - dailyTransactionLimit: + network: + $ref: '#/components/schemas/StablecoinNetwork' + decimals: type: integer - description: Maximum number of transactions per day. - example: 10 - monthlyLimit: - type: - - integer - - 'null' - description: Maximum monthly spend. Set to null to remove the monthly limit. - example: 5000000 - AgentPolicyUpdateRequest: - type: object - description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. - properties: - permissions: - type: array - description: Updated list of permissions. Replaces the entire permissions list when provided. - items: - $ref: '#/components/schemas/AgentPermission' - defaultExecutionMode: - $ref: '#/components/schemas/AgentExecutionMode' - spendingLimits: - $ref: '#/components/schemas/AgentSpendingLimitsUpdate' - accountRestrictions: - $ref: '#/components/schemas/AgentAccountRestrictions' - approvalThresholds: - $ref: '#/components/schemas/AgentApprovalThresholds' - AgentActionRejectRequest: - type: object - properties: - reason: + description: Number of decimal places used by the stablecoin. + example: 6 + issuanceStatus: + $ref: '#/components/schemas/StablecoinIssuanceStatus' + gridOperationsStatus: + $ref: '#/components/schemas/StablecoinGridOperationsStatus' + networkTokenIdentifier: + type: string + description: Token identifier in the namespace selected by `network`. + example: btkn1qw508d6qejxtdg4y5r3zarvary0c5xw7k + currency: type: string - description: Optional human-readable reason for the rejection, stored on the action and visible to the platform. - example: Transaction amount exceeds customer's current risk limit. - AgentDeviceCodeStatusResponse: + description: Grid currency code after the stablecoin is enabled for Grid operations. + example: ACME + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link selected for this stablecoin. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + providerTokenIdentifier: + type: string + description: Provider token identifier. For Brale this maps to `value_type`. + example: ACME + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T16:40:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:10:00Z' + StablecoinListResponse: type: object required: - - code - - redeemed + - data + - hasMore properties: - code: - type: string - description: The device code. - example: GRID-AGENT-X7K9-M2P4 - redeemed: + data: + type: array + items: + $ref: '#/components/schemas/Stablecoin' + hasMore: type: boolean - description: Whether this device code has been redeemed. - example: false - AgentDeviceCodeRedeemResponse: + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results. + totalCount: + type: integer + description: Total number of stablecoins matching the criteria. + StablecoinRegisterRequest: type: object required: - - agentId - - agentName - - accessToken - - policy + - providerTokenIdentifier + - networkTokenIdentifier + - network properties: - agentId: + providerTokenIdentifier: type: string - description: The agent's system-generated ID. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - agentName: + description: Provider identifier for the stablecoin. For Brale this maps to `value_type`. + example: ACME + networkTokenIdentifier: type: string - description: The agent's name. - example: Payroll Automation Agent - accessToken: + description: Token identifier in the namespace selected by `network`. + example: btkn1qw508d6qejxtdg4y5r3zarvary0c5xw7k + network: + $ref: '#/components/schemas/StablecoinNetwork' + stablecoinProviderAccountId: type: string - description: 'Bearer token used to authenticate all subsequent API calls as this agent. Pass as `Authorization: Bearer `. This token is returned only once and must be stored securely — it cannot be retrieved again.' - example: gat_ed0ad25881e234cc28fb2dec0a4fe64e4172a3b9 - policy: - $ref: '#/components/schemas/AgentPolicy' - CardState: + description: Provider account link to register against. Optional when exactly one active link exists for the authenticated platform; required to resolve STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED when multiple links exist. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + StablecoinExternalAccountType: type: string enum: - - PENDING_KYC - - PENDING_ISSUE - - ACTIVE - - FROZEN - - CLOSED - description: | - Lifecycle state of a card. - - | State | Description | - |-------|-------------| - | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this state cannot transact. | - | `PENDING_ISSUE` | The card has been requested and is being provisioned with the issuer. | - | `ACTIVE` | The card is live and can authorize transactions. | - | `FROZEN` | The card is temporarily disabled by the platform. New authorizations are declined with `CARD_PAUSED`. Existing settlements and refunds continue to reconcile. | - | `CLOSED` | The card is permanently closed. Terminal, irreversible state. | - CardStateReason: + - US_BANK_ACCOUNT + description: External account type supported for stablecoin provider linking. + StablecoinTransferType: type: string enum: - - ISSUER_REJECTED - - CLOSED_BY_PLATFORM - - CLOSED_BY_GRID - description: | - Reason a card reached a terminal or non-active state. Present on - `CLOSED` cards, and on cards that fail provisioning before reaching - `ACTIVE`. - - | Reason | Description | - |--------|-------------| - | `ISSUER_REJECTED` | The card issuer rejected provisioning during `PENDING_ISSUE`. | - | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`state: CLOSED`) by the platform. | - | `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or risk action). | - CardBrand: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Provider-supported transfer type for stablecoin funding or redemption. + StablecoinExternalAccountOwner: + type: object + required: + - legalName + properties: + legalName: + type: string + description: Legal name of the account owner. + example: Acme Inc + emailAddress: + type: string + format: email + description: Email address for the account owner. + example: finance@example.com + phoneNumber: + type: string + description: Phone number for the account owner. + example: '+14155550100' + dateOfBirth: + type: string + format: date + description: Date of birth when required by the provider link flow. + example: '1990-01-01' + StablecoinExternalAccountLinkSessionCreateRequest: + type: object + required: + - provider + - accountType + - requestedTransferTypes + - owner + properties: + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link that should own the linked external account. Optional when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + requestedTransferTypes: + type: array + items: + $ref: '#/components/schemas/StablecoinTransferType' + owner: + $ref: '#/components/schemas/StablecoinExternalAccountOwner' + StablecoinExternalAccountLinkSession: + type: object + required: + - id + - provider + - stablecoinProviderAccountId + - accountType + - linkToken + - expiresAt + - createdAt + properties: + id: + type: string + description: System-generated stablecoin external-account link-session identifier. + example: StablecoinExternalAccountLinkSession:019542f5-b3e7-1d02-0000-000000000003 + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link selected for this session. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + linkToken: + type: string + description: Provider/Plaid frontend token for the link flow. + example: link-sandbox-123 + expiresAt: + type: string + format: date-time + description: Link token expiration timestamp. + example: '2026-05-20T18:20:00Z' + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:20:00Z' + StablecoinExternalAccountStatus: type: string enum: - - VISA - - MASTERCARD - description: | - Card network brand. Read-only — determined by Grid when the card is - provisioned with the issuer. - CardForm: + - ACTIVE + - INACTIVE + - NEEDS_UPDATE + - FAILED + description: Status of a provider-linked stablecoin external account. NEEDS_UPDATE indicates the provider link requires attention (for example Plaid reauthentication). + StablecoinExternalAccountCreationMethod: type: string enum: - - VIRTUAL - description: | - Physical form factor of the card. Only `VIRTUAL` is supported in v1; - `PHYSICAL` will be added in a later release. - Card: + - GRID_EXTERNAL_ACCOUNT + - PLAID + - DIRECT_BANK_ENTRY + description: How the stablecoin external account was linked. + StablecoinExternalAccount: type: object required: - id - - cardholderId - - state - - form - - fundingSources + - provider + - stablecoinProviderAccountId + - providerEnvironment + - accountType + - creationMethod + - status + - supportedTransferTypes - createdAt - updatedAt properties: id: type: string - description: System-generated unique card identifier - readOnly: true - example: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: - type: string - description: The id of the `Customer` who holds this card. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: - type: string - description: Platform-specific card identifier. Optional on create — system-generated if omitted, mirroring `platformCustomerId` semantics. - example: card-emp-aary-001 - state: - $ref: '#/components/schemas/CardState' - stateReason: - anyOf: - - $ref: '#/components/schemas/CardStateReason' - - type: 'null' - description: Reason associated with the current `state`. Populated when the card is `CLOSED` or when provisioning was rejected; otherwise null. - brand: - $ref: '#/components/schemas/CardBrand' - form: - $ref: '#/components/schemas/CardForm' - last4: + description: System-generated stablecoin external account identifier. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: type: string - description: Last four digits of the card PAN. - example: '4242' - expMonth: - type: integer - minimum: 1 - maximum: 12 - description: Card expiration month (1–12). - example: 12 - expYear: - type: integer - description: Card expiration year (four digits). - example: 2029 - panEmbedUrl: + description: Stablecoin provider account link for this external account. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + creationMethod: + $ref: '#/components/schemas/StablecoinExternalAccountCreationMethod' + status: + $ref: '#/components/schemas/StablecoinExternalAccountStatus' + gridExternalAccountId: type: string - format: uri - description: URL of the card issuer's iframe that securely displays the PAN, CVV, and expiry to the cardholder. The full PAN and CVV never cross Grid's servers — render this URL in an iframe in your client to reveal card details. - example: https://embed.lithic.com/iframe/...?t=... - fundingSources: + description: Linked normal Grid external account id, when one exists. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000004 + supportedTransferTypes: type: array - description: Internal account ids bound to this card as funding sources, in priority order — the first entry is tried first by Authorization Decisioning. Every card has at least one funding source. items: - type: string - example: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 - currency: + $ref: '#/components/schemas/StablecoinTransferType' + providerStatus: type: string - description: Currency the card transacts in (ISO 4217 for fiat, tickers for crypto). Derived from the funding sources at issue time — all funding sources bound to a card must be denominated in the same card-eligible currency. - example: USD - readOnly: true - issuerRef: + description: Safe provider status summary. + example: active + lastVerifiedAt: type: string - description: Opaque identifier for the card on the underlying issuer. Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. - example: lithic_card_4f8d3a2b1c - readOnly: true + format: date-time + description: Timestamp of the last successful provider external-account verification. + example: '2026-05-20T17:25:00Z' createdAt: type: string format: date-time - description: Creation timestamp - readOnly: true - example: '2026-05-08T14:10:00Z' + description: Creation timestamp. + example: '2026-05-20T17:25:00Z' updatedAt: type: string format: date-time - description: Last update timestamp - readOnly: true - example: '2026-05-08T14:11:00Z' - CardListResponse: + description: Last update timestamp. + example: '2026-05-20T17:25:00Z' + StablecoinExternalAccountListResponse: type: object required: - data @@ -18538,273 +20100,579 @@ components: properties: data: type: array - description: List of cards matching the filter criteria items: - $ref: '#/components/schemas/Card' + $ref: '#/components/schemas/StablecoinExternalAccount' hasMore: type: boolean - description: Indicates if more results are available beyond this page + description: Indicates if more results are available beyond this page. nextCursor: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) + description: Cursor to retrieve the next page of results. totalCount: type: integer - description: Total number of cards matching the criteria (excluding pagination) - CardCreateRequest: + description: Total number of stablecoin external accounts matching the criteria. + StablecoinExternalAccountGridLinkRequest: type: object required: - - cardholderId - - form - - fundingSources + - creationMethod + - provider + - gridExternalAccountId + - requestedTransferTypes properties: - cardholderId: + creationMethod: type: string - description: The id of the `Customer` to issue the card to. The customer must have KYC status `APPROVED`; otherwise the request is rejected with `CARDHOLDER_KYC_NOT_APPROVED`. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: + enum: + - GRID_EXTERNAL_ACCOUNT + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: type: string - description: Optional platform-specific card identifier. System-generated when omitted, mirroring `platformCustomerId` semantics. - example: card-emp-aary-001 - form: - $ref: '#/components/schemas/CardForm' - fundingSources: + description: Stablecoin provider account link that should own the linked external account. Optional when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + gridExternalAccountId: + type: string + description: Existing Grid external account to link to the provider. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000004 + requestedTransferTypes: type: array - description: Internal account ids to bind as funding sources, in priority order. The first entry is tried first by Authorization Decisioning. Every card must be bound to at least one source, and every source must belong to the cardholder and be denominated in a card-eligible currency (USDB in v1); otherwise the request is rejected with `FUNDING_SOURCE_INELIGIBLE`. - minItems: 1 items: - type: string - example: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - CardUpdateRequest: + $ref: '#/components/schemas/StablecoinTransferType' + StablecoinExternalAccountProviderLinkRequest: type: object - description: Update request for `PATCH /cards/{id}`. At least one of `state` or `fundingSources` must be supplied. `state` transitions are limited to `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`; any other transition returns `409 INVALID_STATE_TRANSITION`. `CLOSED` is terminal and irreversible and cannot be combined with `fundingSources`. `fundingSources`, when supplied, fully replaces the card's bound funding sources — the array order determines the priority Authorization Decisioning tries them in. + required: + - creationMethod + - provider + - linkSessionId + - linkResultToken + - requestedTransferTypes properties: - state: + creationMethod: type: string enum: - - ACTIVE - - FROZEN - - CLOSED - description: Target state for the card. Permitted transitions are `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`. `CLOSED` is terminal and irreversible; once closed, the card stays in the system for audit and reconciliation but cannot transact again. - example: FROZEN - fundingSources: + - PLAID + provider: + $ref: '#/components/schemas/StablecoinProvider' + linkSessionId: + type: string + description: Stablecoin external-account link-session id. + example: StablecoinExternalAccountLinkSession:019542f5-b3e7-1d02-0000-000000000003 + linkResultToken: + type: string + writeOnly: true + description: Provider/Plaid public token returned by the frontend link flow. + example: public-sandbox-123 + requestedTransferTypes: type: array - description: 'New ordered list of internal account ids to bind as funding sources. Fully replaces the previous binding. Each id must belong to the cardholder and be denominated in the card''s currency. The list must contain at least one source — to stop a card from spending without removing all sources, transition it to `FROZEN` instead. Cannot be supplied alongside `state: CLOSED`.' - minItems: 1 items: - type: string - example: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 - CardMerchant: + $ref: '#/components/schemas/StablecoinTransferType' + StablecoinDirectEntryUsBankDetails: type: object required: - - descriptor + - routingNumber + - accountNumber + - accountType + - accountHolderName properties: - descriptor: + routingNumber: type: string - description: Merchant descriptor string captured from the card network at authorization time. - example: BLUE BOTTLE COFFEE SF - mcc: + writeOnly: true + description: US bank routing number. + example: '021000021' + accountNumber: + type: string + writeOnly: true + description: US bank account number. + example: '123456789' + accountType: + type: string + enum: + - CHECKING + - SAVINGS + description: US bank account type. + accountHolderName: + type: string + description: Bank account holder legal name. + example: Acme Inc + institutionName: + type: string + description: Bank/institution display name. + example: Example Bank + beneficiaryAddress: + allOf: + - $ref: '#/components/schemas/Address' + description: Beneficiary postal address. Required by some payout rails (especially WIRE) and when `createGridExternalAccount` is true. + bankAddress: + allOf: + - $ref: '#/components/schemas/Address' + description: Bank branch postal address. Required by some payout rails (especially WIRE). + StablecoinExternalAccountDirectEntryRequest: + type: object + required: + - creationMethod + - provider + - accountType + - requestedTransferTypes + - bankDetails + properties: + creationMethod: + type: string + enum: + - DIRECT_BANK_ENTRY + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link that should own the linked external account. Optional when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + requestedTransferTypes: + type: array + items: + $ref: '#/components/schemas/StablecoinTransferType' + bankDetails: + $ref: '#/components/schemas/StablecoinDirectEntryUsBankDetails' + createGridExternalAccount: + type: boolean + description: Whether Grid should also create a normal Grid external account when the request contains enough data. + example: true + StablecoinExternalAccountLinkRequest: + oneOf: + - $ref: '#/components/schemas/StablecoinExternalAccountGridLinkRequest' + - $ref: '#/components/schemas/StablecoinExternalAccountProviderLinkRequest' + - $ref: '#/components/schemas/StablecoinExternalAccountDirectEntryRequest' + discriminator: + propertyName: creationMethod + mapping: + GRID_EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinExternalAccountGridLinkRequest' + PLAID: '#/components/schemas/StablecoinExternalAccountProviderLinkRequest' + DIRECT_BANK_ENTRY: '#/components/schemas/StablecoinExternalAccountDirectEntryRequest' + StablecoinAmount: + type: string + pattern: ^[1-9][0-9]*$ + description: Amount in the stablecoin's smallest unit, as a base-10 integer string (uint128 range). Strings avoid JavaScript precision loss. Must convert exactly to a provider-representable fiat amount (whole cents for USD). + example: '100000000' + StablecoinWireMintFundingSource: + type: object + required: + - type + properties: + type: + type: string + enum: + - WIRE + StablecoinAchDebitMintFundingSource: + type: object + required: + - type + - stablecoinExternalAccountId + properties: + type: + type: string + enum: + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + stablecoinExternalAccountId: + type: string + description: Linked provider external account to debit. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + StablecoinCryptoNetwork: + type: string + enum: + - ETHEREUM + - SOLANA + - BASE + - POLYGON + - SPARK + - TRON + description: Crypto network used by a provider token-balance funding source. + StablecoinProviderTokenBalanceMintFundingSource: + type: object + required: + - type + - sourceTokenIdentifier + - cryptoNetwork + properties: + type: + type: string + enum: + - PROVIDER_TOKEN_BALANCE + sourceTokenIdentifier: + type: string + description: Provider token/value identifier to fund the mint from. + example: USDC + cryptoNetwork: + $ref: '#/components/schemas/StablecoinCryptoNetwork' + StablecoinMintFundingSource: + oneOf: + - $ref: '#/components/schemas/StablecoinWireMintFundingSource' + - $ref: '#/components/schemas/StablecoinAchDebitMintFundingSource' + - $ref: '#/components/schemas/StablecoinProviderTokenBalanceMintFundingSource' + discriminator: + propertyName: type + mapping: + WIRE: '#/components/schemas/StablecoinWireMintFundingSource' + ACH_DEBIT: '#/components/schemas/StablecoinAchDebitMintFundingSource' + SAME_DAY_ACH_DEBIT: '#/components/schemas/StablecoinAchDebitMintFundingSource' + PROVIDER_TOKEN_BALANCE: '#/components/schemas/StablecoinProviderTokenBalanceMintFundingSource' + StablecoinMintDestination: + type: object + required: + - type + - sparkAddress + properties: + type: + type: string + enum: + - SPARK_ADDRESS + sparkAddress: + type: string + description: Destination Spark address that should receive the minted stablecoin. + example: sp1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq + StablecoinMintQuoteRequest: + type: object + required: + - operationType + - amount + - fundingSource + - destination + properties: + operationType: + type: string + enum: + - MINT + amount: + $ref: '#/components/schemas/StablecoinAmount' + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + destination: + $ref: '#/components/schemas/StablecoinMintDestination' + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Initial mint + StablecoinBurnSource: + type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + accountId: type: string - description: Merchant Category Code (ISO 18245) — four-digit numeric string. - example: '5814' - country: + description: Grid-controlled internal account holding the stablecoin balance to redeem. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000006 + StablecoinPayoutRail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail for a burn/redemption. Debit rails are funding-only and are not valid payout rails. + StablecoinBurnDestination: + type: object + required: + - type + - stablecoinExternalAccountId + - rail + properties: + type: type: string - description: Two-letter ISO 3166-1 alpha-2 country code of the merchant. - example: US - SandboxCardAuthorizationRequest: + enum: + - STABLECOIN_EXTERNAL_ACCOUNT + stablecoinExternalAccountId: + type: string + description: Linked stablecoin external account to receive the fiat redemption. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + rail: + $ref: '#/components/schemas/StablecoinPayoutRail' + StablecoinBurnQuoteRequest: type: object required: + - operationType - amount - - currency - - merchant - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/authorization`. Drives the same internal authorization + reconcile paths that the issuer would call in production. The decisioning outcome is controlled by the last three characters of `merchant.descriptor` — see the endpoint documentation for the suffix table. + - source + - destination properties: + operationType: + type: string + enum: + - BURN amount: - type: integer - format: int64 - description: Authorization amount in the smallest unit of `currency` (e.g. cents for USD). - exclusiveMinimum: 0 - example: 1250 - currency: - $ref: '#/components/schemas/Currency' - merchant: - $ref: '#/components/schemas/CardMerchant' - CardTransactionStatus: + $ref: '#/components/schemas/StablecoinAmount' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + destination: + $ref: '#/components/schemas/StablecoinBurnDestination' + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Redeem ACME + StablecoinQuoteRequest: + oneOf: + - $ref: '#/components/schemas/StablecoinMintQuoteRequest' + - $ref: '#/components/schemas/StablecoinBurnQuoteRequest' + discriminator: + propertyName: operationType + mapping: + MINT: '#/components/schemas/StablecoinMintQuoteRequest' + BURN: '#/components/schemas/StablecoinBurnQuoteRequest' + StablecoinOperationType: type: string enum: - - AUTHORIZED - - PARTIALLY_SETTLED - - SETTLED - - REFUNDED - - EXCEPTION - description: | - Lifecycle status of a card transaction. - - | Status | Description | - |--------|-------------| - | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | - | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | - | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. | - | `REFUNDED` | A `RETURN` was received from the merchant; the net settled amount has been refunded in part or whole. | - | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. | - CardPullSummary: + - MINT + - BURN + description: Stablecoin issuer operation type. + StablecoinQuoteStatus: + type: string + enum: + - OPEN + - EXECUTED + - EXPIRED + - FAILED + description: Current status of the stablecoin quote. + StablecoinFee: type: object required: - - count - - totalAmount + - type + - amount + - currency properties: - count: - type: integer - description: Total number of pulls (debits) executed against the funding source for this transaction. `> 1` indicates one or more post-hoc pulls — e.g. restaurant tip / over-auth clearings. - example: 2 - totalAmount: - type: integer - format: int64 - description: Sum of all pull amounts in the smallest unit of the funding source's currency. - example: 1500 - pendingCount: - type: integer - description: Number of pulls still in the `PENDING` state. Drops to zero when every pull has reached a terminal state. Non-zero values that persist beyond the expected settlement window are an early signal for the `EXCEPTION` path. - example: 0 - CardRefundSummary: + type: + type: string + description: Fee type identifier (for example PROVIDER, GRID, RAIL, NETWORK). + example: PROVIDER + amount: + type: string + pattern: ^[0-9]+$ + description: Fee amount as a base-10 integer string in the smallest unit of `currency`. + example: '0' + currency: + type: string + description: Currency of the fee amount. + example: USD + StablecoinFundingInstructions: type: object + description: Sanitized funding instructions for the selected funding rail. Shape varies by rail; contains only intentionally public deposit coordinates. required: - - count - - totalAmount + - rail properties: - count: - type: integer - description: Number of refund (return) events received for this transaction. - example: 0 - totalAmount: - type: integer - format: int64 - description: Sum of all refund amounts in the smallest unit of the funding source's currency. - example: 0 - CardSettlementSummary: + rail: + $ref: '#/components/schemas/StablecoinTransferType' + additionalProperties: true + StablecoinEstimatedDelivery: type: object + description: Sanitized fiat delivery estimate for a burn/redemption. required: - - count - - totalAmount + - rail + - amount + - currency properties: - count: - type: integer - description: Number of settlement (clearing) events received for this transaction. - example: 1 - totalAmount: - type: integer - format: int64 - description: Sum of all settled amounts in the smallest unit of the funding source's currency. - example: 1500 - CardTransaction: + rail: + $ref: '#/components/schemas/StablecoinPayoutRail' + amount: + type: string + pattern: ^[0-9]+$ + description: Estimated delivery amount as a base-10 integer string in the smallest unit of `currency`. + example: '100000000' + currency: + type: string + description: Currency of the estimated delivery. + example: USD + StablecoinQuote: type: object required: - id - - cardId + - stablecoinId + - operationType - status - - merchant - - authorizedAmount - - accountId - - pullSummary - - refundSummary - - settlementSummary - - authorizedAt + - amount + - expiresAt + - fees - createdAt - - updatedAt - description: Parent transaction row for a card authorization and all of the pulls / settlements / refunds that reconcile against it. Child events are rolled up into the `pullSummary`, `refundSummary`, and `settlementSummary` aggregates. Delivered as the payload of the generic transaction webhook stream (extends the Transaction model with a card destination type) on every transition. properties: id: type: string - description: System-generated unique card transaction identifier - readOnly: true - example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 - cardId: - type: string - description: The id of the `Card` this transaction was made on. - example: Card:019542f5-b3e7-1d02-0000-000000000010 - issuerTransactionToken: + description: System-generated stablecoin quote identifier. + example: StablecoinQuote:019542f5-b3e7-1d02-0000-000000000008 + stablecoinId: type: string - description: Opaque identifier for the transaction on the underlying issuer. Used to cross-reference Grid records against issuer dashboards and webhooks. - example: lithic_txn_b81c2a4f - readOnly: true + description: Stablecoin this quote belongs to. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + operationType: + $ref: '#/components/schemas/StablecoinOperationType' status: - $ref: '#/components/schemas/CardTransactionStatus' - merchant: - $ref: '#/components/schemas/CardMerchant' - authorizedAmount: - $ref: '#/components/schemas/CurrencyAmount' - settledAmount: - $ref: '#/components/schemas/CurrencyAmount' - refundedAmount: - $ref: '#/components/schemas/CurrencyAmount' - accountId: - type: string - description: Internal account id that funded this transaction (the funding source selected by Authorization Decisioning at auth time). - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - pullSummary: - $ref: '#/components/schemas/CardPullSummary' - refundSummary: - $ref: '#/components/schemas/CardRefundSummary' - settlementSummary: - $ref: '#/components/schemas/CardSettlementSummary' - authorizedAt: + $ref: '#/components/schemas/StablecoinQuoteStatus' + amount: + $ref: '#/components/schemas/StablecoinAmount' + expiresAt: type: string format: date-time - description: When the auth was approved. - example: '2026-05-08T14:30:00Z' - lastEventAt: + description: Quote expiration time. Execution rejects expired quotes. + example: '2026-05-20T17:25:00Z' + fees: + type: array + items: + $ref: '#/components/schemas/StablecoinFee' + description: Previewed provider, Grid, rail, or network fees. + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + destination: + description: Quoted destination. For mints this is a Spark address destination; for burns this is a linked stablecoin external account destination. + oneOf: + - $ref: '#/components/schemas/StablecoinMintDestination' + - $ref: '#/components/schemas/StablecoinBurnDestination' + discriminator: + propertyName: type + mapping: + SPARK_ADDRESS: '#/components/schemas/StablecoinMintDestination' + STABLECOIN_EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinBurnDestination' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + fundingInstructions: + $ref: '#/components/schemas/StablecoinFundingInstructions' + estimatedDelivery: + $ref: '#/components/schemas/StablecoinEstimatedDelivery' + operationId: + type: string + description: Operation created by executing this quote, when the quote has been executed. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000007 + description: type: string - format: date-time - description: Timestamp of the most recent reconcile event (pull / clearing / refund) against this transaction. - example: '2026-05-08T15:42:11Z' + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Initial mint createdAt: type: string format: date-time - description: Creation timestamp (same as `authorizedAt` for card transactions). - readOnly: true - example: '2026-05-08T14:30:00Z' + description: Creation timestamp. + example: '2026-05-20T17:20:00Z' updatedAt: type: string format: date-time description: Last update timestamp. - readOnly: true - example: '2026-05-08T15:42:11Z' - SandboxCardClearingRequest: + example: '2026-05-20T17:25:00Z' + StablecoinOperationStatus: + type: string + enum: + - CREATED + - PENDING + - PROCESSING + - COMPLETED + - FAILED + - EXPIRED + description: Current status of the stablecoin operation. EXPIRED applies to wire-funded mints that were never funded within the expiry window. Provider-canceled states map to FAILED with a stable failure reason. + StablecoinOperation: type: object required: - - cardTransactionId + - id + - stablecoinId + - operationType + - status - amount - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/clearing`. Drives a clearing event against an existing `CardTransaction`. Pass an `amount` greater than the authorized amount to exercise the over-auth / restaurant-tip post-hoc-pull path; pass `0` to exercise `AUTHORIZATION_EXPIRY`. Suffix-driven outcomes on the parent transaction's id govern whether the post-hoc pull succeeds. + - provider + - providerEnvironment + - stablecoinProviderAccountId + - createdAt + - updatedAt properties: - cardTransactionId: + id: type: string - description: The id of the `CardTransaction` to clear against. Must be in `AUTHORIZED` or `PARTIALLY_SETTLED` state. - example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + description: System-generated stablecoin operation identifier. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000007 + stablecoinId: + type: string + description: Stablecoin this operation belongs to. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + operationType: + $ref: '#/components/schemas/StablecoinOperationType' + status: + $ref: '#/components/schemas/StablecoinOperationStatus' amount: - type: integer - format: int64 - description: Clearing amount in the smallest unit of the transaction's currency. Set to `0` to simulate an authorization expiry with no clearing. - minimum: 0 - example: 1500 - SandboxCardReturnRequest: + $ref: '#/components/schemas/StablecoinAmount' + quoteId: + type: string + description: Quote that produced this operation. + example: StablecoinQuote:019542f5-b3e7-1d02-0000-000000000008 + provider: + $ref: '#/components/schemas/StablecoinProvider' + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link used by this operation. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + fundingInstructions: + $ref: '#/components/schemas/StablecoinFundingInstructions' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + destination: + description: Stablecoin operation destination. For mints this is a Spark address; for burns this is a linked stablecoin external account. + oneOf: + - $ref: '#/components/schemas/StablecoinMintDestination' + - $ref: '#/components/schemas/StablecoinBurnDestination' + discriminator: + propertyName: type + mapping: + SPARK_ADDRESS: '#/components/schemas/StablecoinMintDestination' + STABLECOIN_EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinBurnDestination' + estimatedDelivery: + $ref: '#/components/schemas/StablecoinEstimatedDelivery' + expiresAt: + type: string + format: date-time + description: Expiry for operations that wait on external funding (wire-funded mints). Past-due unfunded operations transition to EXPIRED. + example: '2026-06-19T17:20:00Z' + providerStatus: + type: string + description: Safe provider status summary. + example: processing + failureReason: + type: string + description: Safe failure reason, when the operation failed. + example: provider_rejected + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description copied from the executed quote. + example: Initial mint + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:30:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:35:00Z' + StablecoinOperationListResponse: type: object required: - - cardTransactionId - - amount - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and pushes the parent transaction towards `REFUNDED` (full) or keeps it `SETTLED` (partial). + - data + - hasMore properties: - cardTransactionId: + data: + type: array + items: + $ref: '#/components/schemas/StablecoinOperation' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: type: string - description: The id of the `CardTransaction` to refund against. Must have at least one settled clearing. - example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 - amount: + description: Cursor to retrieve the next page of results. + totalCount: type: integer - format: int64 - description: Return amount in the smallest unit of the transaction's currency. Must be less than or equal to the net settled amount (settled minus previously-refunded). - exclusiveMinimum: 0 - example: 1500 + description: Total number of stablecoin operations matching the criteria. WebhookType: type: string enum: diff --git a/openapi.yaml b/openapi.yaml index 059e09dd..aad86dfb 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -55,6 +55,8 @@ tags: description: Endpoints called by the agent itself using its own credentials (obtained via device code redemption). Scoped to the agent's associated customer — all requests automatically operate on behalf of that customer and are subject to the agent's policy. When an action requires approval, the resulting transaction enters a pending state and must be approved by the platform via `POST /transactions/{transactionId}/approve`. - name: Cards description: Card management endpoints. Issue debit cards against an internal account, freeze / unfreeze, close, manage card funding sources, and list card transactions. + - name: Stablecoins + description: Stablecoin issuance endpoints. Register provider-created stablecoins, link provider accounts and external bank accounts, create mint/burn quotes, execute them, and track the resulting operations. paths: /config: get: @@ -6864,357 +6866,191 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' -webhooks: - agent-action: + /stablecoin-provider-accounts: post: - summary: Agent action pending approval webhook + summary: Link a stablecoin provider account description: | - Fired when an agent submits an action that requires platform approval before Grid will execute it. Use this to send a push notification to the customer so they can review and approve or reject the action in your app. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - The payload contains the full `AgentAction` — including the embedded quote or transfer details — so you can render the approval UI without a second API call. Approve or reject via `POST /agents/{agentId}/actions/{actionId}/approve` or `POST /agents/{agentId}/actions/{actionId}/reject`. - operationId: agentActionWebhook + Link provider API credentials for the authenticated platform. Provider credentials are account-scoped and can be reused for multiple stablecoins. In V1 the only supported provider is `BRALE`; the provider environment is derived from the authenticated Grid platform mode. + operationId: linkStablecoinProviderAccount tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/AgentActionWebhook' - examples: - pendingApproval: - summary: Agent action pending approval - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000020 - type: AGENT_ACTION.PENDING_APPROVAL - timestamp: '2025-10-03T15:00:00Z' - data: - id: AgentAction:019542f5-b3e7-1d02-0000-000000000099 - agentId: Agent:019542f5-b3e7-1d02-0000-000000000042 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000010 - platformCustomerId: user-a1b2c3 - status: PENDING_APPROVAL - type: EXECUTE_QUOTE - quote: - id: Quote:019542f5-b3e7-1d02-0000-000000000006 - status: PENDING - expiresAt: '2025-10-03T15:00:30Z' - createdAt: '2025-10-03T15:00:00Z' - source: - sourceType: ACCOUNT - accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - sendingCurrency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - receivingCurrency: - code: INR - name: Indian Rupee - symbol: ₹ - decimals: 2 - totalSendingAmount: 50000 - totalReceivingAmount: 4625000 - exchangeRate: 92.5 - feesIncluded: 250 - transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 - createdAt: '2025-10-03T15:00:00Z' - updatedAt: '2025-10-03T15:00:00Z' + $ref: '#/components/schemas/StablecoinProviderAccountLinkRequest' responses: - '200': - description: Webhook received and acknowledged. + '201': + description: Stablecoin provider account linked + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinProviderAccount' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - incoming-payment: - post: - summary: Incoming payment webhook and approval mechanism - description: | - Webhook that is called when an incoming payment is received by a customer's UMA address. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - ### Payment Approval Flow - When a transaction has `status: "PENDING"`, this webhook serves as an approval mechanism: - - 1. The client should check the `counterpartyInformation` against their requirements - 2. To APPROVE the payment synchronously, return a 200 OK response - 3. To REJECT the payment, return a 403 Forbidden response with an Error object - 4. To request more information, return a 422 Unprocessable Entity with specific missing fields - 5. To process the payment asynchronously, return a 202 Accepted response and then call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint within 5 seconds. Note that synchronous approval/rejection is preferred where possible. - - The Grid system will proceed or cancel the payment based on your response. - - For transactions with other statuses (COMPLETED, FAILED, REFUNDED), this webhook is purely informational. - operationId: incomingPaymentWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List stablecoin provider account links + description: Retrieve stablecoin provider account links for the authenticated platform. + operationId: listStablecoinProviderAccounts tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/IncomingPaymentWebhook' - examples: - pendingPayment: - summary: Pending payment example requiring approval - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INCOMING_PAYMENT.PENDING - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: PENDING - type: INCOMING - destination: - destinationType: UMA_ADDRESS - umaAddress: $recipient@uma.domain - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@external.domain - receiverUmaAddress: $recipient@uma.domain - receivedAmount: - amount: 50000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - counterpartyInformation: - FULL_NAME: John Sender - BIRTH_DATE: '1985-06-15' - NATIONALITY: US - reconciliationInstructions: - reference: REF-123456789 - requestedReceiverCustomerInfoFields: - - name: NATIONALITY - mandatory: true - - name: POSTAL_ADDRESS - mandatory: false - incomingCompletedPayment: - summary: Completed payment notification - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INCOMING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: COMPLETED - type: INCOMING - destination: - destinationType: UMA_ADDRESS - umaAddress: $recipient@uma.domain - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@external.domain - receiverUmaAddress: $recipient@uma.domain - receivedAmount: - amount: 50000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: Payment for services - reconciliationInstructions: - reference: REF-123456789 + - BasicAuth: [] + parameters: + - name: provider + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProvider' + - name: status + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProviderAccountStatus' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: | - Webhook received successfully. - For PENDING transactions, this indicates approval to proceed with the payment. - If `requestedReceiverCustomerInfoFields` were present in the webhook request, the corresponding fields for the recipient must be included in this response in the `receiverCustomerInfo` object. + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookResponse' - '202': - description: | - Webhook received and will be processed asynchronously. The synchronous 200 response should be preferred where possible. This asycnhronous path should only be used in - cases where the platform's architecture requires async (but still very quick) processing before approving or rejecting the payment. - The platform must call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint to approve or reject the payment within 5 seconds or the payment will be automatically rejected. + $ref: '#/components/schemas/StablecoinProviderAccountListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '403': - description: | - Forbidden - Payment rejected by the client. - Only applicable for PENDING transactions. + '500': + description: Internal service error content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookForbiddenResponse' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + $ref: '#/components/schemas/Error500' + /stablecoin-provider-accounts/{stablecoinProviderAccountId}: + parameters: + - name: stablecoinProviderAccountId + in: path + description: System-generated stablecoin provider account link identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin provider account link + operationId: getStablecoinProviderAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error409' - '422': - description: | - Unprocessable Entity - Additional counterparty information required. - Only applicable for PENDING transactions. + $ref: '#/components/schemas/StablecoinProviderAccount' + '401': + description: Unauthorized content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookUnprocessableResponse' - outgoing-payment: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin provider account link not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins: post: - summary: Outgoing payment status webhook + summary: Register an existing provider-created stablecoin description: | - Webhook that is called when an outgoing payment's status changes. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - This webhook is informational only and is sent when an outgoing payment completes successfully, fails, or is refunded. - operationId: outgoingPaymentWebhook + Register an existing provider-created stablecoin as a Grid `Stablecoin`. This endpoint links provider token metadata to Grid; it does not create the token with the provider. Grid derives the active provider account link from the authenticated platform, provider, and provider environment. + operationId: registerStablecoin tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/OutgoingPaymentWebhook' - examples: - outgoingCompletedPayment: - summary: Completed outgoing payment - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: OUTGOING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: COMPLETED - type: OUTGOING - source: - sourceType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@uma.domain - receiverUmaAddress: $recipient@external.domain - sentAmount: - amount: 10550 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - receivedAmount: - amount: 9706 - currency: - code: EUR - name: Euro - symbol: € - decimals: 2 - exchangeRate: 0.92 - quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: 'Payment for invoice #1234' - paymentInstructions: [] - rateDetails: - counterpartyMultiplier: 1.08 - counterpartyFixedFee: 10 - gridApiMultiplier: 0.925 - gridApiFixedFee: 10 - gridApiVariableFeeRate: 0.003 - gridApiVariableFeeAmount: 30 - failedPayment: - summary: Failed outgoing payment - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: OUTGOING_PAYMENT.FAILED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000005 - status: FAILED - type: OUTGOING - source: - sourceType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - senderUmaAddress: $sender@uma.domain - receiverUmaAddress: $recipient@external.domain - sentAmount: - amount: 10550 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - createdAt: '2025-08-15T14:25:18Z' - quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 - failureReason: QUOTE_EXECUTION_FAILED + $ref: '#/components/schemas/StablecoinRegisterRequest' responses: - '200': - description: Webhook received successfully + '201': + description: Stablecoin registered + content: + application/json: + schema: + $ref: '#/components/schemas/Stablecoin' '400': description: Bad request content: @@ -7222,219 +7058,163 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: Referenced stablecoin provider account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - test-webhook: - post: - summary: Test webhook for integration verification - description: | - Webhook that is sent once to verify your webhook endpoint is correctly set up. - This is sent when you configure or update your platform settings with a webhook URL. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by the Grid API. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - This webhook is purely for testing your endpoint integration and signature verification. - operationId: testWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List stablecoins + description: Retrieve stablecoins registered to the authenticated platform. + operationId: listStablecoins tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TestWebhookRequest' - examples: - testWebhook: - summary: Test webhook example - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000001 - type: TEST - timestamp: '2025-08-15T14:32:00Z' - data: {} + - BasicAuth: [] + parameters: + - name: issuanceStatus + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinIssuanceStatus' + - name: gridOperationsStatus + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinGridOperationsStatus' + - name: provider + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProvider' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: Webhook received successfully. This confirms your webhook endpoint is properly configured. + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '500': + description: Internal service error content: application/json: schema: - $ref: '#/components/schemas/Error409' - bulk-upload: - post: - summary: Bulk upload status webhook - description: | - Webhook that is called when a bulk customer upload job completes or fails. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - This webhook is sent when a bulk upload job completes or fails, providing detailed information about the results. - operationId: bulkUploadWebhook + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin + operationId: getStablecoin tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/BulkUploadWebhook' - examples: - completedUpload: - summary: Successful bulk upload completion - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: BULK_UPLOAD.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Job:019542f5-b3e7-1d02-0000-000000000006 - status: COMPLETED - progress: - total: 5000 - processed: 5000 - successful: 5000 - failed: 0 - errors: [] - failedUpload: - summary: Failed bulk upload - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: BULK_UPLOAD.FAILED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Job:019542f5-b3e7-1d02-0000-000000000006 - status: FAILED - progress: - total: 5000 - processed: 5000 - successful: 0 - failed: 5000 - errors: - - correlationId: row_1 - error: - code: invalid_csv_format - message: Invalid CSV format - details: - reason: missing_required_column - column: umaAddress + - BasicAuth: [] responses: '200': - description: Webhook received successfully - '400': - description: Bad request + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error400' + $ref: '#/components/schemas/Stablecoin' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '404': + description: Stablecoin not found content: application/json: schema: - $ref: '#/components/schemas/Error409' - invitation-claimed: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-external-account-link-sessions: post: - summary: Invitation claimed webhook - description: | - Webhook that is called when an invitation is claimed by a customer. - This endpoint should be implemented by platform clients of the Grid API. - - When a customer claims an invitation, this webhook is triggered to notify the platform that: - 1. The invitation has been successfully claimed - 2. The invitee UMA address is now associated with the invitation - 3. The invitation status has changed from PENDING to CLAIMED - - This allows platforms to: - - Track invitation usage and conversion rates - - Trigger onboarding flows for new customers who joined via invitation - - Apply referral bonuses or rewards to the inviter - - Update their UI to reflect the claimed status - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: invitationClaimedWebhook + summary: Create a stablecoin external-account link session + description: Create a provider/Plaid link session for linking a bank account to the stablecoin provider. + operationId: createStablecoinExternalAccountLinkSession tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/InvitationClaimedWebhook' - examples: - claimedInvitation: - summary: Invitation claimed notification - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: INVITATION.CLAIMED - timestamp: '2025-09-01T15:45:00Z' - data: - code: 019542f5 - createdAt: '2025-09-01T14:30:00Z' - claimedAt: '2025-09-01T15:45:00Z' - inviterUma: $inviter@uma.domain - inviteeUma: $invitee@uma.domain - status: CLAIMED - url: https://uma.me/i/019542f5 + $ref: '#/components/schemas/StablecoinExternalAccountLinkSessionCreateRequest' responses: - '200': - description: Webhook received successfully + '201': + description: Link session created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccountLinkSession' '400': description: Bad request content: @@ -7442,158 +7222,54 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - customer-update: + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-external-accounts: post: - summary: Customer status change + summary: Link a stablecoin external account description: | - Webhook that is called when the status of a customer is updated, including KYC and KYB status changes. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid API public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: customerStatusWebhook + Link a Grid external account, provider/Plaid link result, or direct-entry bank account to the stablecoin provider. The returned resource stores provider address metadata used for stablecoin mints and burns. + operationId: linkStablecoinExternalAccount tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/CustomerWebhook' - examples: - kycApprovedWebhook: - summary: When an individual customer KYC has been approved - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: CUSTOMER.KYC_APPROVED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 9f84e0c2a72c4fa - customerType: INDIVIDUAL - region: US - currencies: - - USD - - USDC - umaAddress: $john.doe@uma.domain.com - kycStatus: APPROVED - fullName: John Michael Doe - birthDate: '1990-01-15' - nationality: US - address: - line1: 123 Main Street - line2: Apt 4B - city: San Francisco - state: CA - postalCode: '94105' - country: US - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-07-21T17:32:28Z' - isDeleted: false - kycRejectedWebhook: - summary: When an individual customer KYC has been rejected - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: CUSTOMER.KYC_REJECTED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000002 - platformCustomerId: 4b7c1e9d3f5a8e2 - customerType: INDIVIDUAL - region: US - currencies: - - USD - - USDC - umaAddress: $jane.smith@uma.domain.com - kycStatus: REJECTED - fullName: Jane Smith - birthDate: '1988-03-22' - nationality: US - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-08-15T14:32:00Z' - isDeleted: false - kybApprovedWebhook: - summary: When a business customer KYB has been approved - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000009 - type: CUSTOMER.KYB_APPROVED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000003 - platformCustomerId: 7a2f9d4e1b8c3f5 - customerType: BUSINESS - region: US - currencies: - - USD - - USDC - umaAddress: $acme.corp@uma.domain.com - kybStatus: APPROVED - address: - line1: 456 Business Ave - city: New York - state: NY - postalCode: '10001' - country: US - businessInfo: - legalName: Acme Corporation - registrationNumber: '12345678' - taxId: 98-7654321 - incorporatedOn: '2018-03-14' - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-08-15T14:32:00Z' - isDeleted: false - kybRejectedWebhook: - summary: When a business customer KYB has been rejected - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000010 - type: CUSTOMER.KYB_REJECTED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Customer:019542f5-b3e7-1d02-0000-000000000004 - platformCustomerId: 3c8e5f2a9d1b7e4 - customerType: BUSINESS - region: US - currencies: - - USD - umaAddress: $globex.inc@uma.domain.com - kybStatus: REJECTED - address: - line1: 789 Corporate Blvd - city: Chicago - state: IL - postalCode: '60601' - country: US - businessInfo: - legalName: Globex Inc - taxId: 47-1234567 - incorporatedOn: '2015-09-01' - createdAt: '2025-07-21T17:32:28Z' - updatedAt: '2025-08-15T14:32:00Z' - isDeleted: false + $ref: '#/components/schemas/StablecoinExternalAccountLinkRequest' responses: - '200': - description: | - Webhook received successfully + '201': + description: Stablecoin external account linked + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccount' '400': description: Bad request content: @@ -7601,174 +7277,170 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: External account or link session not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - internal-account-status: - post: - summary: Internal account status webhook - description: | - Webhook that is called when the status of an internal account changes. This includes balance updates and may include additional account events in the future. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - - ### Event types - - `INTERNAL_ACCOUNT.BALANCE_UPDATED` — Fired when the balance of an internal account changes. The `data` payload contains the full internal account object. - - `INTERNAL_ACCOUNT.STATUS_UPDATED` — Fired when the status of an internal account changes (e.g., `OPEN` → `FROZEN`). The `data` payload contains the full internal account object. - operationId: internalAccountStatusWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List stablecoin external accounts + operationId: listStablecoinExternalAccounts tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/InternalAccountStatusWebhook' - examples: - balanceDecrease: - summary: A transaction just cleared a customer account and the balance has decreased - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INTERNAL_ACCOUNT.BALANCE_UPDATED - timestamp: '2025-08-15T14:32:00Z' - data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: INTERNAL_FIAT - status: ACTIVE - balance: - amount: 10000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - fundingPaymentInstructions: [] - createdAt: '2025-08-01T10:00:00Z' - updatedAt: '2025-08-15T14:32:00Z' - statusUpdated: - summary: The status of an internal account changed (e.g., frozen by Grid) - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: INTERNAL_ACCOUNT.STATUS_UPDATED - timestamp: '2025-08-15T14:32:00Z' - data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: INTERNAL_FIAT - status: FROZEN - balance: - amount: 10000 - currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - fundingPaymentInstructions: [] - createdAt: '2025-08-01T10:00:00Z' - updatedAt: '2025-08-15T14:32:00Z' + - BasicAuth: [] + parameters: + - name: provider + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinProvider' + - name: status + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinExternalAccountStatus' + - name: gridExternalAccountId + in: query + required: false + schema: + type: string + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: | - Webhook received successfully + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccountListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '500': + description: Internal service error content: application/json: schema: - $ref: '#/components/schemas/Error409' - verification-update: + $ref: '#/components/schemas/Error500' + /stablecoin-external-accounts/{stablecoinExternalAccountId}: + parameters: + - name: stablecoinExternalAccountId + in: path + description: System-generated stablecoin external account identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin external account + operationId: getStablecoinExternalAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinExternalAccount' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin external account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/quotes: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string post: - summary: Verification status change + summary: Create a stablecoin quote description: | - Webhook that is called when a customer's KYC/KYB verification status changes. - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid API public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: verificationStatusWebhook + Create a MINT or BURN quote for this stablecoin. A quote is a validation preview only: it locks no exchange rate, reserves no fee, and holds no balance. Execution re-validates everything; for burns, the balance hold happens at execution time. Execute the quote with `executeStablecoinQuote` before it expires. + operationId: createStablecoinQuote tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key scoped to this quote request. Replays return the prior quote; conflicting payloads are rejected. + required: true + schema: + type: string + maxLength: 255 requestBody: required: true content: application/json: schema: - $ref: '#/components/schemas/VerificationWebhook' - examples: - approved: - summary: Verification approved - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: VERIFICATION.APPROVED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Verification:019542f5-b3e7-1d02-0000-000000000010 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - verificationStatus: APPROVED - errors: [] - createdAt: '2025-08-15T14:00:00Z' - resolveErrors: - summary: Verification requires action - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000031 - type: VERIFICATION.RESOLVE_ERRORS - timestamp: '2025-08-15T14:32:00Z' - data: - id: Verification:019542f5-b3e7-1d02-0000-000000000011 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - verificationStatus: RESOLVE_ERRORS - errors: - - resourceId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: MISSING_PROOF_OF_ADDRESS_DOCUMENT - acceptedDocumentTypes: - - PROOF_OF_ADDRESS - reason: Proof of address document is required - createdAt: '2025-08-15T14:00:00Z' + $ref: '#/components/schemas/StablecoinQuoteRequest' responses: - '200': - description: | - Webhook received successfully + '201': + description: Quote created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinQuote' '400': description: Bad request content: @@ -7776,113 +7448,113 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin or linked account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - card-state-change: - post: - summary: Card state change - description: | - Webhook that is called when a card's lifecycle state changes. Fires on `PENDING_ISSUE → ACTIVE`, on `PENDING_ISSUE → CLOSED (ISSUER_REJECTED)` when issuer provisioning fails, and on every subsequent `ACTIVE ⇄ FROZEN` and `→ CLOSED` transition. - - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: cardStateChangeWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/quotes/{stablecoinQuoteId}: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + - name: stablecoinQuoteId + in: path + description: System-generated stablecoin quote identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin quote + operationId: getStablecoinQuote tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CardStateChangeWebhook' - examples: - activated: - summary: Card transitioned from PENDING_ISSUE to ACTIVE - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000020 - type: CARD.STATE_CHANGE - timestamp: '2026-05-08T14:11:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: card-emp-aary-001 - state: ACTIVE - stateReason: null - brand: VISA - form: VIRTUAL - last4: '4242' - expMonth: 12 - expYear: 2029 - panEmbedUrl: https://embed.lithic.com/iframe/...?t=... - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - issuerRef: lithic_card_4f8d3a2b1c - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-08T14:11:00Z' - issuerRejected: - summary: Card rejected by issuer during provisioning - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000021 - type: CARD.STATE_CHANGE - timestamp: '2026-05-08T14:12:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000011 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - state: CLOSED - stateReason: ISSUER_REJECTED - form: VIRTUAL - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-08T14:12:00Z' - frozen: - summary: Card frozen by the platform - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000022 - type: CARD.STATE_CHANGE - timestamp: '2026-05-09T09:00:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - state: FROZEN - stateReason: null - brand: VISA - form: VIRTUAL - last4: '4242' - expMonth: 12 - expYear: 2029 - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-09T09:00:00Z' + - BasicAuth: [] responses: '200': - description: | - Webhook received successfully + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinQuote' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin or quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/quotes/{stablecoinQuoteId}/execute: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + - name: stablecoinQuoteId + in: path + description: System-generated stablecoin quote identifier + required: true + schema: + type: string + post: + summary: Execute a stablecoin quote + description: | + Execute an open, unexpired quote, creating the StablecoinOperation and the first provider side effect. Execution re-validates the quoted inputs (stablecoin state, credential status, external-account capability, and for burns the source balance). Expired or already-executed quotes are rejected; create a new quote instead. + operationId: executeStablecoinQuote + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key scoped to creating the operation and provider side effects. Replays against the same quote return the prior operation; replays against a different quote are rejected. + required: true + schema: + type: string + maxLength: 255 + responses: + '201': + description: Operation created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperation' '400': description: Bad request content: @@ -7890,107 +7562,151 @@ webhooks: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin or quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - card-funding-source-change: - post: - summary: Card funding source change - description: | - Webhook that is called when the funding sources bound to a card change. Fires whenever `PATCH /cards/{id}` updates the `fundingSources` array. The payload carries the full `Card` resource with the post-change `fundingSources` array. - - This endpoint should be implemented by clients of the Grid API. - - ### Authentication - - The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. - To verify the signature: - 1. Get the Grid public key provided to you during integration - 2. Decode the base64 signature from the header - 3. Create a SHA-256 hash of the request body - 4. Verify the signature using the public key and the hash - - If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - operationId: cardFundingSourceChangeWebhook + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoins/{stablecoinId}/operations: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + get: + summary: List stablecoin operations + operationId: listStablecoinOperations tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CardFundingSourceChangeWebhook' - examples: - fundingSourcesReplaced: - summary: Funding sources replaced via PATCH /cards/{id} - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: CARD.FUNDING_SOURCE_CHANGE - timestamp: '2026-05-08T14:30:00Z' - data: - id: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 - state: ACTIVE - stateReason: null - brand: VISA - form: VIRTUAL - last4: '4242' - expMonth: 12 - expYear: 2029 - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 - currency: USD - createdAt: '2026-05-08T14:10:00Z' - updatedAt: '2026-05-08T14:30:00Z' + - BasicAuth: [] + parameters: + - name: type + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinOperationType' + - name: status + in: query + required: false + schema: + $ref: '#/components/schemas/StablecoinOperationStatus' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string responses: '200': - description: | - Webhook received successfully + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperationListResponse' '400': - description: Bad request + description: Bad request - Invalid parameters content: application/json: schema: $ref: '#/components/schemas/Error400' '401': - description: Unauthorized - Signature validation failed + description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error401' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '404': + description: Stablecoin not found content: application/json: schema: - $ref: '#/components/schemas/Error409' -components: - securitySchemes: - BasicAuth: - type: http - scheme: basic - description: API token authentication using format `:` - AgentAuth: - type: http - scheme: bearer - description: 'Bearer token authentication for agent-scoped endpoints. The token is the `accessToken` returned when redeeming a device code via `POST /agents/device-codes/{code}/redeem`. Agent credentials are user-scoped: all requests are automatically bound to the agent''s associated customer and subject to the agent''s policy.' - WebhookSignature: - type: apiKey - in: header - name: X-Grid-Signature + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-operations/{stablecoinOperationId}: + parameters: + - name: stablecoinOperationId + in: path + description: System-generated stablecoin operation identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin operation + operationId: getStablecoinOperation + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperation' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Stablecoin operation not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' +webhooks: + agent-action: + post: + summary: Agent action pending approval webhook description: | - Secp256r1 (P-256) asymmetric signature of the webhook payload, which can be used to verify that the webhook was sent by Grid. + Fired when an agent submits an action that requires platform approval before Grid will execute it. Use this to send a push notification to the customer so they can review and approve or reject the action in your app. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. To verify the signature: 1. Get the Grid public key provided to you during integration 2. Decode the base64 signature from the header @@ -7998,128 +7714,1245 @@ components: 4. Verify the signature using the public key and the hash If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. - schemas: - CustomerInfoFieldName: - type: string - enum: - - FULL_NAME - - BIRTH_DATE - - NATIONALITY - - PHONE_NUMBER - - EMAIL - - POSTAL_ADDRESS - - TAX_ID - - REGISTRATION_NUMBER - - USER_TYPE - - COUNTRY_OF_RESIDENCE - - ACCOUNT_IDENTIFIER - - FI_LEGAL_ENTITY_NAME - - FI_ADDRESS - - PURPOSE_OF_PAYMENT - - ULTIMATE_INSTITUTION_COUNTRY - - IDENTIFIER - - BUSINESS_TYPE - - COMPANY_LEGAL_NAME - - ID_TYPE - - ID_NUMBER - description: Name of a type of field containing info about a platform's customer or counterparty customer. - example: FULL_NAME - CounterpartyFieldDefinition: - type: object - properties: - name: - $ref: '#/components/schemas/CustomerInfoFieldName' - mandatory: - type: boolean - description: Whether the field is mandatory - example: true - required: - - name - - mandatory - TransactionType: - type: string - enum: - - INCOMING - - OUTGOING - description: Type of transaction (incoming payment or outgoing payment) - PlatformCurrencyConfig: - type: object - properties: - currencyCode: - type: string - description: Three-letter currency code (ISO 4217) - example: USD - minAmount: - type: integer - format: int64 - description: Minimum amount that can be sent in the smallest unit of this currency - minimum: 0 - example: 100 - maxAmount: - type: integer - format: int64 - description: Maximum amount that can be sent in the smallest unit of this currency - minimum: 0 - example: 1000000 - requiredCounterpartyFields: - type: array - items: - $ref: '#/components/schemas/CounterpartyFieldDefinition' - description: List of fields which the platform requires from the counterparty institutions about counterparty customers. Platforms can set mandatory to false if the platform does not require the field, but would like to have it available. Some fields may be required by the underlying UMA provider. - example: - - name: FULL_NAME - mandatory: true - - name: BIRTH_DATE - mandatory: true - - name: NATIONALITY - mandatory: true - providerRequiredCustomerFields: - type: array - items: - $ref: '#/components/schemas/CustomerInfoFieldName' - description: List of customer info field names that are required by the underlying UMA provider when creating a customer for this currency. These fields must be supplied when creating or updating a customer if this currency is intended to be used by that customer. If no fields are required, this field is omitted. - readOnly: true - example: - - NATIONALITY - - BIRTH_DATE - providerRequiredCounterpartyCustomerFields: - type: array - items: - $ref: '#/components/schemas/CustomerInfoFieldName' - description: List of fields that are required by the underlying UMA provider for this currency. If the counterparty does not provide these fields, quote requests will fail. - readOnly: true - example: - - FULL_NAME - - COUNTRY_OF_RESIDENCE - enabledTransactionTypes: - type: array - items: - $ref: '#/components/schemas/TransactionType' - description: List of transaction types that are enabled for this currency. - example: - - OUTGOING - - INCOMING - required: - - currencyCode - - minAmount - - maxAmount - - requiredCounterpartyFields - - enabledTransactionTypes - EmbeddedWalletConfig: - type: object + + The payload contains the full `AgentAction` — including the embedded quote or transfer details — so you can render the approval UI without a second API call. Approve or reject via `POST /agents/{agentId}/actions/{actionId}/approve` or `POST /agents/{agentId}/actions/{actionId}/reject`. + operationId: agentActionWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentActionWebhook' + examples: + pendingApproval: + summary: Agent action pending approval + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: AGENT_ACTION.PENDING_APPROVAL + timestamp: '2025-10-03T15:00:00Z' + data: + id: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: user-a1b2c3 + status: PENDING_APPROVAL + type: EXECUTE_QUOTE + quote: + id: Quote:019542f5-b3e7-1d02-0000-000000000006 + status: PENDING + expiresAt: '2025-10-03T15:00:30Z' + createdAt: '2025-10-03T15:00:00Z' + source: + sourceType: ACCOUNT + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + sendingCurrency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + receivingCurrency: + code: INR + name: Indian Rupee + symbol: ₹ + decimals: 2 + totalSendingAmount: 50000 + totalReceivingAmount: 4625000 + exchangeRate: 92.5 + feesIncluded: 250 + transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 + createdAt: '2025-10-03T15:00:00Z' + updatedAt: '2025-10-03T15:00:00Z' + responses: + '200': + description: Webhook received and acknowledged. + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + incoming-payment: + post: + summary: Incoming payment webhook and approval mechanism description: | - Per-platform embedded-wallet configuration. Controls branding and OTP - behavior for the email sent when a customer authenticates with an - EMAIL_OTP credential. Fields omitted from a request are left unchanged. - properties: - appName: - type: string - maxLength: 255 - description: App name displayed in the default OTP email template. - example: Acme Wallet - otpLength: - type: integer - minimum: 4 + Webhook that is called when an incoming payment is received by a customer's UMA address. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + ### Payment Approval Flow + When a transaction has `status: "PENDING"`, this webhook serves as an approval mechanism: + + 1. The client should check the `counterpartyInformation` against their requirements + 2. To APPROVE the payment synchronously, return a 200 OK response + 3. To REJECT the payment, return a 403 Forbidden response with an Error object + 4. To request more information, return a 422 Unprocessable Entity with specific missing fields + 5. To process the payment asynchronously, return a 202 Accepted response and then call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint within 5 seconds. Note that synchronous approval/rejection is preferred where possible. + + The Grid system will proceed or cancel the payment based on your response. + + For transactions with other statuses (COMPLETED, FAILED, REFUNDED), this webhook is purely informational. + operationId: incomingPaymentWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhook' + examples: + pendingPayment: + summary: Pending payment example requiring approval + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INCOMING_PAYMENT.PENDING + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: PENDING + type: INCOMING + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + counterpartyInformation: + FULL_NAME: John Sender + BIRTH_DATE: '1985-06-15' + NATIONALITY: US + reconciliationInstructions: + reference: REF-123456789 + requestedReceiverCustomerInfoFields: + - name: NATIONALITY + mandatory: true + - name: POSTAL_ADDRESS + mandatory: false + incomingCompletedPayment: + summary: Completed payment notification + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INCOMING_PAYMENT.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: INCOMING + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: Payment for services + reconciliationInstructions: + reference: REF-123456789 + responses: + '200': + description: | + Webhook received successfully. + For PENDING transactions, this indicates approval to proceed with the payment. + If `requestedReceiverCustomerInfoFields` were present in the webhook request, the corresponding fields for the recipient must be included in this response in the `receiverCustomerInfo` object. + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhookResponse' + '202': + description: | + Webhook received and will be processed asynchronously. The synchronous 200 response should be preferred where possible. This asycnhronous path should only be used in + cases where the platform's architecture requires async (but still very quick) processing before approving or rejecting the payment. + The platform must call the `/transactions/{transactionId}/approve` or `/transactions/{transactionId}/reject` endpoint to approve or reject the payment within 5 seconds or the payment will be automatically rejected. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: | + Forbidden - Payment rejected by the client. + Only applicable for PENDING transactions. + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhookForbiddenResponse' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '422': + description: | + Unprocessable Entity - Additional counterparty information required. + Only applicable for PENDING transactions. + content: + application/json: + schema: + $ref: '#/components/schemas/IncomingPaymentWebhookUnprocessableResponse' + outgoing-payment: + post: + summary: Outgoing payment status webhook + description: | + Webhook that is called when an outgoing payment's status changes. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + This webhook is informational only and is sent when an outgoing payment completes successfully, fails, or is refunded. + operationId: outgoingPaymentWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/OutgoingPaymentWebhook' + examples: + outgoingCompletedPayment: + summary: Completed outgoing payment + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: OUTGOING_PAYMENT.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: OUTGOING + source: + sourceType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@uma.domain + receiverUmaAddress: $recipient@external.domain + sentAmount: + amount: 10550 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + receivedAmount: + amount: 9706 + currency: + code: EUR + name: Euro + symbol: € + decimals: 2 + exchangeRate: 0.92 + quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: 'Payment for invoice #1234' + paymentInstructions: [] + rateDetails: + counterpartyMultiplier: 1.08 + counterpartyFixedFee: 10 + gridApiMultiplier: 0.925 + gridApiFixedFee: 10 + gridApiVariableFeeRate: 0.003 + gridApiVariableFeeAmount: 30 + failedPayment: + summary: Failed outgoing payment + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: OUTGOING_PAYMENT.FAILED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: FAILED + type: OUTGOING + source: + sourceType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@uma.domain + receiverUmaAddress: $recipient@external.domain + sentAmount: + amount: 10550 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + createdAt: '2025-08-15T14:25:18Z' + quoteId: Quote:019542f5-b3e7-1d02-0000-000000000006 + failureReason: QUOTE_EXECUTION_FAILED + responses: + '200': + description: Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + test-webhook: + post: + summary: Test webhook for integration verification + description: | + Webhook that is sent once to verify your webhook endpoint is correctly set up. + This is sent when you configure or update your platform settings with a webhook URL. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by the Grid API. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + This webhook is purely for testing your endpoint integration and signature verification. + operationId: testWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TestWebhookRequest' + examples: + testWebhook: + summary: Test webhook example + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000001 + type: TEST + timestamp: '2025-08-15T14:32:00Z' + data: {} + responses: + '200': + description: Webhook received successfully. This confirms your webhook endpoint is properly configured. + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + bulk-upload: + post: + summary: Bulk upload status webhook + description: | + Webhook that is called when a bulk customer upload job completes or fails. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + This webhook is sent when a bulk upload job completes or fails, providing detailed information about the results. + operationId: bulkUploadWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/BulkUploadWebhook' + examples: + completedUpload: + summary: Successful bulk upload completion + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: BULK_UPLOAD.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Job:019542f5-b3e7-1d02-0000-000000000006 + status: COMPLETED + progress: + total: 5000 + processed: 5000 + successful: 5000 + failed: 0 + errors: [] + failedUpload: + summary: Failed bulk upload + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: BULK_UPLOAD.FAILED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Job:019542f5-b3e7-1d02-0000-000000000006 + status: FAILED + progress: + total: 5000 + processed: 5000 + successful: 0 + failed: 5000 + errors: + - correlationId: row_1 + error: + code: invalid_csv_format + message: Invalid CSV format + details: + reason: missing_required_column + column: umaAddress + responses: + '200': + description: Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + invitation-claimed: + post: + summary: Invitation claimed webhook + description: | + Webhook that is called when an invitation is claimed by a customer. + This endpoint should be implemented by platform clients of the Grid API. + + When a customer claims an invitation, this webhook is triggered to notify the platform that: + 1. The invitation has been successfully claimed + 2. The invitee UMA address is now associated with the invitation + 3. The invitation status has changed from PENDING to CLAIMED + + This allows platforms to: + - Track invitation usage and conversion rates + - Trigger onboarding flows for new customers who joined via invitation + - Apply referral bonuses or rewards to the inviter + - Update their UI to reflect the claimed status + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: invitationClaimedWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/InvitationClaimedWebhook' + examples: + claimedInvitation: + summary: Invitation claimed notification + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: INVITATION.CLAIMED + timestamp: '2025-09-01T15:45:00Z' + data: + code: 019542f5 + createdAt: '2025-09-01T14:30:00Z' + claimedAt: '2025-09-01T15:45:00Z' + inviterUma: $inviter@uma.domain + inviteeUma: $invitee@uma.domain + status: CLAIMED + url: https://uma.me/i/019542f5 + responses: + '200': + description: Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + customer-update: + post: + summary: Customer status change + description: | + Webhook that is called when the status of a customer is updated, including KYC and KYB status changes. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid API public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: customerStatusWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CustomerWebhook' + examples: + kycApprovedWebhook: + summary: When an individual customer KYC has been approved + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: CUSTOMER.KYC_APPROVED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 9f84e0c2a72c4fa + customerType: INDIVIDUAL + region: US + currencies: + - USD + - USDC + umaAddress: $john.doe@uma.domain.com + kycStatus: APPROVED + fullName: John Michael Doe + birthDate: '1990-01-15' + nationality: US + address: + line1: 123 Main Street + line2: Apt 4B + city: San Francisco + state: CA + postalCode: '94105' + country: US + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-07-21T17:32:28Z' + isDeleted: false + kycRejectedWebhook: + summary: When an individual customer KYC has been rejected + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: CUSTOMER.KYC_REJECTED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000002 + platformCustomerId: 4b7c1e9d3f5a8e2 + customerType: INDIVIDUAL + region: US + currencies: + - USD + - USDC + umaAddress: $jane.smith@uma.domain.com + kycStatus: REJECTED + fullName: Jane Smith + birthDate: '1988-03-22' + nationality: US + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-08-15T14:32:00Z' + isDeleted: false + kybApprovedWebhook: + summary: When a business customer KYB has been approved + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000009 + type: CUSTOMER.KYB_APPROVED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000003 + platformCustomerId: 7a2f9d4e1b8c3f5 + customerType: BUSINESS + region: US + currencies: + - USD + - USDC + umaAddress: $acme.corp@uma.domain.com + kybStatus: APPROVED + address: + line1: 456 Business Ave + city: New York + state: NY + postalCode: '10001' + country: US + businessInfo: + legalName: Acme Corporation + registrationNumber: '12345678' + taxId: 98-7654321 + incorporatedOn: '2018-03-14' + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-08-15T14:32:00Z' + isDeleted: false + kybRejectedWebhook: + summary: When a business customer KYB has been rejected + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000010 + type: CUSTOMER.KYB_REJECTED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Customer:019542f5-b3e7-1d02-0000-000000000004 + platformCustomerId: 3c8e5f2a9d1b7e4 + customerType: BUSINESS + region: US + currencies: + - USD + umaAddress: $globex.inc@uma.domain.com + kybStatus: REJECTED + address: + line1: 789 Corporate Blvd + city: Chicago + state: IL + postalCode: '60601' + country: US + businessInfo: + legalName: Globex Inc + taxId: 47-1234567 + incorporatedOn: '2015-09-01' + createdAt: '2025-07-21T17:32:28Z' + updatedAt: '2025-08-15T14:32:00Z' + isDeleted: false + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + internal-account-status: + post: + summary: Internal account status webhook + description: | + Webhook that is called when the status of an internal account changes. This includes balance updates and may include additional account events in the future. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + + ### Event types + - `INTERNAL_ACCOUNT.BALANCE_UPDATED` — Fired when the balance of an internal account changes. The `data` payload contains the full internal account object. + - `INTERNAL_ACCOUNT.STATUS_UPDATED` — Fired when the status of an internal account changes (e.g., `OPEN` → `FROZEN`). The `data` payload contains the full internal account object. + operationId: internalAccountStatusWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/InternalAccountStatusWebhook' + examples: + balanceDecrease: + summary: A transaction just cleared a customer account and the balance has decreased + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INTERNAL_ACCOUNT.BALANCE_UPDATED + timestamp: '2025-08-15T14:32:00Z' + data: + id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: INTERNAL_FIAT + status: ACTIVE + balance: + amount: 10000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + fundingPaymentInstructions: [] + createdAt: '2025-08-01T10:00:00Z' + updatedAt: '2025-08-15T14:32:00Z' + statusUpdated: + summary: The status of an internal account changed (e.g., frozen by Grid) + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: INTERNAL_ACCOUNT.STATUS_UPDATED + timestamp: '2025-08-15T14:32:00Z' + data: + id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: INTERNAL_FIAT + status: FROZEN + balance: + amount: 10000 + currency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + fundingPaymentInstructions: [] + createdAt: '2025-08-01T10:00:00Z' + updatedAt: '2025-08-15T14:32:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + verification-update: + post: + summary: Verification status change + description: | + Webhook that is called when a customer's KYC/KYB verification status changes. + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid API public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: verificationStatusWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/VerificationWebhook' + examples: + approved: + summary: Verification approved + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000030 + type: VERIFICATION.APPROVED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Verification:019542f5-b3e7-1d02-0000-000000000010 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + verificationStatus: APPROVED + errors: [] + createdAt: '2025-08-15T14:00:00Z' + resolveErrors: + summary: Verification requires action + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000031 + type: VERIFICATION.RESOLVE_ERRORS + timestamp: '2025-08-15T14:32:00Z' + data: + id: Verification:019542f5-b3e7-1d02-0000-000000000011 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + verificationStatus: RESOLVE_ERRORS + errors: + - resourceId: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: MISSING_PROOF_OF_ADDRESS_DOCUMENT + acceptedDocumentTypes: + - PROOF_OF_ADDRESS + reason: Proof of address document is required + createdAt: '2025-08-15T14:00:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + card-state-change: + post: + summary: Card state change + description: | + Webhook that is called when a card's lifecycle state changes. Fires on `PENDING_ISSUE → ACTIVE`, on `PENDING_ISSUE → CLOSED (ISSUER_REJECTED)` when issuer provisioning fails, and on every subsequent `ACTIVE ⇄ FROZEN` and `→ CLOSED` transition. + + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: cardStateChangeWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CardStateChangeWebhook' + examples: + activated: + summary: Card transitioned from PENDING_ISSUE to ACTIVE + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: CARD.STATE_CHANGE + timestamp: '2026-05-08T14:11:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCardId: card-emp-aary-001 + state: ACTIVE + stateReason: null + brand: VISA + form: VIRTUAL + last4: '4242' + expMonth: 12 + expYear: 2029 + panEmbedUrl: https://embed.lithic.com/iframe/...?t=... + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + issuerRef: lithic_card_4f8d3a2b1c + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-08T14:11:00Z' + issuerRejected: + summary: Card rejected by issuer during provisioning + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000021 + type: CARD.STATE_CHANGE + timestamp: '2026-05-08T14:12:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000011 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + state: CLOSED + stateReason: ISSUER_REJECTED + form: VIRTUAL + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-08T14:12:00Z' + frozen: + summary: Card frozen by the platform + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000022 + type: CARD.STATE_CHANGE + timestamp: '2026-05-09T09:00:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + state: FROZEN + stateReason: null + brand: VISA + form: VIRTUAL + last4: '4242' + expMonth: 12 + expYear: 2029 + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-09T09:00:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + card-funding-source-change: + post: + summary: Card funding source change + description: | + Webhook that is called when the funding sources bound to a card change. Fires whenever `PATCH /cards/{id}` updates the `fundingSources` array. The payload carries the full `Card` resource with the post-change `fundingSources` array. + + This endpoint should be implemented by clients of the Grid API. + + ### Authentication + + The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + operationId: cardFundingSourceChangeWebhook + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CardFundingSourceChangeWebhook' + examples: + fundingSourcesReplaced: + summary: Funding sources replaced via PATCH /cards/{id} + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000030 + type: CARD.FUNDING_SOURCE_CHANGE + timestamp: '2026-05-08T14:30:00Z' + data: + id: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: Customer:019542f5-b3e7-1d02-0000-000000000001 + state: ACTIVE + stateReason: null + brand: VISA + form: VIRTUAL + last4: '4242' + expMonth: 12 + expYear: 2029 + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 + currency: USD + createdAt: '2026-05-08T14:10:00Z' + updatedAt: '2026-05-08T14:30:00Z' + responses: + '200': + description: | + Webhook received successfully + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' +components: + securitySchemes: + BasicAuth: + type: http + scheme: basic + description: API token authentication using format `:` + AgentAuth: + type: http + scheme: bearer + description: 'Bearer token authentication for agent-scoped endpoints. The token is the `accessToken` returned when redeeming a device code via `POST /agents/device-codes/{code}/redeem`. Agent credentials are user-scoped: all requests are automatically bound to the agent''s associated customer and subject to the agent''s policy.' + WebhookSignature: + type: apiKey + in: header + name: X-Grid-Signature + description: | + Secp256r1 (P-256) asymmetric signature of the webhook payload, which can be used to verify that the webhook was sent by Grid. + To verify the signature: + 1. Get the Grid public key provided to you during integration + 2. Decode the base64 signature from the header + 3. Create a SHA-256 hash of the request body + 4. Verify the signature using the public key and the hash + + If the signature verification succeeds, the webhook is authentic. If not, it should be rejected. + schemas: + CustomerInfoFieldName: + type: string + enum: + - FULL_NAME + - BIRTH_DATE + - NATIONALITY + - PHONE_NUMBER + - EMAIL + - POSTAL_ADDRESS + - TAX_ID + - REGISTRATION_NUMBER + - USER_TYPE + - COUNTRY_OF_RESIDENCE + - ACCOUNT_IDENTIFIER + - FI_LEGAL_ENTITY_NAME + - FI_ADDRESS + - PURPOSE_OF_PAYMENT + - ULTIMATE_INSTITUTION_COUNTRY + - IDENTIFIER + - BUSINESS_TYPE + - COMPANY_LEGAL_NAME + - ID_TYPE + - ID_NUMBER + description: Name of a type of field containing info about a platform's customer or counterparty customer. + example: FULL_NAME + CounterpartyFieldDefinition: + type: object + properties: + name: + $ref: '#/components/schemas/CustomerInfoFieldName' + mandatory: + type: boolean + description: Whether the field is mandatory + example: true + required: + - name + - mandatory + TransactionType: + type: string + enum: + - INCOMING + - OUTGOING + description: Type of transaction (incoming payment or outgoing payment) + PlatformCurrencyConfig: + type: object + properties: + currencyCode: + type: string + description: Three-letter currency code (ISO 4217) + example: USD + minAmount: + type: integer + format: int64 + description: Minimum amount that can be sent in the smallest unit of this currency + minimum: 0 + example: 100 + maxAmount: + type: integer + format: int64 + description: Maximum amount that can be sent in the smallest unit of this currency + minimum: 0 + example: 1000000 + requiredCounterpartyFields: + type: array + items: + $ref: '#/components/schemas/CounterpartyFieldDefinition' + description: List of fields which the platform requires from the counterparty institutions about counterparty customers. Platforms can set mandatory to false if the platform does not require the field, but would like to have it available. Some fields may be required by the underlying UMA provider. + example: + - name: FULL_NAME + mandatory: true + - name: BIRTH_DATE + mandatory: true + - name: NATIONALITY + mandatory: true + providerRequiredCustomerFields: + type: array + items: + $ref: '#/components/schemas/CustomerInfoFieldName' + description: List of customer info field names that are required by the underlying UMA provider when creating a customer for this currency. These fields must be supplied when creating or updating a customer if this currency is intended to be used by that customer. If no fields are required, this field is omitted. + readOnly: true + example: + - NATIONALITY + - BIRTH_DATE + providerRequiredCounterpartyCustomerFields: + type: array + items: + $ref: '#/components/schemas/CustomerInfoFieldName' + description: List of fields that are required by the underlying UMA provider for this currency. If the counterparty does not provide these fields, quote requests will fail. + readOnly: true + example: + - FULL_NAME + - COUNTRY_OF_RESIDENCE + enabledTransactionTypes: + type: array + items: + $ref: '#/components/schemas/TransactionType' + description: List of transaction types that are enabled for this currency. + example: + - OUTGOING + - INCOMING + required: + - currencyCode + - minAmount + - maxAmount + - requiredCounterpartyFields + - enabledTransactionTypes + EmbeddedWalletConfig: + type: object + description: | + Per-platform embedded-wallet configuration. Controls branding and OTP + behavior for the email sent when a customer authenticates with an + EMAIL_OTP credential. Fields omitted from a request are left unchanged. + properties: + appName: + type: string + maxLength: 255 + description: App name displayed in the default OTP email template. + example: Acme Wallet + otpLength: + type: integer + minimum: 4 maximum: 12 description: | Number of digits / characters in the OTP code. Defaults to 6 when @@ -8355,6 +9188,22 @@ components: | INCOMPLETE | Document is missing pages or sides | | EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS | An EMAIL_OTP credential is already registered on the target internal account; only one email OTP credential is supported per internal account at this time | | PASSKEY_CREDENTIAL_ALREADY_EXISTS | A PASSKEY credential with the same WebAuthn credentialId is already registered on the target internal account | + | STABLECOIN_PROVIDER_ACCOUNT_INVALID | The stablecoin provider account link is not usable | + | STABLECOIN_PROVIDER_ACCOUNT_REVOKED | The stablecoin provider account link has been revoked | + | STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active provider account links exist; pass `stablecoinProviderAccountId` to select one | + | STABLECOIN_VERIFICATION_FAILED | Provider verification of the stablecoin or credentials failed | + | STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED | Linking the external account with the provider failed | + | STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED | The request must specify a supported external-account link method | + | STABLECOIN_NOT_PROVISIONED | The stablecoin is not provisioned with the provider | + | STABLECOIN_GRID_OPERATIONS_NOT_ENABLED | Grid operations are not enabled for this stablecoin | + | STABLECOIN_QUOTE_EXPIRED | The stablecoin quote has expired | + | STABLECOIN_AMOUNT_NOT_REPRESENTABLE | The amount cannot be represented in the target currency or token precision | + | STABLECOIN_OPERATION_NOT_SUPPORTED | The requested stablecoin operation is not supported | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED | The stablecoin external account is not linked or not active | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED | The stablecoin external account does not support the requested transfer type | + | STABLECOIN_BURN_SOURCE_NOT_SUPPORTED | The burn source account is not supported | + | STABLECOIN_PROVIDER_SOURCE_NOT_LINKED | The provider token-balance funding source is not linked | + | STABLECOIN_PROVIDER_ERROR | The stablecoin provider rejected or failed the request | enum: - INVALID_INPUT - MISSING_MANDATORY_USER_INFO @@ -8391,6 +9240,22 @@ components: - INCOMPLETE - EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS - PASSKEY_CREDENTIAL_ALREADY_EXISTS + - STABLECOIN_PROVIDER_ACCOUNT_INVALID + - STABLECOIN_PROVIDER_ACCOUNT_REVOKED + - STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED + - STABLECOIN_VERIFICATION_FAILED + - STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED + - STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED + - STABLECOIN_NOT_PROVISIONED + - STABLECOIN_GRID_OPERATIONS_NOT_ENABLED + - STABLECOIN_QUOTE_EXPIRED + - STABLECOIN_AMOUNT_NOT_REPRESENTABLE + - STABLECOIN_OPERATION_NOT_SUPPORTED + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED + - STABLECOIN_BURN_SOURCE_NOT_SUPPORTED + - STABLECOIN_PROVIDER_SOURCE_NOT_LINKED + - STABLECOIN_PROVIDER_ERROR message: type: string description: Error message @@ -9287,12 +10152,16 @@ components: | EMAIL_OTP_EMAIL_ALREADY_EXISTS | Email address is already associated with an EMAIL_OTP credential | | EMAIL_OTP_CREDENTIAL_SET_CHANGED | Tied EMAIL_OTP credential set changed after the signed-retry challenge was issued | | CONFLICT | Generic resource-state conflict. Returned, for example, when `platformCustomerId` on a customer create call collides with an existing active customer on the same platform | + | STABLECOIN_SYMBOL_ALREADY_EXISTS | A stablecoin with the same symbol is already registered for this platform | + | STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS | A stablecoin with the same network token identifier is already registered | enum: - TRANSACTION_NOT_PENDING_PLATFORM_APPROVAL - UMA_ADDRESS_EXISTS - EMAIL_OTP_EMAIL_ALREADY_EXISTS - EMAIL_OTP_CREDENTIAL_SET_CHANGED - CONFLICT + - STABLECOIN_SYMBOL_ALREADY_EXISTS + - STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS message: type: string description: Error message @@ -9326,6 +10195,11 @@ components: | BULK_UPLOAD_JOB_NOT_FOUND | Bulk upload job not found | | REFERENCE_NOT_FOUND | Reference not found | | UMA_NOT_FOUND | The UMA address is well-formed but no receiver exists at the counterparty VASP | + | STABLECOIN_NOT_FOUND | Stablecoin not found | + | STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND | Stablecoin provider account link not found | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND | Stablecoin external account not found | + | STABLECOIN_QUOTE_NOT_FOUND | Stablecoin quote not found | + | STABLECOIN_OPERATION_NOT_FOUND | Stablecoin operation not found | enum: - TRANSACTION_NOT_FOUND - INVITATION_NOT_FOUND @@ -9336,6 +10210,11 @@ components: - BULK_UPLOAD_JOB_NOT_FOUND - REFERENCE_NOT_FOUND - UMA_NOT_FOUND + - STABLECOIN_NOT_FOUND + - STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND + - STABLECOIN_QUOTE_NOT_FOUND + - STABLECOIN_OPERATION_NOT_FOUND message: type: string description: Error message @@ -15393,44 +16272,421 @@ components: allOf: - type: object required: - - currency - - accountInfo + - currency + - accountInfo + properties: + customerId: + type: string + description: The ID of the customer for whom to create the external account. If not provided, the external account will be created on behalf of the platform. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + currency: + type: string + description: The ISO 4217 currency code + example: USD + platformAccountId: + type: string + description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. + example: ext_acc_123456 + defaultUmaDepositAccount: + type: boolean + description: Whether to set the external account as the default UMA deposit account. When set to true, incoming payments to this customer's UMA address will be automatically deposited into this external account. False if not provided. Note that only one external account can be set as the default UMA deposit account for a customer, so if there is already a default UMA deposit account, this will override the existing default UMA deposit account. If there is no default UMA deposit account, incoming UMA payments will be deposited into the primary internal account for the customer. + default: false + accountInfo: + $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' + PlatformExternalAccountCreateRequest: + type: object + required: + - currency + - accountInfo + properties: + currency: + type: string + description: The ISO 4217 currency code + example: USD + platformAccountId: + type: string + description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. + example: ext_acc_123456 + accountInfo: + $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' + BeneficialOwnerListResponse: + type: object + required: + - data + - hasMore + properties: + data: + type: array + description: List of beneficial owners matching the filter criteria + items: + $ref: '#/components/schemas/BeneficialOwner' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of results matching the criteria + BeneficialOwnerCreateRequest: + type: object + required: + - customerId + - roles + - ownershipPercentage + - personalInfo + properties: + customerId: + type: string + description: The ID of the business customer this beneficial owner is associated with + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + roles: + type: array + items: + $ref: '#/components/schemas/BeneficialOwnerRole' + description: Roles of this person within the business + example: + - UBO + - DIRECTOR + ownershipPercentage: + type: integer + description: Percentage of ownership in the business (0-100). Relevant when role includes UBO. + minimum: 0 + maximum: 100 + example: 51 + personalInfo: + $ref: '#/components/schemas/BeneficialOwnerPersonalInfo' + BeneficialOwnerPersonalInfoUpdate: + type: object + description: Partial update for beneficial owner personal information. Only provided fields are updated. + properties: + firstName: + type: string + description: First name of the individual + example: Jane + middleName: + type: string + description: Middle name of the individual + example: Marie + lastName: + type: string + description: Last name of the individual + example: Smith + birthDate: + type: string + format: date + description: Date of birth in ISO 8601 format (YYYY-MM-DD) + example: '1978-06-15' + nationality: + type: string + description: Country of nationality (ISO 3166-1 alpha-2) + example: US + email: + type: string + format: email + description: Email address of the individual + example: jane.smith@acmecorp.com + phoneNumber: + type: string + description: Phone number in E.164 format + example: '+14155550192' + pattern: ^\+[1-9]\d{1,14}$ + address: + $ref: '#/components/schemas/Address' + idType: + $ref: '#/components/schemas/IdentificationType' + identifier: + type: string + description: The identification number or value + example: 123-45-6789 + countryOfIssuance: + type: string + description: Country that issued the identification (ISO 3166-1 alpha-2) + example: US + BeneficialOwnerUpdateRequest: + type: object + properties: + roles: + type: array + items: + $ref: '#/components/schemas/BeneficialOwnerRole' + description: Roles of this person within the business + example: + - UBO + - DIRECTOR + ownershipPercentage: + type: integer + description: Percentage of ownership in the business (0-100) + minimum: 0 + maximum: 100 + example: 51 + personalInfo: + $ref: '#/components/schemas/BeneficialOwnerPersonalInfoUpdate' + DocumentType: + type: string + enum: + - PASSPORT + - DRIVERS_LICENSE + - NATIONAL_ID + - PROOF_OF_ADDRESS + - BANK_STATEMENT + - TAX_RETURN + - CERTIFICATE_OF_INCORPORATION + - ARTICLES_OF_INCORPORATION + - ARTICLES_OF_ASSOCIATION + - STATE_REGISTRY_EXCERPT + - GOOD_STANDING_CERTIFICATE + - INFORMATION_STATEMENT + - INCUMBENCY_CERTIFICATE + - BUSINESS_LICENSE + - SHAREHOLDER_REGISTER + - POWER_OF_ATTORNEY + - UTILITY_BILL + - ELECTRICITY_BILL + - RENT_OR_LEASE_AGREEMENT + - DIRECTOR_REGISTRY + - TRUST_AGREEMENT + - STATE_COMPANY_REGISTRY + - PARTNERSHIP_CONTROL_AGREEMENT + - PARTNERSHIP_AGREEMENT + - SELFIE + - OTHER + description: |- + Type of identity or business verification document. Document types are grouped by verification category: + **Identity** — PASSPORT, DRIVERS_LICENSE, NATIONAL_ID + **Business — Legal presence** — CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT + **Business — Control structure** — DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT + **Business — Ownership structure** — SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT + **Proof of address** — UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN + example: PASSPORT + Document: + type: object + required: + - id + - documentHolder + - documentType + - country + - fileName + - createdAt + properties: + id: + type: string + description: Unique identifier for this document + example: Document:019542f5-b3e7-1d02-0000-000000000001 + documentHolder: + type: string + description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. + example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 + documentType: + $ref: '#/components/schemas/DocumentType' + side: + type: string + enum: + - FRONT + - BACK + description: Which side of the document this upload represents. Relevant for two-sided documents like driver's licenses or national IDs. + example: FRONT + country: + type: string + description: Country that issued the document (ISO 3166-1 alpha-2) + example: US + documentNumber: + type: string + description: Document identification number (e.g., passport number) + example: A12345678 + issuingAuthority: + type: string + description: Name of the government agency or organization that issued the document + example: U.S. Department of State + fileName: + type: string + description: Original file name of the uploaded document + example: passport_scan.pdf + createdAt: + type: string + format: date-time + description: When this document was uploaded + example: '2025-10-03T12:00:00Z' + updatedAt: + type: string + format: date-time + description: When this document was last updated + example: '2025-10-03T12:00:00Z' + DocumentListResponse: + type: object + required: + - data + - hasMore + properties: + data: + type: array + description: List of documents matching the filter criteria + items: + $ref: '#/components/schemas/Document' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of results matching the criteria + BaseDocumentRequest: + type: object + required: + - file + - documentType + - country + properties: + file: + type: string + format: binary + description: The document file (PDF, JPEG, or PNG, max 10 MB) + documentType: + $ref: '#/components/schemas/DocumentType' + side: + type: string + enum: + - FRONT + - BACK + description: Which side of the document (for two-sided documents like driver's licenses) + example: FRONT + country: + type: string + description: Country that issued the document (ISO 3166-1 alpha-2) + example: US + documentNumber: + type: string + description: Document identification number (e.g., passport number) + example: A12345678 + issuingAuthority: + type: string + description: Name of the government agency or organization that issued the document + example: U.S. Department of State + DocumentUploadRequest: + title: Document Upload Request + allOf: + - $ref: '#/components/schemas/BaseDocumentRequest' + - type: object + required: + - documentHolder properties: - customerId: - type: string - description: The ID of the customer for whom to create the external account. If not provided, the external account will be created on behalf of the platform. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - currency: - type: string - description: The ISO 4217 currency code - example: USD - platformAccountId: + documentHolder: type: string - description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. - example: ext_acc_123456 - defaultUmaDepositAccount: - type: boolean - description: Whether to set the external account as the default UMA deposit account. When set to true, incoming payments to this customer's UMA address will be automatically deposited into this external account. False if not provided. Note that only one external account can be set as the default UMA deposit account for a customer, so if there is already a default UMA deposit account, this will override the existing default UMA deposit account. If there is no default UMA deposit account, incoming UMA payments will be deposited into the primary internal account for the customer. - default: false - accountInfo: - $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' - PlatformExternalAccountCreateRequest: + description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. + example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 + DocumentReplaceRequest: + title: Document Replace Request + allOf: + - $ref: '#/components/schemas/BaseDocumentRequest' + VerificationStatus: + type: string + enum: + - RESOLVE_ERRORS + - PENDING_MANUAL_REVIEW + - IN_PROGRESS + - APPROVED + - REJECTED + - READY_FOR_VERIFICATION + description: Current status of the KYC/KYB verification + example: RESOLVE_ERRORS + VerificationErrorType: + type: string + enum: + - MISSING_FIELD + - INVALID_FIELD + - MISSING_LEGAL_PRESENCE_DOCUMENT + - MISSING_CONTROL_STRUCTURE_DOCUMENT + - MISSING_OWNERSHIP_STRUCTURE_DOCUMENT + - MISSING_PROOF_OF_ADDRESS_DOCUMENT + - MISSING_IDENTITY_DOCUMENT + - INVALID_DOCUMENT + - EXPIRED_DOCUMENT + - POOR_QUALITY_DOCUMENT + - SUSPECTED_FRAUD_DOCUMENT + - WRONG_DOCUMENT_TYPE + - INCOMPLETE_DOCUMENT + - UNREADABLE_DOCUMENT + - DOCUMENT_VERIFICATION_FAILED + - APPLICANT_SANCTIONED + - APPLICANT_FRAUD + - APPLICANT_CRIMINAL_RECORD + - APPLICANT_REJECTED + - MISSING_BENEFICIAL_OWNER + description: Type of verification error. The category-specific MISSING_*_DOCUMENT types indicate which document category is needed. Document quality types (POOR_QUALITY_DOCUMENT, SUSPECTED_FRAUD_DOCUMENT, etc.) indicate specific issues with uploaded documents. APPLICANT_* types indicate issues with the applicant themselves (sanctions, fraud, criminal records). + example: MISSING_FIELD + VerificationError: type: object required: - - currency - - accountInfo + - resourceId + - type + - reason properties: - currency: + resourceId: type: string - description: The ISO 4217 currency code - example: USD - platformAccountId: + description: ID of the resource with the issue (Customer, BeneficialOwner, or Document) + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + type: + $ref: '#/components/schemas/VerificationErrorType' + field: type: string - description: Your platform's identifier for the account in your system. This can be used to reference the account by your own identifier. - example: ext_acc_123456 - accountInfo: - $ref: '#/components/schemas/ExternalAccountCreateInfoOneOf' - BeneficialOwnerListResponse: + description: Dot-notation path to the field with the issue. Present when type is MISSING_FIELD or INVALID_FIELD. + example: customer.address.line1 + acceptedDocumentTypes: + type: array + items: + $ref: '#/components/schemas/DocumentType' + description: |- + Document types that would satisfy this requirement. The integrator can upload any one of the listed types. Present when type is MISSING_LEGAL_PRESENCE_DOCUMENT, MISSING_CONTROL_STRUCTURE_DOCUMENT, MISSING_OWNERSHIP_STRUCTURE_DOCUMENT, MISSING_PROOF_OF_ADDRESS_DOCUMENT, MISSING_IDENTITY_DOCUMENT, INVALID_DOCUMENT, or EXPIRED_DOCUMENT. + + | Error Type | Accepted Document Types | + |---|---| + | MISSING_LEGAL_PRESENCE_DOCUMENT | CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT | + | MISSING_CONTROL_STRUCTURE_DOCUMENT | DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT | + | MISSING_OWNERSHIP_STRUCTURE_DOCUMENT | SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT | + | MISSING_PROOF_OF_ADDRESS_DOCUMENT | UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN | + | MISSING_IDENTITY_DOCUMENT | PASSPORT, DRIVERS_LICENSE, NATIONAL_ID | + reason: + type: string + description: Human-readable description of the issue + example: Business address line 1 is required + Verification: + type: object + required: + - id + - customerId + - verificationStatus + - errors + - createdAt + properties: + id: + type: string + description: Unique identifier for this verification + example: Verification:019542f5-b3e7-1d02-0000-000000000001 + customerId: + type: string + description: The ID of the customer being verified + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + verificationStatus: + $ref: '#/components/schemas/VerificationStatus' + errors: + type: array + description: List of issues preventing verification from proceeding. Empty when verificationStatus is APPROVED or IN_PROGRESS. + items: + $ref: '#/components/schemas/VerificationError' + createdAt: + type: string + format: date-time + description: When this verification was created + example: '2025-10-03T12:00:00Z' + updatedAt: + type: string + format: date-time + description: When this verification was last updated + example: '2025-10-03T12:00:00Z' + VerificationListResponse: type: object required: - data @@ -15438,9 +16694,9 @@ components: properties: data: type: array - description: List of beneficial owners matching the filter criteria + description: List of verifications matching the filter criteria items: - $ref: '#/components/schemas/BeneficialOwner' + $ref: '#/components/schemas/Verification' hasMore: type: boolean description: Indicates if more results are available beyond this page @@ -15450,393 +16706,606 @@ components: totalCount: type: integer description: Total number of results matching the criteria - BeneficialOwnerCreateRequest: + VerificationRequest: type: object required: - customerId - - roles - - ownershipPercentage - - personalInfo properties: customerId: type: string - description: The ID of the business customer this beneficial owner is associated with + description: The ID of the customer to verify example: Customer:019542f5-b3e7-1d02-0000-000000000001 - roles: - type: array - items: - $ref: '#/components/schemas/BeneficialOwnerRole' - description: Roles of this person within the business - example: - - UBO - - DIRECTOR - ownershipPercentage: - type: integer - description: Percentage of ownership in the business (0-100). Relevant when role includes UBO. - minimum: 0 - maximum: 100 - example: 51 - personalInfo: - $ref: '#/components/schemas/BeneficialOwnerPersonalInfo' - BeneficialOwnerPersonalInfoUpdate: + ExternalAccountReference: type: object - description: Partial update for beneficial owner personal information. Only provided fields are updated. + required: + - accountId properties: - firstName: - type: string - description: First name of the individual - example: Jane - middleName: - type: string - description: Middle name of the individual - example: Marie - lastName: - type: string - description: Last name of the individual - example: Smith - birthDate: - type: string - format: date - description: Date of birth in ISO 8601 format (YYYY-MM-DD) - example: '1978-06-15' - nationality: - type: string - description: Country of nationality (ISO 3166-1 alpha-2) - example: US - email: - type: string - format: email - description: Email address of the individual - example: jane.smith@acmecorp.com - phoneNumber: + accountId: type: string - description: Phone number in E.164 format - example: '+14155550192' - pattern: ^\+[1-9]\d{1,14}$ - address: - $ref: '#/components/schemas/Address' - idType: - $ref: '#/components/schemas/IdentificationType' - identifier: + description: Reference to an external account ID + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + InternalAccountReference: + type: object + required: + - accountId + properties: + accountId: type: string - description: The identification number or value - example: 123-45-6789 - countryOfIssuance: + description: Reference to an internal account ID + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + TransferInRequest: + type: object + required: + - source + - destination + properties: + source: + $ref: '#/components/schemas/ExternalAccountReference' + description: Source external account details + destination: + $ref: '#/components/schemas/InternalAccountReference' + description: Destination internal account details + amount: + type: integer + format: int64 + description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) + example: 12550 + TransactionStatus: + type: string + enum: + - CREATED + - PENDING + - PROCESSING + - COMPLETED + - REJECTED + - FAILED + - REFUNDED + - EXPIRED + description: | + Status of a payment transaction. + + | Status | Description | + |--------|-------------| + | `CREATED` | Initial lookup has been created | + | `PENDING` | Quote has been created | + | `PROCESSING` | Funding has been received and payment initiated | + | `COMPLETED` | Cross border payment has been received, converted and payment has been sent to the offramp network | + | `REJECTED` | Receiving institution or wallet rejected payment, payment has been refunded | + | `FAILED` | An error occurred during payment | + | `REFUNDED` | Payment was unable to complete and refunded | + | `EXPIRED` | Quote has expired | + TransactionDestinationType: + type: string + enum: + - ACCOUNT + - UMA_ADDRESS + description: Type of transaction destination + example: ACCOUNT + BaseTransactionDestination: + type: object + required: + - destinationType + properties: + destinationType: + $ref: '#/components/schemas/TransactionDestinationType' + currency: type: string - description: Country that issued the identification (ISO 3166-1 alpha-2) - example: US - BeneficialOwnerUpdateRequest: + description: Currency code for the destination + example: EUR + AccountTransactionDestination: + title: Account Destination + allOf: + - $ref: '#/components/schemas/BaseTransactionDestination' + - type: object + required: + - accountId + - destinationType + properties: + destinationType: + type: string + enum: + - ACCOUNT + accountId: + type: string + description: Destination account identifier + example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + description: Destination account details + UmaAddressTransactionDestination: + title: UMA Address Destination + allOf: + - $ref: '#/components/schemas/BaseTransactionDestination' + - type: object + required: + - umaAddress + - destinationType + properties: + destinationType: + type: string + enum: + - UMA_ADDRESS + umaAddress: + type: string + description: UMA address of the recipient + example: $receiver@uma.domain.com + description: UMA address destination details + TransactionDestinationOneOf: + oneOf: + - $ref: '#/components/schemas/AccountTransactionDestination' + - $ref: '#/components/schemas/UmaAddressTransactionDestination' + discriminator: + propertyName: destinationType + mapping: + ACCOUNT: '#/components/schemas/AccountTransactionDestination' + UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionDestination' + CounterpartyInformation: type: object - properties: - roles: - type: array - items: - $ref: '#/components/schemas/BeneficialOwnerRole' - description: Roles of this person within the business - example: - - UBO - - DIRECTOR - ownershipPercentage: - type: integer - description: Percentage of ownership in the business (0-100) - minimum: 0 - maximum: 100 - example: 51 - personalInfo: - $ref: '#/components/schemas/BeneficialOwnerPersonalInfoUpdate' - DocumentType: - type: string - enum: - - PASSPORT - - DRIVERS_LICENSE - - NATIONAL_ID - - PROOF_OF_ADDRESS - - BANK_STATEMENT - - TAX_RETURN - - CERTIFICATE_OF_INCORPORATION - - ARTICLES_OF_INCORPORATION - - ARTICLES_OF_ASSOCIATION - - STATE_REGISTRY_EXCERPT - - GOOD_STANDING_CERTIFICATE - - INFORMATION_STATEMENT - - INCUMBENCY_CERTIFICATE - - BUSINESS_LICENSE - - SHAREHOLDER_REGISTER - - POWER_OF_ATTORNEY - - UTILITY_BILL - - ELECTRICITY_BILL - - RENT_OR_LEASE_AGREEMENT - - DIRECTOR_REGISTRY - - TRUST_AGREEMENT - - STATE_COMPANY_REGISTRY - - PARTNERSHIP_CONTROL_AGREEMENT - - PARTNERSHIP_AGREEMENT - - SELFIE - - OTHER - description: |- - Type of identity or business verification document. Document types are grouped by verification category: - **Identity** — PASSPORT, DRIVERS_LICENSE, NATIONAL_ID - **Business — Legal presence** — CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT - **Business — Control structure** — DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT - **Business — Ownership structure** — SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT - **Proof of address** — UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN - example: PASSPORT - Document: + description: Additional information about the counterparty, if available and relevant to the transaction and platform. + additionalProperties: true + example: + FULL_NAME: John Sender + BIRTH_DATE: '1985-06-15' + NATIONALITY: DE + Transaction: type: object required: - id - - documentHolder - - documentType - - country - - fileName - - createdAt + - status + - type + - destination + - customerId + - platformCustomerId properties: id: type: string - description: Unique identifier for this document - example: Document:019542f5-b3e7-1d02-0000-000000000001 - documentHolder: - type: string - description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. - example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 - documentType: - $ref: '#/components/schemas/DocumentType' - side: - type: string - enum: - - FRONT - - BACK - description: Which side of the document this upload represents. Relevant for two-sided documents like driver's licenses or national IDs. - example: FRONT - country: - type: string - description: Country that issued the document (ISO 3166-1 alpha-2) - example: US - documentNumber: + description: Unique identifier for the transaction + example: Transaction:019542f5-b3e7-1d02-0000-000000000004 + status: + $ref: '#/components/schemas/TransactionStatus' + type: + $ref: '#/components/schemas/TransactionType' + destination: + $ref: '#/components/schemas/TransactionDestinationOneOf' + customerId: type: string - description: Document identification number (e.g., passport number) - example: A12345678 - issuingAuthority: + description: System ID of the customer (sender for outgoing, recipient for incoming) + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: type: string - description: Name of the government agency or organization that issued the document - example: U.S. Department of State - fileName: + description: Platform-specific ID of the customer (sender for outgoing, recipient for incoming) + example: 18d3e5f7b4a9c2 + settledAt: type: string - description: Original file name of the uploaded document - example: passport_scan.pdf + format: date-time + description: When the payment was or will be settled + example: '2025-08-15T14:30:00Z' createdAt: type: string format: date-time - description: When this document was uploaded - example: '2025-10-03T12:00:00Z' + description: When the transaction was created + example: '2025-08-15T14:25:18Z' updatedAt: type: string format: date-time - description: When this document was last updated - example: '2025-10-03T12:00:00Z' - DocumentListResponse: + description: When the transaction was last updated + example: '2025-08-15T14:30:00Z' + receiptDeliveryConfirmedAt: + type: string + format: date-time + description: The time at which the platform confirmed delivery of the receipt to their customer. + example: '2025-08-15T14:31:00Z' + agentId: + type: string + description: If this transaction was initiated by an agent, the system-generated ID of that agent. Absent for platform-initiated transactions. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 + description: + type: string + description: Optional memo or description for the payment + example: 'Payment for invoice #1234' + counterpartyInformation: + $ref: '#/components/schemas/CounterpartyInformation' + TransactionSourceType: + type: string + enum: + - ACCOUNT + - UMA_ADDRESS + - REALTIME_FUNDING + description: Type of transaction source + example: ACCOUNT + BaseTransactionSource: + type: object + required: + - sourceType + properties: + sourceType: + $ref: '#/components/schemas/TransactionSourceType' + currency: + type: string + description: Currency code for the source + example: USD + AccountTransactionSource: + title: Account Source + allOf: + - $ref: '#/components/schemas/BaseTransactionSource' + - type: object + required: + - accountId + - sourceType + properties: + sourceType: + type: string + enum: + - ACCOUNT + accountId: + type: string + description: Source account identifier + example: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + description: Source account details + UmaAddressTransactionSource: + title: UMA Address Source + allOf: + - $ref: '#/components/schemas/BaseTransactionSource' + - type: object + required: + - umaAddress + - sourceType + properties: + sourceType: + type: string + enum: + - UMA_ADDRESS + umaAddress: + type: string + description: UMA address of the sender + example: $sender@uma.domain.com + description: UMA address source details + RealtimeFundingTransactionSource: + title: External Funding Source + allOf: + - $ref: '#/components/schemas/BaseTransactionSource' + - type: object + required: + - currency + - sourceType + properties: + sourceType: + type: string + enum: + - REALTIME_FUNDING + customerId: + type: string + description: The customer on whose behalf the transaction was initiated. + example: Customer:019542f5-b3e7-1d02-0000-000000000009 + currency: + type: string + description: Currency code for the funding source + example: USDC + accountHolderName: + type: string + description: The name of the originator (sender) of the payment. + example: John Sender + accountIdentifier: + type: string + description: The originator's account number or IBAN. May be masked or partial depending on the rail. + example: '****6789' + bankName: + type: string + description: The name of the originating bank. + example: Chase Bank + bankIdentifier: + type: string + description: The identifier of the originating bank, such as a routing number, BIC, or SWIFT code. + example: '021000021' + paymentRail: + description: The payment rail the funds arrived on. + allOf: + - $ref: '#/components/schemas/PaymentRail' + remittanceInformation: + type: string + description: 'Free-form information about the payment provided by the originator. The source field depends on the payment rail: the Addenda record for ACH, the OBI / beneficiary information for wires, and the remittanceInformation field for RTP and FedNow.' + example: '12345' + endToEndId: + type: string + description: The originator's own end-to-end reference for the payment. + example: E2E-9f2c6b6f + traceNumber: + type: string + description: Rail-level tracking identifier for the payment, such as an ACH trace number or a wire IMAD/OMAD, useful for reconciliation. + example: '021000020123456' + description: Transaction was funded using an external funding source. All originator fields are optional and populated on a best-effort basis depending on what the funding source provides. + TransactionSourceOneOf: + oneOf: + - $ref: '#/components/schemas/AccountTransactionSource' + - $ref: '#/components/schemas/UmaAddressTransactionSource' + - $ref: '#/components/schemas/RealtimeFundingTransactionSource' + discriminator: + propertyName: sourceType + mapping: + ACCOUNT: '#/components/schemas/AccountTransactionSource' + UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionSource' + REALTIME_FUNDING: '#/components/schemas/RealtimeFundingTransactionSource' + ReconciliationInstructions: type: object - required: - - data - - hasMore + minProperties: 1 properties: - data: - type: array - description: List of documents matching the filter criteria - items: - $ref: '#/components/schemas/Document' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: + reference: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: - type: integer - description: Total number of results matching the criteria - BaseDocumentRequest: + description: Unique reference code to include with the payment to match it with the correct incoming transaction, when available. + example: UMA-Q12345-REF + transactionHash: + type: string + description: Transaction hash for the crypto transfer that delivered funds to the transaction destination, when available. + example: '0x9f2c6b6f4b6c8f2a8d9e0b1c2d3e4f5061728394a5b6c7d8e9f00112233445566' + IncomingRateDetails: + description: 'Details about the rate and fees for an incoming transaction. Note: `gridApiFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' type: object required: - - file - - documentType - - country + - gridApiMultiplier + - gridApiFixedFee + - gridApiVariableFeeRate + - gridApiVariableFeeAmount properties: - file: - type: string - format: binary - description: The document file (PDF, JPEG, or PNG, max 10 MB) - documentType: - $ref: '#/components/schemas/DocumentType' - side: - type: string - enum: - - FRONT - - BACK - description: Which side of the document (for two-sided documents like driver's licenses) - example: FRONT - country: - type: string - description: Country that issued the document (ISO 3166-1 alpha-2) - example: US - documentNumber: - type: string - description: Document identification number (e.g., passport number) - example: A12345678 - issuingAuthority: - type: string - description: Name of the government agency or organization that issued the document - example: U.S. Department of State - DocumentUploadRequest: - title: Document Upload Request + gridApiMultiplier: + type: number + format: double + description: The underlying multiplier from the mSATS to the receiving currency, including variable fees. + exclusiveMinimum: 0 + example: 0.925 + gridApiFixedFee: + type: integer + format: int64 + description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). + minimum: 0 + example: 10 + gridApiVariableFeeRate: + type: number + format: double + description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the receiving currency amount. + minimum: 0 + example: 0.003 + gridApiVariableFeeAmount: + type: number + format: int64 + description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). This is the receiving amount times gridApiVariableFeeRate. + minimum: 0 + example: 30 + IncomingTransactionFailureReason: + type: string + enum: + - LNURLP_FAILED + - PAY_REQUEST_FAILED + - PAYMENT_APPROVAL_WEBHOOK_ERROR + - PAYMENT_APPROVAL_TIMED_OUT + - OFFRAMP_FAILED + - MISSING_MANDATORY_PAYEE_DATA + - QUOTE_EXPIRED + - QUOTE_EXECUTION_FAILED + description: Reason for failure of an incoming transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. + IncomingTransaction: + title: Incoming Transaction allOf: - - $ref: '#/components/schemas/BaseDocumentRequest' + - $ref: '#/components/schemas/Transaction' - type: object required: - - documentHolder + - type + - receivedAmount properties: - documentHolder: + type: type: string - description: ID of the entity that owns this document. Can be a Customer ID or a BeneficialOwner ID. - example: BeneficialOwner:019542f5-b3e7-1d02-0000-000000000001 - DocumentReplaceRequest: - title: Document Replace Request - allOf: - - $ref: '#/components/schemas/BaseDocumentRequest' - VerificationStatus: - type: string - enum: - - RESOLVE_ERRORS - - PENDING_MANUAL_REVIEW - - IN_PROGRESS - - APPROVED - - REJECTED - - READY_FOR_VERIFICATION - description: Current status of the KYC/KYB verification - example: RESOLVE_ERRORS - VerificationErrorType: + enum: + - INCOMING + source: + $ref: '#/components/schemas/TransactionSourceOneOf' + receivedAmount: + $ref: '#/components/schemas/CurrencyAmount' + description: Amount received in the recipient's currency + fees: + type: integer + format: int64 + description: The total fees available from the receive quote in the smallest unit of the receiving currency (eg. cents). + minimum: 0 + example: 10 + reconciliationInstructions: + $ref: '#/components/schemas/ReconciliationInstructions' + description: Included for all transactions except those with "CREATED" status + rateDetails: + $ref: '#/components/schemas/IncomingRateDetails' + description: Details about the rate and fees for the transaction. + failureReason: + $ref: '#/components/schemas/IncomingTransactionFailureReason' + description: If the transaction failed, this field provides the reason for failure. + OutgoingTransactionStatus: type: string enum: - - MISSING_FIELD - - INVALID_FIELD - - MISSING_LEGAL_PRESENCE_DOCUMENT - - MISSING_CONTROL_STRUCTURE_DOCUMENT - - MISSING_OWNERSHIP_STRUCTURE_DOCUMENT - - MISSING_PROOF_OF_ADDRESS_DOCUMENT - - MISSING_IDENTITY_DOCUMENT - - INVALID_DOCUMENT - - EXPIRED_DOCUMENT - - POOR_QUALITY_DOCUMENT - - SUSPECTED_FRAUD_DOCUMENT - - WRONG_DOCUMENT_TYPE - - INCOMPLETE_DOCUMENT - - UNREADABLE_DOCUMENT - - DOCUMENT_VERIFICATION_FAILED - - APPLICANT_SANCTIONED - - APPLICANT_FRAUD - - APPLICANT_CRIMINAL_RECORD - - APPLICANT_REJECTED - - MISSING_BENEFICIAL_OWNER - description: Type of verification error. The category-specific MISSING_*_DOCUMENT types indicate which document category is needed. Document quality types (POOR_QUALITY_DOCUMENT, SUSPECTED_FRAUD_DOCUMENT, etc.) indicate specific issues with uploaded documents. APPLICANT_* types indicate issues with the applicant themselves (sanctions, fraud, criminal records). - example: MISSING_FIELD - VerificationError: - type: object - required: - - resourceId - - type - - reason - properties: - resourceId: - type: string - description: ID of the resource with the issue (Customer, BeneficialOwner, or Document) - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: - $ref: '#/components/schemas/VerificationErrorType' - field: - type: string - description: Dot-notation path to the field with the issue. Present when type is MISSING_FIELD or INVALID_FIELD. - example: customer.address.line1 - acceptedDocumentTypes: - type: array - items: - $ref: '#/components/schemas/DocumentType' - description: |- - Document types that would satisfy this requirement. The integrator can upload any one of the listed types. Present when type is MISSING_LEGAL_PRESENCE_DOCUMENT, MISSING_CONTROL_STRUCTURE_DOCUMENT, MISSING_OWNERSHIP_STRUCTURE_DOCUMENT, MISSING_PROOF_OF_ADDRESS_DOCUMENT, MISSING_IDENTITY_DOCUMENT, INVALID_DOCUMENT, or EXPIRED_DOCUMENT. + - PENDING + - EXPIRED + - PROCESSING + - COMPLETED + - FAILED + description: | + Status of an outgoing payment transaction. - | Error Type | Accepted Document Types | - |---|---| - | MISSING_LEGAL_PRESENCE_DOCUMENT | CERTIFICATE_OF_INCORPORATION, ARTICLES_OF_INCORPORATION, ARTICLES_OF_ASSOCIATION, STATE_REGISTRY_EXCERPT | - | MISSING_CONTROL_STRUCTURE_DOCUMENT | DIRECTOR_REGISTRY, TRUST_AGREEMENT, STATE_COMPANY_REGISTRY, PARTNERSHIP_CONTROL_AGREEMENT | - | MISSING_OWNERSHIP_STRUCTURE_DOCUMENT | SHAREHOLDER_REGISTER, TRUST_AGREEMENT, PARTNERSHIP_AGREEMENT | - | MISSING_PROOF_OF_ADDRESS_DOCUMENT | UTILITY_BILL, RENT_OR_LEASE_AGREEMENT, ELECTRICITY_BILL, BANK_STATEMENT, TAX_RETURN | - | MISSING_IDENTITY_DOCUMENT | PASSPORT, DRIVERS_LICENSE, NATIONAL_ID | - reason: - type: string - description: Human-readable description of the issue - example: Business address line 1 is required - Verification: + | Status | Description | + |--------|-------------| + | `PENDING` | Quote is pending confirmation | + | `EXPIRED` | Quote wasn't executed before expiry window | + | `PROCESSING` | Executing the quote after receiving funds | + | `COMPLETED` | Payout successfully reached the destination | + | `FAILED` | Something went wrong — accompanied by a `failureReason` | + Refund: type: object required: - - id - - customerId - - verificationStatus - - errors - - createdAt - properties: - id: - type: string - description: Unique identifier for this verification - example: Verification:019542f5-b3e7-1d02-0000-000000000001 - customerId: - type: string - description: The ID of the customer being verified - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - verificationStatus: - $ref: '#/components/schemas/VerificationStatus' - errors: - type: array - description: List of issues preventing verification from proceeding. Empty when verificationStatus is APPROVED or IN_PROGRESS. - items: - $ref: '#/components/schemas/VerificationError' - createdAt: + - reference + - initiatedAt + - status + properties: + reference: + type: string + description: The unique reference ID of the refund + example: UMA-Q12345-REFUND + initiatedAt: type: string format: date-time - description: When this verification was created - example: '2025-10-03T12:00:00Z' - updatedAt: + description: When the refund was initiated + example: '2025-08-15T14:30:00Z' + settledAt: type: string format: date-time - description: When this verification was last updated - example: '2025-10-03T12:00:00Z' - VerificationListResponse: - type: object - required: - - data - - hasMore - properties: - data: - type: array - description: List of verifications matching the filter criteria - items: - $ref: '#/components/schemas/Verification' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: + description: When the refund was settled + example: '2025-08-15T14:35:00Z' + status: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: - type: integer - description: Total number of results matching the criteria - VerificationRequest: + enum: + - PENDING + - COMPLETED + - FAILED + description: Current status of the refund + example: COMPLETED + reason: + type: string + enum: + - TRANSACTION_FAILED + - USER_CANCELLATION + - TIMEOUT + description: Reason for the refund + example: TRANSACTION_FAILED + OutgoingRateDetails: + description: 'Details about the rate and fees for an outgoing transaction or quote. Note: `counterpartyFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' type: object required: - - customerId + - counterpartyMultiplier + - counterpartyFixedFee + - gridApiMultiplier + - gridApiFixedFee + - gridApiVariableFeeRate + - gridApiVariableFeeAmount properties: - customerId: - type: string - description: The ID of the customer to verify - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - ExternalAccountReference: + counterpartyMultiplier: + type: number + format: double + description: The underlying multiplier from mSATs to the receiving currency as returned by the counterparty institution. + exclusiveMinimum: 0 + example: 1.08 + counterpartyFixedFee: + type: integer + format: int64 + description: The fixed fee charged by the counterparty institution to execute the quote in the smallest unit of the receiving currency (eg. cents). + minimum: 0 + example: 10 + gridApiMultiplier: + type: number + format: double + description: The underlying multiplier from the sending currency to mSATS, including variable fees. + exclusiveMinimum: 0 + example: 0.925 + gridApiFixedFee: + type: integer + format: int64 + description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). + minimum: 0 + example: 10 + gridApiVariableFeeRate: + type: number + format: double + description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the sending currency amount. + minimum: 0 + example: 0.003 + gridApiVariableFeeAmount: + type: number + format: int64 + description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). This is the sending amount times gridApiVariableFeeRate. + minimum: 0 + example: 30 + OutgoingTransactionFailureReason: + type: string + enum: + - QUOTE_EXPIRED + - QUOTE_EXECUTION_FAILED + - LIGHTNING_PAYMENT_FAILED + - FUNDING_AMOUNT_MISMATCH + - COUNTERPARTY_POST_TX_FAILED + description: Reason for failure of an outgoing transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. + OutgoingTransaction: + title: Outgoing Transaction + allOf: + - $ref: '#/components/schemas/Transaction' + - type: object + required: + - type + - sentAmount + - source + properties: + status: + $ref: '#/components/schemas/OutgoingTransactionStatus' + type: + type: string + enum: + - OUTGOING + source: + $ref: '#/components/schemas/TransactionSourceOneOf' + sentAmount: + $ref: '#/components/schemas/CurrencyAmount' + description: Amount sent in the sender's currency + receivedAmount: + $ref: '#/components/schemas/CurrencyAmount' + description: Amount to be received by recipient in the recipient's currency + exchangeRate: + type: number + description: Number of sending currency units per receiving currency unit. + exclusiveMinimum: 0 + example: 1.08 + fees: + type: integer + format: int64 + description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). + minimum: 0 + example: 10 + reconciliationInstructions: + $ref: '#/components/schemas/ReconciliationInstructions' + description: Reconciliation details for this transaction, including crypto transaction hash when available. + quoteId: + type: string + description: The ID of the quote that was used to trigger this payment + example: Quote:019542f5-b3e7-1d02-0000-000000000006 + paymentInstructions: + type: array + description: Payment instructions for executing the payment. + items: + $ref: '#/components/schemas/PaymentInstructions' + example: + - accountOrWalletInfo: + accountType: USD_ACCOUNT + paymentRails: + - ACH + - WIRE + accountNumber: '1234567890' + routingNumber: '021000021' + bankName: Chase Bank + reference: UMA-Q12345-REF + instructionsNotes: Include reference UMA-Q12345-REF in memo + - accountOrWalletInfo: + accountType: SPARK_WALLET + assetType: BTC + address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu + invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs + refund: + $ref: '#/components/schemas/Refund' + description: The refund if transaction was refunded. + rateDetails: + $ref: '#/components/schemas/OutgoingRateDetails' + description: Details about the rate and fees for the transaction. + failureReason: + $ref: '#/components/schemas/OutgoingTransactionFailureReason' + description: If the transaction failed, this field provides the reason for failure. + TransactionOneOf: + oneOf: + - $ref: '#/components/schemas/IncomingTransaction' + - $ref: '#/components/schemas/OutgoingTransaction' + discriminator: + propertyName: type + mapping: + INCOMING: '#/components/schemas/IncomingTransaction' + OUTGOING: '#/components/schemas/OutgoingTransaction' + ExternalAccountDestinationReference: type: object required: - accountId @@ -15845,208 +17314,141 @@ components: type: string description: Reference to an external account ID example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - InternalAccountReference: - type: object - required: - - accountId - properties: - accountId: - type: string - description: Reference to an internal account ID - example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - TransferInRequest: + paymentRail: + description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. + allOf: + - $ref: '#/components/schemas/PaymentRail' + TransferOutRequest: type: object required: - source - destination properties: source: - $ref: '#/components/schemas/ExternalAccountReference' - description: Source external account details - destination: $ref: '#/components/schemas/InternalAccountReference' - description: Destination internal account details + description: Source internal account details + destination: + $ref: '#/components/schemas/ExternalAccountDestinationReference' + description: Destination external account details amount: type: integer format: int64 description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) example: 12550 - TransactionStatus: - type: string - enum: - - CREATED - - PENDING - - PROCESSING - - COMPLETED - - REJECTED - - FAILED - - REFUNDED - - EXPIRED - description: | - Status of a payment transaction. - - | Status | Description | - |--------|-------------| - | `CREATED` | Initial lookup has been created | - | `PENDING` | Quote has been created | - | `PROCESSING` | Funding has been received and payment initiated | - | `COMPLETED` | Cross border payment has been received, converted and payment has been sent to the offramp network | - | `REJECTED` | Receiving institution or wallet rejected payment, payment has been refunded | - | `FAILED` | An error occurred during payment | - | `REFUNDED` | Payment was unable to complete and refunded | - | `EXPIRED` | Quote has expired | - TransactionDestinationType: - type: string - enum: - - ACCOUNT - - UMA_ADDRESS - description: Type of transaction destination - example: ACCOUNT - BaseTransactionDestination: + CurrencyPreference: + type: object + required: + - currency + - estimatedExchangeRate + - min + - max + properties: + currency: + $ref: '#/components/schemas/Currency' + estimatedExchangeRate: + type: number + description: An estimated exchange rate from the sender's currency to this currency. This is not a locked rate and is subject to change when calling the quotes endpoint. + exclusiveMinimum: 0 + example: 1.08 + min: + type: integer + format: int64 + description: The minimum amount that can be received in this currency. + exclusiveMinimum: 0 + example: 1 + max: + type: integer + format: int64 + description: The maximum amount that can be received in this currency. + exclusiveMinimum: 0 + example: 1000000 + ReceiverLookupResponse: type: object required: - - destinationType + - supportedCurrencies + - lookupId properties: - destinationType: - $ref: '#/components/schemas/TransactionDestinationType' - currency: + supportedCurrencies: + type: array + description: List of currencies supported by the receiving account + items: + $ref: '#/components/schemas/CurrencyPreference' + requiredPayerDataFields: + type: array + description: Fields required by the receiving institution about the payer before payment can be completed + items: + $ref: '#/components/schemas/CounterpartyFieldDefinition' + lookupId: type: string - description: Currency code for the destination - example: EUR - AccountTransactionDestination: - title: Account Destination - allOf: - - $ref: '#/components/schemas/BaseTransactionDestination' - - type: object - required: - - accountId - - destinationType - properties: - destinationType: - type: string - enum: - - ACCOUNT - accountId: - type: string - description: Destination account identifier - example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - description: Destination account details - UmaAddressTransactionDestination: - title: UMA Address Destination + description: Unique identifier for the lookup. Needed in the subsequent create quote request. + example: Lookup:019542f5-b3e7-1d02-0000-000000000009 + ReceiverUmaLookupResponse: allOf: - - $ref: '#/components/schemas/BaseTransactionDestination' + - $ref: '#/components/schemas/ReceiverLookupResponse' - type: object required: - - umaAddress - - destinationType + - receiverUmaAddress properties: - destinationType: - type: string - enum: - - UMA_ADDRESS - umaAddress: + receiverUmaAddress: type: string - description: UMA address of the recipient - example: $receiver@uma.domain.com - description: UMA address destination details - TransactionDestinationOneOf: - oneOf: - - $ref: '#/components/schemas/AccountTransactionDestination' - - $ref: '#/components/schemas/UmaAddressTransactionDestination' - discriminator: - propertyName: destinationType - mapping: - ACCOUNT: '#/components/schemas/AccountTransactionDestination' - UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionDestination' - CounterpartyInformation: - type: object - description: Additional information about the counterparty, if available and relevant to the transaction and platform. - additionalProperties: true - example: - FULL_NAME: John Sender - BIRTH_DATE: '1985-06-15' - NATIONALITY: DE - Transaction: + description: The UMA address that was looked up + example: $receiver@uma.domain + Error412: type: object required: - - id + - message - status - - type - - destination - - customerId - - platformCustomerId + - code properties: - id: - type: string - description: Unique identifier for the transaction - example: Transaction:019542f5-b3e7-1d02-0000-000000000004 status: - $ref: '#/components/schemas/TransactionStatus' - type: - $ref: '#/components/schemas/TransactionType' - destination: - $ref: '#/components/schemas/TransactionDestinationOneOf' - customerId: - type: string - description: System ID of the customer (sender for outgoing, recipient for incoming) - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: - type: string - description: Platform-specific ID of the customer (sender for outgoing, recipient for incoming) - example: 18d3e5f7b4a9c2 - settledAt: - type: string - format: date-time - description: When the payment was or will be settled - example: '2025-08-15T14:30:00Z' - createdAt: - type: string - format: date-time - description: When the transaction was created - example: '2025-08-15T14:25:18Z' - updatedAt: - type: string - format: date-time - description: When the transaction was last updated - example: '2025-08-15T14:30:00Z' - receiptDeliveryConfirmedAt: - type: string - format: date-time - description: The time at which the platform confirmed delivery of the receipt to their customer. - example: '2025-08-15T14:31:00Z' - agentId: + type: integer + enum: + - 412 + description: HTTP status code + code: type: string - description: If this transaction was initiated by an agent, the system-generated ID of that agent. Absent for platform-initiated transactions. - example: Agent:019542f5-b3e7-1d02-0000-000000000042 - description: + description: | + | Error Code | Description | + |------------|-------------| + | UNSUPPORTED_UMA_VERSION | Counterparty doesn't support the Grid UMA version | + enum: + - UNSUPPORTED_UMA_VERSION + message: type: string - description: Optional memo or description for the payment - example: 'Payment for invoice #1234' - counterpartyInformation: - $ref: '#/components/schemas/CounterpartyInformation' - TransactionSourceType: + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + ReceiverExternalAccountLookupResponse: + allOf: + - $ref: '#/components/schemas/ReceiverLookupResponse' + - type: object + required: + - accountId + properties: + accountId: + type: string + description: The external account ID that was looked up + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + QuoteSourceType: type: string enum: - ACCOUNT - - UMA_ADDRESS - REALTIME_FUNDING - description: Type of transaction source + description: Type of quote funding source example: ACCOUNT - BaseTransactionSource: + BaseQuoteSource: type: object required: - sourceType properties: sourceType: - $ref: '#/components/schemas/TransactionSourceType' - currency: - type: string - description: Currency code for the source - example: USD - AccountTransactionSource: - title: Account Source + $ref: '#/components/schemas/QuoteSourceType' + AccountQuoteSource: + title: Account allOf: - - $ref: '#/components/schemas/BaseTransactionSource' + - $ref: '#/components/schemas/BaseQuoteSource' - type: object required: - accountId @@ -16060,461 +17462,596 @@ components: type: string description: Source account identifier example: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + customerId: + type: string + description: Required when funding from an FBO account to identify the customer on whose behalf the transaction is being initiated. Otherwise, will default to the customerId of the account owner. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 description: Source account details - UmaAddressTransactionSource: - title: UMA Address Source + RealtimeFundingQuoteSource: + title: Real-time Funding allOf: - - $ref: '#/components/schemas/BaseTransactionSource' + - $ref: '#/components/schemas/BaseQuoteSource' - type: object required: - - umaAddress + - currency - sourceType properties: sourceType: type: string enum: - - UMA_ADDRESS - umaAddress: + - REALTIME_FUNDING + customerId: type: string - description: UMA address of the sender - example: $sender@uma.domain.com - description: UMA address source details - RealtimeFundingTransactionSource: - title: External Funding Source + description: Source customer ID. If this transaction is being initiated on behalf of a customer, this is required. If customerId is not provided, the quote will be created on behalf of the platform itself. + example: Customer:019542f5-b3e7-1d02-0000-000000000009 + currency: + type: string + description: Currency code for the funding source. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. + example: USD + cryptoNetwork: + type: string + description: 'The crypto network to use for the funding source. Required when `currency` is a stablecoin (e.g. USDC, USDT). Specifies which network the customer will deposit on, so the correct deposit address can be generated. Example values: `SOLANA`, `ETHEREUM`, `BASE`, `POLYGON`, `SPARK`, `LIGHTNING`, `BITCOIN`.' + example: SOLANA + description: Fund the quote using a real-time funding source (RTP, SEPA Instant, Spark, Stables, etc.). This will require manual just-in-time funding using `paymentInstructions` in the response. Because quotes expire quickly, this option is only valid for instant payment methods. Do not try to fund a quote with a non-instant payment method (ACH, etc.). + QuoteSourceOneOf: + oneOf: + - $ref: '#/components/schemas/AccountQuoteSource' + - $ref: '#/components/schemas/RealtimeFundingQuoteSource' + discriminator: + propertyName: sourceType + mapping: + ACCOUNT: '#/components/schemas/AccountQuoteSource' + REALTIME_FUNDING: '#/components/schemas/RealtimeFundingQuoteSource' + DestinationType: + type: string + enum: + - ACCOUNT + - UMA_ADDRESS + description: Type of payment destination + example: ACCOUNT + BaseDestination: + type: object + required: + - destinationType + properties: + destinationType: + $ref: '#/components/schemas/DestinationType' + AccountDestination: + title: Account allOf: - - $ref: '#/components/schemas/BaseTransactionSource' + - $ref: '#/components/schemas/BaseDestination' - type: object required: - - currency - - sourceType + - accountId + - destinationType properties: - sourceType: + destinationType: type: string enum: - - REALTIME_FUNDING - customerId: - type: string - description: The customer on whose behalf the transaction was initiated. - example: Customer:019542f5-b3e7-1d02-0000-000000000009 - currency: - type: string - description: Currency code for the funding source - example: USDC - accountHolderName: - type: string - description: The name of the originator (sender) of the payment. - example: John Sender - accountIdentifier: - type: string - description: The originator's account number or IBAN. May be masked or partial depending on the rail. - example: '****6789' - bankName: - type: string - description: The name of the originating bank. - example: Chase Bank - bankIdentifier: + - ACCOUNT + accountId: type: string - description: The identifier of the originating bank, such as a routing number, BIC, or SWIFT code. - example: '021000021' + description: Destination account identifier + example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 paymentRail: - description: The payment rail the funds arrived on. allOf: - $ref: '#/components/schemas/PaymentRail' - remittanceInformation: + - description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. + description: Destination account details + UmaAddressDestination: + title: UMA Address + allOf: + - $ref: '#/components/schemas/BaseDestination' + - type: object + required: + - umaAddress + - destinationType + properties: + destinationType: type: string - description: 'Free-form information about the payment provided by the originator. The source field depends on the payment rail: the Addenda record for ACH, the OBI / beneficiary information for wires, and the remittanceInformation field for RTP and FedNow.' - example: '12345' - endToEndId: + enum: + - UMA_ADDRESS + umaAddress: type: string - description: The originator's own end-to-end reference for the payment. - example: E2E-9f2c6b6f - traceNumber: + description: UMA address of the recipient + example: $receiver@uma.domain.com + currency: type: string - description: Rail-level tracking identifier for the payment, such as an ACH trace number or a wire IMAD/OMAD, useful for reconciliation. - example: '021000020123456' - description: Transaction was funded using an external funding source. All originator fields are optional and populated on a best-effort basis depending on what the funding source provides. - TransactionSourceOneOf: + description: Currency code for the destination. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. + example: EUR + description: UMA address destination details + QuoteDestinationOneOf: oneOf: - - $ref: '#/components/schemas/AccountTransactionSource' - - $ref: '#/components/schemas/UmaAddressTransactionSource' - - $ref: '#/components/schemas/RealtimeFundingTransactionSource' + - $ref: '#/components/schemas/AccountDestination' + - $ref: '#/components/schemas/UmaAddressDestination' discriminator: - propertyName: sourceType + propertyName: destinationType mapping: - ACCOUNT: '#/components/schemas/AccountTransactionSource' - UMA_ADDRESS: '#/components/schemas/UmaAddressTransactionSource' - REALTIME_FUNDING: '#/components/schemas/RealtimeFundingTransactionSource' - ReconciliationInstructions: + ACCOUNT: '#/components/schemas/AccountDestination' + UMA_ADDRESS: '#/components/schemas/UmaAddressDestination' + Quote: + type: object + required: + - id + - status + - expiresAt + - createdAt + - source + - destination + - sendingCurrency + - receivingCurrency + - totalSendingAmount + - totalReceivingAmount + - exchangeRate + - feesIncluded + - transactionId + properties: + id: + type: string + description: Unique identifier for this quote + example: Quote:019542f5-b3e7-1d02-0000-000000000006 + status: + type: string + enum: + - PENDING + - PROCESSING + - COMPLETED + - FAILED + - EXPIRED + description: Current status of the quote + example: PENDING + createdAt: + type: string + format: date-time + description: When this quote was created + example: '2025-10-03T12:00:00Z' + expiresAt: + type: string + format: date-time + description: 'Absolute UTC timestamp when the rate locked in this quote becomes invalid and the quote can no longer be executed. The window depends on the rail and corridor: instant rails (Lightning, Spark, USDC on Solana/Base/Polygon, RTP, SEPA Instant) typically expire in 1–5 minutes; corridors with longer settlement guarantees may have longer windows. Always rely on this timestamp rather than assuming a fixed window.' + example: '2025-10-03T12:05:00Z' + source: + $ref: '#/components/schemas/QuoteSourceOneOf' + destination: + $ref: '#/components/schemas/QuoteDestinationOneOf' + sendingCurrency: + $ref: '#/components/schemas/Currency' + description: Currency for the sending amount + receivingCurrency: + $ref: '#/components/schemas/Currency' + description: Currency for the receiving amount + totalSendingAmount: + type: integer + format: int64 + description: The total amount that will be sent in the smallest unit of the sending currency (eg. cents). + exclusiveMinimum: 0 + example: 123010 + totalReceivingAmount: + type: integer + format: int64 + description: The total amount that will be received in the smallest unit of the receiving currency (eg. cents). + exclusiveMinimum: 0 + example: 1000 + exchangeRate: + type: number + description: Number of sending currency units per receiving currency unit. + exclusiveMinimum: 0 + feesIncluded: + type: integer + format: int64 + description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' + minimum: 0 + example: 10 + paymentInstructions: + type: array + description: Payment instructions for executing the payment. This is not required when using an internal account source. + items: + $ref: '#/components/schemas/PaymentInstructions' + example: + - accountOrWalletInfo: + accountType: USD_ACCOUNT + paymentRails: + - ACH + - WIRE + accountNumber: '1234567890' + routingNumber: '021000021' + bankName: Chase Bank + reference: UMA-Q12345-REF + instructionsNotes: Include reference UMA-Q12345-REF in memo + - accountOrWalletInfo: + accountType: SPARK_WALLET + assetType: BTC + address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu + invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs + transactionId: + type: string + description: The ID of the transaction created from this quote. + example: Transaction:019542f5-b3e7-1d02-0000-000000000005 + counterpartyInformation: + $ref: '#/components/schemas/CounterpartyInformation' + description: Additional information about the counterparty, if available and required by the platform in their configuration. + rateDetails: + $ref: '#/components/schemas/OutgoingRateDetails' + description: Details about the rate and fees for the transaction. + QuoteLockSide: + type: string + enum: + - SENDING + - RECEIVING + description: The side of the quote which should be locked and specified in the `lockedCurrencyAmount`. For example, if I want to send exactly $5 MXN from my wallet, I would set this to "sending", and the `lockedCurrencyAmount` to 500 (in cents). If I want the receiver to receive exactly $10 USD, I would set this to "receiving" and the `lockedCurrencyAmount` to 10000 (in cents). + PurposeOfPayment: + type: string + description: The purpose of the payment. This may be required when sending to certain geographies (e.g. India). + enum: + - GIFT + - SELF + - GOODS_OR_SERVICES + - EDUCATION + - HEALTH_OR_MEDICAL + - REAL_ESTATE_PURCHASE + - TAX_PAYMENT + - LOAN_PAYMENT + - UTILITY_BILL + - DONATION + - TRAVEL + - OTHER + QuoteRequest: + type: object + required: + - source + - destination + - lockedCurrencySide + - lockedCurrencyAmount + properties: + lookupId: + type: string + description: |- + Lookup ID from a previous receiver lookup request. If provided, this can make the quote creation more efficient by reusing cached lookup data. + NOTE: This is required for UMA destinations due to counterparty institution requirements. See `senderCustomerInfo` for more information. + example: Lookup:019542f5-b3e7-1d02-0000-000000000009 + source: + $ref: '#/components/schemas/QuoteSourceOneOf' + destination: + $ref: '#/components/schemas/QuoteDestinationOneOf' + lockedCurrencySide: + $ref: '#/components/schemas/QuoteLockSide' + lockedCurrencyAmount: + type: integer + format: int64 + description: The amount to send/receive in the smallest unit of the locked currency (eg. cents). See `lockedCurrencySide` for more information. + exclusiveMinimum: 0 + maximum: 9000000000000000 + example: 1000 + immediatelyExecute: + type: boolean + description: |- + Whether to immediately execute the quote after creation. If true, the quote will be executed and the transaction will be created at the current exchange rate. It should only be used if you don't want to lock and view rate details before executing the quote. If you are executing a pre-existing quote, use the `/quotes/{quoteId}/execute` endpoint instead. This is false by default. + This can only be used for quotes with a `source` which is either an internal account, or has direct pull functionality (e.g. ACH pull with an external account). + Not supported when the `source` is an internal account of type `EMBEDDED_WALLET`: those transfers require a `Grid-Wallet-Signature` over the `payloadToSign` returned in the quote response, which is not available in a combined create-and-execute call. Create the quote first with `immediatelyExecute: false` and then call `POST /quotes/{quoteId}/execute` with the `Grid-Wallet-Signature` stamp header. + example: false + description: + type: string + description: Optional description/memo for the transfer + example: 'Invoice #1234 payment' + purposeOfPayment: + $ref: '#/components/schemas/PurposeOfPayment' + senderCustomerInfo: + type: object + additionalProperties: true + description: | + Key-value pairs of additional information about the sender which was requested by the destination. This is relevant when the destination requires more sender info than was provided during customer creation. + Any fields specified in `requiredPayerDataFields` from the response of the `/receiver/uma/{receiverUmaAddress}` (lookupUma) or `/receiver/external-account/{accountId}` (lookupExternalAccount) endpoints MUST be provided here if they were requested. If the destination did not request any additional information, this field can be omitted. + example: + FULL_NAME: Jane Receiver + NATIONALITY: FR + TransactionListResponse: type: object - minProperties: 1 + required: + - data + - hasMore properties: - reference: + data: + type: array + description: List of transactions matching the criteria + items: + $ref: '#/components/schemas/TransactionOneOf' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: type: string - description: Unique reference code to include with the payment to match it with the correct incoming transaction, when available. - example: UMA-Q12345-REF - transactionHash: + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of transactions matching the criteria (excluding pagination) + ConfirmReceiptDeliveryRequest: + type: object + properties: + receiptDeliveryConfirmedAt: type: string - description: Transaction hash for the crypto transfer that delivered funds to the transaction destination, when available. - example: '0x9f2c6b6f4b6c8f2a8d9e0b1c2d3e4f5061728394a5b6c7d8e9f00112233445566' - IncomingRateDetails: - description: 'Details about the rate and fees for an incoming transaction. Note: `gridApiFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' + format: date-time + description: The time at which the platform delivered the transaction receipt to their customer. If omitted, the current server time is used. + example: '2025-08-15T14:31:00Z' + ApprovePaymentRequest: + type: object + properties: + receiverCustomerInfo: + type: object + additionalProperties: true + description: Information about the recipient, provided by the platform if requested in the original webhook via `requestedReceiverCustomerInfoFields`. + RejectPaymentRequest: + type: object + properties: + reason: + type: string + description: Optional reason for rejecting the payment. This is just for debugging purposes or can be used for a platform's own purposes. + example: RESTRICTED_JURISDICTION + EstimateCryptoWithdrawalFeeRequest: type: object required: - - gridApiMultiplier - - gridApiFixedFee - - gridApiVariableFeeRate - - gridApiVariableFeeAmount + - internalAccountId + - currency + - cryptoNetwork + - amount + - destinationAddress properties: - gridApiMultiplier: - type: number - format: double - description: The underlying multiplier from the mSATS to the receiving currency, including variable fees. - exclusiveMinimum: 0 - example: 0.925 - gridApiFixedFee: + internalAccountId: + type: string + description: The ID of the crypto internal account to withdraw from. + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + currency: + type: string + description: The currency code of the asset to withdraw (e.g. USDC). + example: USDC + cryptoNetwork: + type: string + description: 'The blockchain network for the withdrawal. Example values: SOLANA, ETHEREUM, BASE, POLYGON, SPARK, LIGHTNING, BITCOIN.' + example: SOLANA + amount: type: integer - format: int64 - description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). - minimum: 0 - example: 10 - gridApiVariableFeeRate: - type: number - format: double - description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the receiving currency amount. - minimum: 0 - example: 0.003 - gridApiVariableFeeAmount: - type: number - format: int64 - description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the receiving currency (eg. cents). This is the receiving amount times gridApiVariableFeeRate. - minimum: 0 - example: 30 - IncomingTransactionFailureReason: - type: string - enum: - - LNURLP_FAILED - - PAY_REQUEST_FAILED - - PAYMENT_APPROVAL_WEBHOOK_ERROR - - PAYMENT_APPROVAL_TIMED_OUT - - OFFRAMP_FAILED - - MISSING_MANDATORY_PAYEE_DATA - - QUOTE_EXPIRED - - QUOTE_EXECUTION_FAILED - description: Reason for failure of an incoming transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. - IncomingTransaction: - title: Incoming Transaction + description: The amount to withdraw in the smallest unit of the currency. + example: 1000000 + destinationAddress: + type: string + description: The blockchain address to withdraw funds to. + example: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU + EstimateCryptoWithdrawalFeeResponse: + type: object + required: + - networkFee + - networkFeeAsset + - applicationFee + - totalFee + - netAmount + properties: + networkFee: + type: integer + description: The estimated network (gas) fee in the smallest unit of the network fee asset (e.g. lamports for SOL). This is provided for informational purposes to show the raw on-chain cost. Note that this value is denominated in networkFeeAsset, not in the withdrawal currency — it cannot be directly added to applicationFee or compared to totalFee. + example: 5000 + networkFeeAsset: + type: string + description: The asset used to pay the network fee (e.g. SOL for Solana transactions). + example: SOL + applicationFee: + type: integer + description: The application fee charged by the platform in the smallest unit of the withdrawal currency. Zero if no application fee applies. + example: 0 + totalFee: + type: integer + description: The total cost of the withdrawal in the smallest unit of the withdrawal currency. This equals the network fee converted to the withdrawal currency at current rates plus the application fee. This is the amount deducted from the withdrawal in addition to netAmount. + example: 5000 + netAmount: + type: integer + description: The net amount the recipient will receive after fees, in the smallest unit of the withdrawal currency. + example: 995000 + TestWebhookResponse: + type: object + required: + - response_status + properties: + url: + type: string + format: uri + description: URL where the webhook was sent + example: https://api.mycompany.com/webhooks/uma + response_status: + type: integer + description: The HTTP status code returned by the webhook endpoint + example: 200 + response_body: + type: string + description: The raw body content returned by the webhook endpoint in response to the request + BulkCustomerImportJobAccepted: + type: object + required: + - jobId + - status + properties: + jobId: + type: string + description: Unique identifier for the bulk import job + example: Job:019542f5-b3e7-1d02-0000-000000000006 + status: + type: string + enum: + - PENDING + - PROCESSING + GridError: + type: object + title: GridError + properties: + code: + type: string + description: Error code + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + BulkCustomerImportErrorEntry: allOf: - - $ref: '#/components/schemas/Transaction' + - $ref: '#/components/schemas/GridError' - type: object + description: Error information for a failed bulk import entry required: - - type - - receivedAmount + - correlationId properties: - type: + correlationId: type: string - enum: - - INCOMING - source: - $ref: '#/components/schemas/TransactionSourceOneOf' - receivedAmount: - $ref: '#/components/schemas/CurrencyAmount' - description: Amount received in the recipient's currency - fees: - type: integer - format: int64 - description: The total fees available from the receive quote in the smallest unit of the receiving currency (eg. cents). - minimum: 0 - example: 10 - reconciliationInstructions: - $ref: '#/components/schemas/ReconciliationInstructions' - description: Included for all transactions except those with "CREATED" status - rateDetails: - $ref: '#/components/schemas/IncomingRateDetails' - description: Details about the rate and fees for the transaction. - failureReason: - $ref: '#/components/schemas/IncomingTransactionFailureReason' - description: If the transaction failed, this field provides the reason for failure. - OutgoingTransactionStatus: - type: string - enum: - - PENDING - - EXPIRED - - PROCESSING - - COMPLETED - - FAILED - description: | - Status of an outgoing payment transaction. - - | Status | Description | - |--------|-------------| - | `PENDING` | Quote is pending confirmation | - | `EXPIRED` | Quote wasn't executed before expiry window | - | `PROCESSING` | Executing the quote after receiving funds | - | `COMPLETED` | Payout successfully reached the destination | - | `FAILED` | Something went wrong — accompanied by a `failureReason` | - Refund: + description: Platform customer ID or row number for the failed entry + example: biz456 + BulkCustomerImportJob: type: object required: - - reference - - initiatedAt + - id - status + - progress properties: - reference: - type: string - description: The unique reference ID of the refund - example: UMA-Q12345-REFUND - initiatedAt: - type: string - format: date-time - description: When the refund was initiated - example: '2025-08-15T14:30:00Z' - settledAt: + id: type: string - format: date-time - description: When the refund was settled - example: '2025-08-15T14:35:00Z' + description: Unique identifier for the bulk import job + example: Job:019542f5-b3e7-1d02-0000-000000000006 status: type: string enum: - PENDING + - PROCESSING - COMPLETED - FAILED - description: Current status of the refund - example: COMPLETED - reason: - type: string - enum: - - TRANSACTION_FAILED - - USER_CANCELLATION - - TIMEOUT - description: Reason for the refund - example: TRANSACTION_FAILED - OutgoingRateDetails: - description: 'Details about the rate and fees for an outgoing transaction or quote. Note: `counterpartyFixedFee` is denominated in the receiving currency, so its equivalent value in the sending currency fluctuates with the FX rate. As a result, the total fee on a subsequent quote for the same transfer may differ even if the underlying fee structure is unchanged.' - type: object - required: - - counterpartyMultiplier - - counterpartyFixedFee - - gridApiMultiplier - - gridApiFixedFee - - gridApiVariableFeeRate - - gridApiVariableFeeAmount - properties: - counterpartyMultiplier: - type: number - format: double - description: The underlying multiplier from mSATs to the receiving currency as returned by the counterparty institution. - exclusiveMinimum: 0 - example: 1.08 - counterpartyFixedFee: - type: integer - format: int64 - description: The fixed fee charged by the counterparty institution to execute the quote in the smallest unit of the receiving currency (eg. cents). - minimum: 0 - example: 10 - gridApiMultiplier: - type: number - format: double - description: The underlying multiplier from the sending currency to mSATS, including variable fees. - exclusiveMinimum: 0 - example: 0.925 - gridApiFixedFee: - type: integer - format: int64 - description: The fixed fee charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). - minimum: 0 - example: 10 - gridApiVariableFeeRate: - type: number - format: double - description: The variable fee rate charged by the Grid product to execute the quote as a percentage of the sending currency amount. - minimum: 0 - example: 0.003 - gridApiVariableFeeAmount: - type: number - format: int64 - description: The variable fee amount charged by the Grid product to execute the quote in the smallest unit of the sending currency (eg. cents). This is the sending amount times gridApiVariableFeeRate. - minimum: 0 - example: 30 - OutgoingTransactionFailureReason: - type: string - enum: - - QUOTE_EXPIRED - - QUOTE_EXECUTION_FAILED - - LIGHTNING_PAYMENT_FAILED - - FUNDING_AMOUNT_MISMATCH - - COUNTERPARTY_POST_TX_FAILED - description: Reason for failure of an outgoing transaction. This is used to provide more context on why a transaction failed. If the transaction is not in a failed state, this field is omitted. - OutgoingTransaction: - title: Outgoing Transaction - allOf: - - $ref: '#/components/schemas/Transaction' - - type: object + description: Current status of the job + example: PROCESSING + progress: + type: object required: - - type - - sentAmount - - source + - total + - processed + - successful + - failed properties: - status: - $ref: '#/components/schemas/OutgoingTransactionStatus' - type: - type: string - enum: - - OUTGOING - source: - $ref: '#/components/schemas/TransactionSourceOneOf' - sentAmount: - $ref: '#/components/schemas/CurrencyAmount' - description: Amount sent in the sender's currency - receivedAmount: - $ref: '#/components/schemas/CurrencyAmount' - description: Amount to be received by recipient in the recipient's currency - exchangeRate: - type: number - description: Number of sending currency units per receiving currency unit. - exclusiveMinimum: 0 - example: 1.08 - fees: + total: type: integer - format: int64 - description: The fees associated with the quote in the smallest unit of the sending currency (eg. cents). - minimum: 0 - example: 10 - reconciliationInstructions: - $ref: '#/components/schemas/ReconciliationInstructions' - description: Reconciliation details for this transaction, including crypto transaction hash when available. - quoteId: - type: string - description: The ID of the quote that was used to trigger this payment - example: Quote:019542f5-b3e7-1d02-0000-000000000006 - paymentInstructions: - type: array - description: Payment instructions for executing the payment. - items: - $ref: '#/components/schemas/PaymentInstructions' - example: - - accountOrWalletInfo: - accountType: USD_ACCOUNT - paymentRails: - - ACH - - WIRE - accountNumber: '1234567890' - routingNumber: '021000021' - bankName: Chase Bank - reference: UMA-Q12345-REF - instructionsNotes: Include reference UMA-Q12345-REF in memo - - accountOrWalletInfo: - accountType: SPARK_WALLET - assetType: BTC - address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu - invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs - refund: - $ref: '#/components/schemas/Refund' - description: The refund if transaction was refunded. - rateDetails: - $ref: '#/components/schemas/OutgoingRateDetails' - description: Details about the rate and fees for the transaction. - failureReason: - $ref: '#/components/schemas/OutgoingTransactionFailureReason' - description: If the transaction failed, this field provides the reason for failure. - TransactionOneOf: - oneOf: - - $ref: '#/components/schemas/IncomingTransaction' - - $ref: '#/components/schemas/OutgoingTransaction' - discriminator: - propertyName: type - mapping: - INCOMING: '#/components/schemas/IncomingTransaction' - OUTGOING: '#/components/schemas/OutgoingTransaction' - ExternalAccountDestinationReference: - type: object - required: - - accountId - properties: - accountId: + description: Total number of customers to process + example: 5000 + processed: + type: integer + description: Number of customers processed so far + example: 2500 + successful: + type: integer + description: Number of customers successfully created + example: 2450 + failed: + type: integer + description: Number of customers that failed to create + example: 50 + errors: + type: array + description: Detailed error information for failed entries + items: + $ref: '#/components/schemas/BulkCustomerImportErrorEntry' + completedAt: type: string - description: Reference to an external account ID - example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - paymentRail: - description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. - allOf: - - $ref: '#/components/schemas/PaymentRail' - TransferOutRequest: + format: date-time + description: Timestamp when the job completed (only present for COMPLETED or FAILED status) + example: '2025-08-15T14:32:00Z' + UmaInvitationCreateRequest: type: object required: - - source - - destination + - inviterUma properties: - source: - $ref: '#/components/schemas/InternalAccountReference' - description: Source internal account details - destination: - $ref: '#/components/schemas/ExternalAccountDestinationReference' - description: Destination external account details - amount: + inviterUma: + type: string + description: The UMA address of the customer creating the invitation + example: $inviter@uma.domain + firstName: + type: string + description: First name of the invitee to show as part of the invite + example: Alice + amountToSend: + description: | + An amount to send (in the smallest unit of the customer's currency) to the invitee when the invitation is claimed. + This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of + the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter + platform either does not send the payment or the payment fails, the invitee will not receive this amount. This + field is primarily used for display purposes on the claiming side of the invitation. type: integer format: int64 - description: Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC) example: 12550 - CurrencyPreference: + expiresAt: + type: string + format: date-time + description: When the invitation expires (if at all) + example: '2025-09-01T14:30:00Z' + UmaInvitation: type: object required: - - currency - - estimatedExchangeRate - - min - - max - properties: - currency: - $ref: '#/components/schemas/Currency' - estimatedExchangeRate: - type: number - description: An estimated exchange rate from the sender's currency to this currency. This is not a locked rate and is subject to change when calling the quotes endpoint. - exclusiveMinimum: 0 - example: 1.08 - min: - type: integer - format: int64 - description: The minimum amount that can be received in this currency. - exclusiveMinimum: 0 - example: 1 - max: - type: integer - format: int64 - description: The maximum amount that can be received in this currency. - exclusiveMinimum: 0 - example: 1000000 - ReceiverLookupResponse: + - code + - createdAt + - inviterUma + - status + - url + properties: + code: + type: string + description: The unique code of the invitation + example: 019542f5 + createdAt: + type: string + format: date-time + description: When the invitation was created + example: '2025-09-01T14:30:00Z' + claimedAt: + type: string + format: date-time + description: When the invitation was claimed if it has been claimed + example: '2025-09-01T14:30:00Z' + url: + type: string + description: The URL where this invitation can be claimed. + example: https://uma.me/i/019542f5 + expiresAt: + type: string + format: date-time + description: When the invitation expires (if at all) + example: '2025-09-01T14:30:00Z' + inviterUma: + type: string + description: The UMA address of the inviter + example: $inviter@uma.domain + inviteeUma: + type: string + description: The UMA address of the invitee + example: $invitee@uma.domain + status: + type: string + enum: + - PENDING + - CLAIMED + - EXPIRED + - CANCELLED + description: The status of the invitation + example: PENDING + firstName: + type: string + description: The inviter's first name. Will be displayed when the recipient clicks the invite link + example: Jane + amountToSend: + $ref: '#/components/schemas/CurrencyAmount' + description: |- + The amount to send to the invitee when the invitation is claimed. This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter platform either does not send the payment or the payment fails, the invitee will not receive this amount. This field is primarily used for display purposes on the claiming side of the invitation. + This field is useful for "send-by-link" style customer flows where an inviter can send a payment simply by sharing a link without knowing the receiver's UMA address. Note that these sends can only be sender-locked, meaning that the sender will not know ahead of time how much the receiver will receive in the receiving currency. + UmaInvitationClaimRequest: type: object required: - - supportedCurrencies - - lookupId + - inviteeUma properties: - supportedCurrencies: - type: array - description: List of currencies supported by the receiving account - items: - $ref: '#/components/schemas/CurrencyPreference' - requiredPayerDataFields: - type: array - description: Fields required by the receiving institution about the payer before payment can be completed - items: - $ref: '#/components/schemas/CounterpartyFieldDefinition' - lookupId: + inviteeUma: type: string - description: Unique identifier for the lookup. Needed in the subsequent create quote request. - example: Lookup:019542f5-b3e7-1d02-0000-000000000009 - ReceiverUmaLookupResponse: - allOf: - - $ref: '#/components/schemas/ReceiverLookupResponse' - - type: object - required: - - receiverUmaAddress - properties: - receiverUmaAddress: - type: string - description: The UMA address that was looked up - example: $receiver@uma.domain - Error412: + description: The UMA address of the customer claiming the invitation + example: $invitee@uma.domain + Error403: type: object required: - message @@ -16524,348 +18061,197 @@ components: status: type: integer enum: - - 412 + - 403 description: HTTP status code code: type: string description: | | Error Code | Description | |------------|-------------| - | UNSUPPORTED_UMA_VERSION | Counterparty doesn't support the Grid UMA version | + | FORBIDDEN | Insufficient permissions | + | USER_NOT_READY | Customer exists but is not ready for operation | + | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | + | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | enum: - - UNSUPPORTED_UMA_VERSION - message: - type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true - ReceiverExternalAccountLookupResponse: - allOf: - - $ref: '#/components/schemas/ReceiverLookupResponse' - - type: object - required: - - accountId - properties: - accountId: - type: string - description: The external account ID that was looked up - example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - QuoteSourceType: - type: string - enum: - - ACCOUNT - - REALTIME_FUNDING - description: Type of quote funding source - example: ACCOUNT - BaseQuoteSource: - type: object - required: - - sourceType - properties: - sourceType: - $ref: '#/components/schemas/QuoteSourceType' - AccountQuoteSource: - title: Account - allOf: - - $ref: '#/components/schemas/BaseQuoteSource' - - type: object - required: - - accountId - - sourceType - properties: - sourceType: - type: string - enum: - - ACCOUNT - accountId: - type: string - description: Source account identifier - example: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - customerId: - type: string - description: Required when funding from an FBO account to identify the customer on whose behalf the transaction is being initiated. Otherwise, will default to the customerId of the account owner. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - description: Source account details - RealtimeFundingQuoteSource: - title: Real-time Funding - allOf: - - $ref: '#/components/schemas/BaseQuoteSource' - - type: object - required: - - currency - - sourceType - properties: - sourceType: - type: string - enum: - - REALTIME_FUNDING - customerId: - type: string - description: Source customer ID. If this transaction is being initiated on behalf of a customer, this is required. If customerId is not provided, the quote will be created on behalf of the platform itself. - example: Customer:019542f5-b3e7-1d02-0000-000000000009 - currency: - type: string - description: Currency code for the funding source. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. - example: USD - cryptoNetwork: - type: string - description: 'The crypto network to use for the funding source. Required when `currency` is a stablecoin (e.g. USDC, USDT). Specifies which network the customer will deposit on, so the correct deposit address can be generated. Example values: `SOLANA`, `ETHEREUM`, `BASE`, `POLYGON`, `SPARK`, `LIGHTNING`, `BITCOIN`.' - example: SOLANA - description: Fund the quote using a real-time funding source (RTP, SEPA Instant, Spark, Stables, etc.). This will require manual just-in-time funding using `paymentInstructions` in the response. Because quotes expire quickly, this option is only valid for instant payment methods. Do not try to fund a quote with a non-instant payment method (ACH, etc.). - QuoteSourceOneOf: - oneOf: - - $ref: '#/components/schemas/AccountQuoteSource' - - $ref: '#/components/schemas/RealtimeFundingQuoteSource' - discriminator: - propertyName: sourceType - mapping: - ACCOUNT: '#/components/schemas/AccountQuoteSource' - REALTIME_FUNDING: '#/components/schemas/RealtimeFundingQuoteSource' - DestinationType: - type: string - enum: - - ACCOUNT - - UMA_ADDRESS - description: Type of payment destination - example: ACCOUNT - BaseDestination: - type: object - required: - - destinationType - properties: - destinationType: - $ref: '#/components/schemas/DestinationType' - AccountDestination: - title: Account - allOf: - - $ref: '#/components/schemas/BaseDestination' - - type: object - required: - - accountId - - destinationType - properties: - destinationType: - type: string - enum: - - ACCOUNT - accountId: - type: string - description: Destination account identifier - example: ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - paymentRail: - allOf: - - $ref: '#/components/schemas/PaymentRail' - - description: The payment rail to use for the transfer. Must be one of the rails supported by the destination account. If not specified, the system will select a default rail. - description: Destination account details - UmaAddressDestination: - title: UMA Address - allOf: - - $ref: '#/components/schemas/BaseDestination' - - type: object - required: - - umaAddress - - destinationType - properties: - destinationType: - type: string - enum: - - UMA_ADDRESS - umaAddress: - type: string - description: UMA address of the recipient - example: $receiver@uma.domain.com - currency: - type: string - description: Currency code for the destination. See [Supported Currencies](https://docs.lightspark.com/platform-overview/core-concepts/currencies-and-rails) for the full list of supported fiat and crypto currencies. - example: EUR - description: UMA address destination details - QuoteDestinationOneOf: - oneOf: - - $ref: '#/components/schemas/AccountDestination' - - $ref: '#/components/schemas/UmaAddressDestination' - discriminator: - propertyName: destinationType - mapping: - ACCOUNT: '#/components/schemas/AccountDestination' - UMA_ADDRESS: '#/components/schemas/UmaAddressDestination' - Quote: + - FORBIDDEN + - USER_NOT_READY + - COUNTERPARTY_NOT_ALLOWED + - VELOCITY_LIMIT_EXCEEDED + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + SandboxSendRequest: type: object required: - - id - - status - - expiresAt - - createdAt - - source - - destination - - sendingCurrency - - receivingCurrency - - totalSendingAmount - - totalReceivingAmount - - exchangeRate - - feesIncluded - - transactionId + - quoteId + - currencyCode properties: - id: + quoteId: type: string - description: Unique identifier for this quote + description: The unique identifier of the quote example: Quote:019542f5-b3e7-1d02-0000-000000000006 - status: - type: string - enum: - - PENDING - - PROCESSING - - COMPLETED - - FAILED - - EXPIRED - description: Current status of the quote - example: PENDING - createdAt: - type: string - format: date-time - description: When this quote was created - example: '2025-10-03T12:00:00Z' - expiresAt: + currencyCode: type: string - format: date-time - description: 'Absolute UTC timestamp when the rate locked in this quote becomes invalid and the quote can no longer be executed. The window depends on the rail and corridor: instant rails (Lightning, Spark, USDC on Solana/Base/Polygon, RTP, SEPA Instant) typically expire in 1–5 minutes; corridors with longer settlement guarantees may have longer windows. Always rely on this timestamp rather than assuming a fixed window.' - example: '2025-10-03T12:05:00Z' - source: - $ref: '#/components/schemas/QuoteSourceOneOf' - destination: - $ref: '#/components/schemas/QuoteDestinationOneOf' - sendingCurrency: - $ref: '#/components/schemas/Currency' - description: Currency for the sending amount - receivingCurrency: - $ref: '#/components/schemas/Currency' - description: Currency for the receiving amount - totalSendingAmount: + description: Currency code for the funds to be sent + example: USD + currencyAmount: type: integer format: int64 - description: The total amount that will be sent in the smallest unit of the sending currency (eg. cents). + description: The amount to send in the smallest unit of the currency (eg. cents). If not provided, the amount will be derived from the quote. exclusiveMinimum: 0 - example: 123010 - totalReceivingAmount: + example: 1000 + SandboxUmaReceiveRequest: + type: object + required: + - senderUmaAddress + - receivingCurrencyCode + - receivingCurrencyAmount + properties: + senderUmaAddress: + type: string + description: UMA address of the sender from the sandbox + example: $success.usd@sandbox.grid.uma.money + receiverUmaAddress: + type: string + description: UMA address of the receiver (optional if customerId is provided) + example: $receiver@uma.domain + customerId: + type: string + description: System ID of the receiver (optional if receiverUmaAddress is provided) + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + receivingCurrencyCode: + type: string + description: The currency code for the receiving amount + example: USD + receivingCurrencyAmount: type: integer format: int64 - description: The total amount that will be received in the smallest unit of the receiving currency (eg. cents). + description: The amount to be received in the smallest unit of the currency (eg. cents) exclusiveMinimum: 0 example: 1000 - exchangeRate: - type: number - description: Number of sending currency units per receiving currency unit. - exclusiveMinimum: 0 - feesIncluded: + SandboxFundRequest: + type: object + required: + - amount + properties: + amount: type: integer format: int64 - description: 'The fees associated with the quote in the smallest unit of the sending currency (eg. cents). Note: this value may fluctuate between quotes — some underlying fee components are defined in the receiving currency, so their equivalent in the sending currency moves with the FX rate. The fees shown here are locked only for the lifetime of this quote.' - minimum: 0 - example: 10 - paymentInstructions: + description: Amount to add in the smallest unit of the account's currency (e.g., cents for USD/EUR, satoshis for BTC) + exclusiveMinimum: 0 + maximum: 100000000000 + example: 100000 + UmaProvider: + type: object + properties: + name: + type: string + description: Name of the UMA Provider + example: Lightspark Group + supportedRegions: type: array - description: Payment instructions for executing the payment. This is not required when using an internal account source. items: - $ref: '#/components/schemas/PaymentInstructions' + type: string + description: Region(s) this UMA Provider operates in example: - - accountOrWalletInfo: - accountType: USD_ACCOUNT - paymentRails: - - ACH - - WIRE - accountNumber: '1234567890' - routingNumber: '021000021' - bankName: Chase Bank - reference: UMA-Q12345-REF - instructionsNotes: Include reference UMA-Q12345-REF in memo - - accountOrWalletInfo: - accountType: SPARK_WALLET - assetType: BTC - address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu - invoice: lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs - transactionId: + - US + domain: type: string - description: The ID of the transaction created from this quote. - example: Transaction:019542f5-b3e7-1d02-0000-000000000005 - counterpartyInformation: - $ref: '#/components/schemas/CounterpartyInformation' - description: Additional information about the counterparty, if available and required by the platform in their configuration. - rateDetails: - $ref: '#/components/schemas/OutgoingRateDetails' - description: Details about the rate and fees for the transaction. - QuoteLockSide: - type: string - enum: - - SENDING - - RECEIVING - description: The side of the quote which should be locked and specified in the `lockedCurrencyAmount`. For example, if I want to send exactly $5 MXN from my wallet, I would set this to "sending", and the `lockedCurrencyAmount` to 500 (in cents). If I want the receiver to receive exactly $10 USD, I would set this to "receiving" and the `lockedCurrencyAmount` to 10000 (in cents). - PurposeOfPayment: + description: Domain this VASP uses for UMA addresses + example: uma.me + logoUrl: + type: string + description: Logo URL for the VASP + format: uri + example: https://uma.me/logo.png + supportedCurrencies: + type: array + items: + $ref: '#/components/schemas/Currency' + description: List of currencies supported by this UMA Provider + example: + - code: USD + name: United States Dollar + symbol: $ + decimals: 2 + lei: + type: string + description: Legal Entity Identifier for the UMA Provider + example: 5493001KJTIIGC8Y1R12 + allowListStatus: + type: boolean + description: Whether this UMA Provider is on your allow list + example: true + UmaProviderListResponse: + type: object + properties: + data: + description: List of available UMA Providers using Grid + type: array + items: + $ref: '#/components/schemas/UmaProvider' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of transactions matching the criteria (excluding pagination) + Permission: type: string - description: The purpose of the payment. This may be required when sending to certain geographies (e.g. India). enum: - - GIFT - - SELF - - GOODS_OR_SERVICES - - EDUCATION - - HEALTH_OR_MEDICAL - - REAL_ESTATE_PURCHASE - - TAX_PAYMENT - - LOAN_PAYMENT - - UTILITY_BILL - - DONATION - - TRAVEL - - OTHER - QuoteRequest: + - VIEW + - TRANSACT + - MANAGE + description: 'Permission of an API token that determines what actions the token can perform: VIEW: Can view all data, including platform config, customers and transactions TRANSACT: Can send payments MANAGE: Can manage platform config, api tokens and customers' + ApiToken: type: object required: - - source - - destination - - lockedCurrencySide - - lockedCurrencyAmount + - id + - name + - permissions + - clientId + - createdAt + - updatedAt properties: - lookupId: - type: string - description: |- - Lookup ID from a previous receiver lookup request. If provided, this can make the quote creation more efficient by reusing cached lookup data. - NOTE: This is required for UMA destinations due to counterparty institution requirements. See `senderCustomerInfo` for more information. - example: Lookup:019542f5-b3e7-1d02-0000-000000000009 - source: - $ref: '#/components/schemas/QuoteSourceOneOf' - destination: - $ref: '#/components/schemas/QuoteDestinationOneOf' - lockedCurrencySide: - $ref: '#/components/schemas/QuoteLockSide' - lockedCurrencyAmount: - type: integer - format: int64 - description: The amount to send/receive in the smallest unit of the locked currency (eg. cents). See `lockedCurrencySide` for more information. - exclusiveMinimum: 0 - maximum: 9000000000000000 - example: 1000 - immediatelyExecute: - type: boolean - description: |- - Whether to immediately execute the quote after creation. If true, the quote will be executed and the transaction will be created at the current exchange rate. It should only be used if you don't want to lock and view rate details before executing the quote. If you are executing a pre-existing quote, use the `/quotes/{quoteId}/execute` endpoint instead. This is false by default. - This can only be used for quotes with a `source` which is either an internal account, or has direct pull functionality (e.g. ACH pull with an external account). - Not supported when the `source` is an internal account of type `EMBEDDED_WALLET`: those transfers require a `Grid-Wallet-Signature` over the `payloadToSign` returned in the quote response, which is not available in a combined create-and-execute call. Create the quote first with `immediatelyExecute: false` and then call `POST /quotes/{quoteId}/execute` with the `Grid-Wallet-Signature` stamp header. - example: false - description: + id: type: string - description: Optional description/memo for the transfer - example: 'Invoice #1234 payment' - purposeOfPayment: - $ref: '#/components/schemas/PurposeOfPayment' - senderCustomerInfo: - type: object - additionalProperties: true - description: | - Key-value pairs of additional information about the sender which was requested by the destination. This is relevant when the destination requires more sender info than was provided during customer creation. - Any fields specified in `requiredPayerDataFields` from the response of the `/receiver/uma/{receiverUmaAddress}` (lookupUma) or `/receiver/external-account/{accountId}` (lookupExternalAccount) endpoints MUST be provided here if they were requested. If the destination did not request any additional information, this field can be omitted. - example: - FULL_NAME: Jane Receiver - NATIONALITY: FR - TransactionListResponse: + description: System-generated unique identifier + example: Token:019542f5-b3e7-1d02-0000-000000000001 + name: + type: string + description: Name of the token + example: Sandbox read-only token + permissions: + type: array + description: A list of permissions granted to the token + items: + $ref: '#/components/schemas/Permission' + clientId: + type: string + description: An opaque identifier that should be used as a client_id (or username) in the HTTP Basic Authentication scheme when issuing http requests to Grid. + example: 01947d2284054f890000e63bca4810df + clientSecret: + type: string + description: The secret that should be used to authenticate against Grid API. This secret is not stored and will never be available again after creation. Platform must keep this secret secure as it grants access to the account. + example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + createdAt: + type: string + format: date-time + description: Creation timestamp + example: '2025-07-21T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + example: '2025-07-21T17:32:28Z' + TokenListResponse: type: object required: - data @@ -16873,9 +18259,9 @@ components: properties: data: type: array - description: List of transactions matching the criteria + description: List of tokens matching the filter criteria items: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/ApiToken' hasMore: type: boolean description: Indicates if more results are available beyond this page @@ -16884,295 +18270,411 @@ components: description: Cursor to retrieve the next page of results (only present if hasMore is true) totalCount: type: integer - description: Total number of transactions matching the criteria (excluding pagination) - ConfirmReceiptDeliveryRequest: + description: Total number of tokens matching the criteria (excluding pagination) + ApiTokenCreateRequest: type: object + required: + - name + - permissions properties: - receiptDeliveryConfirmedAt: + name: type: string - format: date-time - description: The time at which the platform delivered the transaction receipt to their customer. If omitted, the current server time is used. - example: '2025-08-15T14:31:00Z' - ApprovePaymentRequest: + description: Name of the token to help identify it + example: Sandbox read-only + permissions: + type: array + description: A list of permissions to grant to the token + items: + $ref: '#/components/schemas/Permission' + InternalAccountUpdateRequest: + title: Internal Account Update Request + description: Partial request body for `PATCH /internal-accounts/{id}`. At least one update field must be provided. On step 1 of the signed-retry flow Grid binds the submitted update fields into `payloadToSign`; on step 2 the client echoes the same fields back and Grid applies the update to the internal account. type: object properties: - receiverCustomerInfo: - type: object - additionalProperties: true - description: Information about the recipient, provided by the platform if requested in the original webhook via `requestedReceiverCustomerInfoFields`. - RejectPaymentRequest: + privateEnabled: + type: boolean + description: Whether wallet privacy should be enabled for the Embedded Wallet. + example: true + InternalAccountExportRequest: + title: Internal Account Export Request + description: Request body for `POST /internal-accounts/{id}/export`. The `clientPublicKey` is required on both steps of the signed-retry flow. On step 1 Grid binds it into `payloadToSign` so the subsequent stamp in `Grid-Wallet-Signature` commits to the target pubkey; on step 2 the client echoes the same `clientPublicKey` back and Grid uses it to encrypt the wallet credentials returned in the `200` response. type: object + required: + - clientPublicKey properties: - reason: + clientPublicKey: type: string - description: Optional reason for rejecting the payment. This is just for debugging purposes or can be used for a platform's own purposes. - example: RESTRICTED_JURISDICTION - EstimateCryptoWithdrawalFeeRequest: + description: Fresh P-256 public key, uncompressed SEC1 hex — 130 hex chars where the first two are `04` (the uncompressed-point indicator). Generate a new keypair for each export and discard the private key after decrypting the response. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + InternalAccountExportResponse: + title: Internal Account Export Response type: object required: - - internalAccountId - - currency - - cryptoNetwork - - amount - - destinationAddress + - id + - encryptedWalletCredentials properties: - internalAccountId: + id: type: string - description: The ID of the crypto internal account to withdraw from. - example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - currency: + description: The id of the internal account that was exported. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + encryptedWalletCredentials: type: string - description: The currency code of the asset to withdraw (e.g. USDC). - example: USDC - cryptoNetwork: + description: |- + Encrypted wallet mnemonic, sealed to the `clientPublicKey` from the request body using HPKE: DHKEM(P-256, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM. Decrypt with the matching private key, then manage the mnemonic securely because it is the master key of the self-custodial Embedded Wallet. + The value is a JSON string of the form `{"version": "v1.0.0", "data": "", "dataSignature": "", "enclaveQuorumPublic": ""}`. `data` hex-decodes to JSON `{"encappedPublic": "", "ciphertext": "", "organizationId": ""}`, where `encappedPublic` is the uncompressed SEC1 ephemeral public key. `dataSignature` is an ECDSA-P256-SHA256 signature over the `data` bytes produced by the issuer key in `enclaveQuorumPublic`; verify before decrypting. + In sandbox, `dataSignature` and `enclaveQuorumPublic` are empty strings. Clients should bypass attestation verification when calling against sandbox. + example: '{"version":"v1.0.0","data":"7b22656e6361707065645075626c6963223a22303433...","dataSignature":"3045022100c9...","enclaveQuorumPublic":"04a1b2c3..."}' + AuthMethodType: + type: string + enum: + - OAUTH + - EMAIL_OTP + - PASSKEY + description: |- + The type of authentication credential. + - `OAUTH`: OpenID Connect (OIDC) token issued by an identity provider such as Google or Apple. + - `EMAIL_OTP`: A one-time password delivered to the user's email address. + - `PASSKEY`: A WebAuthn passkey bound to the user's device. + AuthMethod: + type: object + required: + - id + - accountId + - type + - nickname + - createdAt + - updatedAt + properties: + id: type: string - description: 'The blockchain network for the withdrawal. Example values: SOLANA, ETHEREUM, BASE, POLYGON, SPARK, LIGHTNING, BITCOIN.' - example: SOLANA - amount: - type: integer - description: The amount to withdraw in the smallest unit of the currency. - example: 1000000 - destinationAddress: + description: System-generated unique identifier for the authentication credential. + example: AuthMethod:019542f5-b3e7-1d02-0000-000000000001 + accountId: type: string - description: The blockchain address to withdraw funds to. - example: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU - EstimateCryptoWithdrawalFeeResponse: + description: Identifier of the internal account that this credential authenticates. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + type: + $ref: '#/components/schemas/AuthMethodType' + credentialId: + type: string + description: Base64url-encoded WebAuthn credential identifier for this passkey. Present only for `PASSKEY` authentication credentials. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. + example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew + nickname: + type: string + description: Human-readable identifier for this credential. For EMAIL_OTP credentials this is the email address; for OAUTH credentials it is typically the email claim from the OIDC token; for PASSKEY credentials it is the validated nickname provided at registration time. + example: example@lightspark.com + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-04-08T15:30:01Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-04-08T15:35:00Z' + AuthCredentialListResponse: type: object required: - - networkFee - - networkFeeAsset - - applicationFee - - totalFee - - netAmount + - data properties: - networkFee: - type: integer - description: The estimated network (gas) fee in the smallest unit of the network fee asset (e.g. lamports for SOL). This is provided for informational purposes to show the raw on-chain cost. Note that this value is denominated in networkFeeAsset, not in the withdrawal currency — it cannot be directly added to applicationFee or compared to totalFee. - example: 5000 - networkFeeAsset: + data: + type: array + description: List of authentication credentials registered on the internal account. + items: + $ref: '#/components/schemas/AuthMethod' + AuthCredentialCreateRequest: + type: object + required: + - type + - accountId + properties: + type: + $ref: '#/components/schemas/AuthMethodType' + accountId: type: string - description: The asset used to pay the network fee (e.g. SOL for Solana transactions). - example: SOL - applicationFee: - type: integer - description: The application fee charged by the platform in the smallest unit of the withdrawal currency. Zero if no application fee applies. - example: 0 - totalFee: - type: integer - description: The total cost of the withdrawal in the smallest unit of the withdrawal currency. This equals the network fee converted to the withdrawal currency at current rates plus the application fee. This is the amount deducted from the withdrawal in addition to netAmount. - example: 5000 - netAmount: - type: integer - description: The net amount the recipient will receive after fees, in the smallest unit of the withdrawal currency. - example: 995000 - TestWebhookResponse: + description: Identifier of the internal account that this credential will authenticate. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + EmailOtpCredentialCreateRequestFields: type: object required: - - response_status + - type + properties: + type: + type: string + enum: + - EMAIL_OTP + description: Discriminator value identifying this as an email OTP credential. + EmailOtpCredentialCreateRequest: + title: Email OTP Credential Create Request + allOf: + - $ref: '#/components/schemas/AuthCredentialCreateRequest' + - $ref: '#/components/schemas/EmailOtpCredentialCreateRequestFields' + OauthCredentialCreateRequestFields: + type: object + required: + - type + - oidcToken + properties: + type: + type: string + enum: + - OAUTH + description: Discriminator value identifying this as an OAuth credential. + oidcToken: + type: string + description: OIDC ID token issued by the identity provider (e.g. Google, Apple). The token's `iss`, `aud`, and `sub` claims define the OAuth identity registered to this credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and `iat` less than 60 seconds before the request timestamp, but the signature segment may be a dummy value. + example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q + OauthCredentialCreateRequest: + title: OAuth Credential Create Request + allOf: + - $ref: '#/components/schemas/AuthCredentialCreateRequest' + - $ref: '#/components/schemas/OauthCredentialCreateRequestFields' + PasskeyAttestation: + title: Passkey Attestation + type: object + required: + - credentialId + - clientDataJson + - attestationObject properties: - url: + credentialId: type: string - format: uri - description: URL where the webhook was sent - example: https://api.mycompany.com/webhooks/uma - response_status: - type: integer - description: The HTTP status code returned by the webhook endpoint - example: 200 - response_body: + description: Base64url-encoded credential identifier produced by the authenticator at registration time. Typically the base64url of `PublicKeyCredential.rawId`. + example: AdKXJEch1aV5Wo7bj7qLHskVY4OoNaj9qu8TPdJ7kSAgUeRxWNngXlcNIGt4gexZGKVGcqZpqqWordXb_he1izY + clientDataJson: type: string - description: The raw body content returned by the webhook endpoint in response to the request - BulkCustomerImportJobAccepted: + description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.create()` call. Corresponds to `AuthenticatorAttestationResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.create"`.' + example: eyJjaGFsbGVuZ2UiOiJBcktRaTJ5QVlIUGxnbkpORkJsbmVJd2NoUWRXWEJPVHJkQi1BbU1VQjIxTHgiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0 + attestationObject: + type: string + description: Base64url-encoded CBOR attestation object produced by the authenticator during registration. Corresponds to `AuthenticatorAttestationResponse.attestationObject`. + example: o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFPdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQHSlyRHIdWleVqO24-6ix7JFWODqDWo_arvEz3Se5EgIFHkcVjZ4F5XDSBreIHsWRilRnKmaaqlqK3V2_4XtYs2pQECAyYgASFYID5PQTZQQg6haZFQWFzqfAOyQ_ENsMH8xxQ4GRiNPsqrIlggU8IVUOV8qpgk_Jh-OTaLuZL52KdX1fTht07X4DiQPow + transports: + type: array + items: + type: string + enum: + - usb + - nfc + - ble + - internal + - hybrid + description: Optional. WebAuthn transports as returned by `AuthenticatorAttestationResponse.getTransports()`. Values follow the W3C `AuthenticatorTransport` enum — pass the raw values through to Grid; provider-specific translation is handled server-side. Some authenticators return an empty array; omit the field or send `[]` in that case. + example: + - internal + - hybrid + PasskeyCredentialCreateRequestFields: type: object required: - - jobId - - status + - type + - nickname + - challenge + - attestation properties: - jobId: - type: string - description: Unique identifier for the bulk import job - example: Job:019542f5-b3e7-1d02-0000-000000000006 - status: + type: type: string enum: - - PENDING - - PROCESSING - GridError: - type: object - title: GridError - properties: - code: + - PASSKEY + description: Discriminator value identifying this as a passkey credential. + nickname: type: string - description: Error code - message: + description: 'Human-readable identifier for the passkey, chosen by the user at registration time (e.g. "iPhone Face-ID", "YubiKey 5C"). Leading and trailing whitespace is ignored. Must be 1-100 characters and may contain Unicode letters, numbers, spaces, and the following separators: period, underscore, hyphen, apostrophe, and parentheses. Shown back on AuthMethod responses and in credential listings.' + example: iPhone Face-ID + challenge: type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true - BulkCustomerImportErrorEntry: + description: Base64url-encoded WebAuthn challenge issued by the platform backend and passed to the client before `navigator.credentials.create()`. Grid verifies it matches the challenge embedded in the attestation's `clientDataJson`, binding the attestation to this registration. Must be single-use. + example: ArkQi2yAYHPlgnJNFBlneIwchQdWXBOTrdB-AmMUB21Lx + attestation: + $ref: '#/components/schemas/PasskeyAttestation' + PasskeyCredentialCreateRequest: + title: Passkey Credential Create Request allOf: - - $ref: '#/components/schemas/GridError' + - $ref: '#/components/schemas/AuthCredentialCreateRequest' + - $ref: '#/components/schemas/PasskeyCredentialCreateRequestFields' + AuthCredentialCreateRequestOneOf: + oneOf: + - $ref: '#/components/schemas/EmailOtpCredentialCreateRequest' + - $ref: '#/components/schemas/OauthCredentialCreateRequest' + - $ref: '#/components/schemas/PasskeyCredentialCreateRequest' + discriminator: + propertyName: type + mapping: + EMAIL_OTP: '#/components/schemas/EmailOtpCredentialCreateRequest' + OAUTH: '#/components/schemas/OauthCredentialCreateRequest' + PASSKEY: '#/components/schemas/PasskeyCredentialCreateRequest' + AuthMethodResponse: + title: Auth Method Response + description: |- + Strict wrapper around `AuthMethod`. Used directly as the registration response on `POST /auth/credentials` (all three credential types) and inside `AuthCredentialResponseOneOf` for the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/challenge`. The only difference from `AuthMethod` is `unevaluatedProperties: false`, which disambiguates the oneOf against `PasskeyAuthChallenge` — without the strictness, an `AuthMethod` with extra fields would ambiguously match both branches. + + For `EMAIL_OTP` credentials, responses that initiate or reissue an OTP challenge carry `otpEncryptionTargetBundle` so the client can HPKE-encrypt the OTP code in the subsequent `POST /auth/credentials/{id}/verify` call without the plaintext code ever transiting the server. First-time EMAIL_OTP wallet bootstrap registration can omit it; call `POST /auth/credentials/{id}/challenge` if it is absent. + allOf: + - $ref: '#/components/schemas/AuthMethod' - type: object - description: Error information for a failed bulk import entry - required: - - correlationId properties: - correlationId: + otpEncryptionTargetBundle: type: string - description: Platform customer ID or row number for the failed entry - example: biz456 - BulkCustomerImportJob: + description: HPKE encryption target bundle for a freshly initiated OTP challenge. Returned only on `EMAIL_OTP` responses that initiate or reissue an OTP challenge, such as `POST /auth/credentials/{id}/challenge` and the add-EMAIL_OTP signed-retry response. It is omitted from first-time EMAIL_OTP wallet bootstrap registration; call `POST /auth/credentials/{id}/challenge` for the new credential if it is absent. The client generates an ephemeral P-256 keypair (the Target Encryption Key, or TEK) and uses this bundle as the recipient when HPKE-encrypting `{otp_code, public_key}`; the encrypted payload is submitted as `encryptedOtpBundle` on `POST /auth/credentials/{id}/verify`. The bundle is one-time-use per OTP issuance — re-issue via `POST /auth/credentials/{id}/challenge` to obtain a fresh bundle. The matching TEK private key must remain on the client and is used to sign the `verificationToken` returned on the subsequent signed-retry. Treat the bundle as opaque and pass it to your HPKE library; the Global Accounts client-keys guide shows how. + example: '{"version":"v1.0.0","data":"7b227461726765745075626c6963...","dataSignature":"30450221...","enclaveQuorumPublic":"04a1b2c3..."}' + unevaluatedProperties: false + AuthSignedRequestChallenge: + title: Authentication Signed Request Challenge + description: |- + 202 response returned from Embedded Wallet Auth endpoints that require a signed retry — `POST /auth/credentials` (adding an additional credential), `DELETE /auth/credentials/{id}` (revoking a credential), `DELETE /auth/sessions/{id}` (revoking a session), and the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify` (the secure OTP login flow, where the client submits an `encryptedOtpBundle` and receives a `verificationToken` to sign for the second-leg session issuance). Carries the signing fields from `SignedRequestChallenge` plus the `type` of the authentication credential involved (being added, revoked, that issued the session being revoked, or being authenticated). The client already knows the target resource id from the request path / body it just sent, so nothing beyond `type` is echoed in the response. + + The keypair used to compute the stamp depends on the operation. For credential / session management retries, sign with the session API keypair of an existing verified credential on the same internal account. For the `EMAIL_OTP` verify retry, sign with the ephemeral Target Encryption Key (TEK) the client generated for this login — its public key is the one carried inside the `encryptedOtpBundle` and bound into the `verificationToken`, and it becomes the client's session API key on successful completion. + allOf: + - $ref: '#/components/schemas/SignedRequestChallenge' + - type: object + required: + - type + properties: + type: + $ref: '#/components/schemas/AuthMethodType' + description: 'Credential type relevant to this challenge: the credential type being added (`POST /auth/credentials`), revoked (`DELETE /auth/credentials/{id}`), or authenticated (`EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify`). For session revocation, this is the type of credential that issued the session (`DELETE /auth/sessions/{id}`).' + AuthCredentialVerifyRequest: type: object required: - - id - - status - - progress + - type properties: - id: - type: string - description: Unique identifier for the bulk import job - example: Job:019542f5-b3e7-1d02-0000-000000000006 - status: - type: string - enum: - - PENDING - - PROCESSING - - COMPLETED - - FAILED - description: Current status of the job - example: PROCESSING - progress: - type: object - required: - - total - - processed - - successful - - failed - properties: - total: - type: integer - description: Total number of customers to process - example: 5000 - processed: - type: integer - description: Number of customers processed so far - example: 2500 - successful: - type: integer - description: Number of customers successfully created - example: 2450 - failed: - type: integer - description: Number of customers that failed to create - example: 50 - errors: - type: array - description: Detailed error information for failed entries - items: - $ref: '#/components/schemas/BulkCustomerImportErrorEntry' - completedAt: - type: string - format: date-time - description: Timestamp when the job completed (only present for COMPLETED or FAILED status) - example: '2025-08-15T14:32:00Z' - UmaInvitationCreateRequest: + type: + $ref: '#/components/schemas/AuthMethodType' + EmailOtpCredentialVerifyRequestFields: type: object required: - - inviterUma + - type + - encryptedOtpBundle + description: Verify an email-OTP credential via the secure two-leg flow. The client HPKE-encrypts the OTP code (together with its public key) under the `otpEncryptionTargetBundle` returned from registration when present, or from `POST /auth/credentials/{id}/challenge` when registration omitted it or the OTP must be reissued, submits the result here, and receives `202` with a `payloadToSign` carrying a `verificationToken` bound to the client's public key. The client signs that token with the matching private key and retries this request with `Grid-Wallet-Signature` + `Request-Id` headers to obtain the session. Plaintext OTP codes are never sent over the wire. properties: - inviterUma: - type: string - description: The UMA address of the customer creating the invitation - example: $inviter@uma.domain - firstName: + type: type: string - description: First name of the invitee to show as part of the invite - example: Alice - amountToSend: - description: | - An amount to send (in the smallest unit of the customer's currency) to the invitee when the invitation is claimed. - This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of - the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter - platform either does not send the payment or the payment fails, the invitee will not receive this amount. This - field is primarily used for display purposes on the claiming side of the invitation. - type: integer - format: int64 - example: 12550 - expiresAt: + enum: + - EMAIL_OTP + description: Discriminator value identifying this as an email OTP verification. + encryptedOtpBundle: type: string - format: date-time - description: When the invitation expires (if at all) - example: '2025-09-01T14:30:00Z' - UmaInvitation: + description: |- + HPKE-sealed OTP attempt — the OTP code never reaches Grid in plaintext. The client generates a fresh ephemeral P-256 key pair (the session signing key pair it keeps once login completes), HPKE-encrypts `{otp_code, public_key}` (the code the user entered plus that key pair's public key) to the key in `otpEncryptionTargetBundle`, and submits the encrypted result here. The value is the `{encappedPublic, ciphertext}` JSON an HPKE library produces; the Global Accounts client-keys guide has a worked example. + + On success the response is `202` with a `payloadToSign` carrying a `verificationToken` bound to the public key sealed in this bundle. Sign that token with the matching private key, then retry this request with the full stamp in `Grid-Wallet-Signature` and the `requestId` in `Request-Id` to complete the flow and receive the session. The client keeps that private key as the session signing key, and its public key becomes the session API key. + example: '{"encappedPublic":"044f631a2d890bc6668d997ee184e190650d06adf970987568ec641214a00403b73effe1ef406c60a5cde8508a4484567ddb8056fbd493bee614cd727aef02a838","ciphertext":"1fa1023390a56539aa48cbb380aa28f544ed5cc04861566bb806e25ba026f14660eaf4140a05b388dd012eaa899759a6a92576cdca8c1b7d12e147bd96cc26ed9f74886794155d8ac5cf0fdc"}' + EmailOtpCredentialVerifyRequest: + title: Email OTP Credential Verify Request + allOf: + - $ref: '#/components/schemas/AuthCredentialVerifyRequest' + - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequestFields' + OauthCredentialVerifyRequestFields: type: object required: - - code - - createdAt - - inviterUma - - status - - url + - type + - oidcToken + - clientPublicKey properties: - code: - type: string - description: The unique code of the invitation - example: 019542f5 - createdAt: - type: string - format: date-time - description: When the invitation was created - example: '2025-09-01T14:30:00Z' - claimedAt: + type: type: string - format: date-time - description: When the invitation was claimed if it has been claimed - example: '2025-09-01T14:30:00Z' - url: + enum: + - OAUTH + description: Discriminator value identifying this as an OAuth verification. + oidcToken: type: string - description: The URL where this invitation can be claimed. - example: https://uma.me/i/019542f5 - expiresAt: + description: OIDC ID token issued by the identity provider. For reauthentication after a prior session expired, supply a fresh token — the token's `iat` claim must be less than 60 seconds before the request timestamp. The token identity (`iss`, `aud`, and `sub`) must match the registered OAuth credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and a `nonce` equal to `sha256(clientPublicKey)`, but the signature segment may be a dummy value. + example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q + clientPublicKey: type: string - format: date-time - description: When the invitation expires (if at all) - example: '2025-09-01T14:30:00Z' - inviterUma: + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (0x04 prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid encrypts the session signing key returned in the response to this public key. The key is ephemeral and one-time-use per verification request. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + OauthCredentialVerifyRequest: + title: OAuth Credential Verify Request + allOf: + - $ref: '#/components/schemas/AuthCredentialVerifyRequest' + - $ref: '#/components/schemas/OauthCredentialVerifyRequestFields' + PasskeyAssertion: + title: Passkey Assertion + type: object + description: WebAuthn assertion returned by `navigator.credentials.get()`. In sandbox, Grid validates the assertion against the registered passkey credential so the client-side flow can match production. In production, Turnkey validates the WebAuthn assertion. + required: + - credentialId + - clientDataJson + - authenticatorData + - signature + properties: + credentialId: type: string - description: The UMA address of the inviter - example: $inviter@uma.domain - inviteeUma: + description: Base64url-encoded credential identifier returned during the WebAuthn assertion. Corresponds to `PublicKeyCredential.rawId`. + example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew + clientDataJson: type: string - description: The UMA address of the invitee - example: $invitee@uma.domain - status: + description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.get()` call. Corresponds to `AuthenticatorAssertionResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.get"`.' + example: eyJjaGFsbGVuZ2UiOiJkRzkwWVd4c2VWVnVhWEYxWlZaaGJIVmxSWFpsY25sVWFXMWwiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uZ2V0In0 + authenticatorData: type: string - enum: - - PENDING - - CLAIMED - - EXPIRED - - CANCELLED - description: The status of the invitation - example: PENDING - firstName: + description: Base64url-encoded authenticator data returned by the authenticator during the assertion. Corresponds to `AuthenticatorAssertionResponse.authenticatorData`. + example: PdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KABAAAAkA + signature: type: string - description: The inviter's first name. Will be displayed when the recipient clicks the invite link - example: Jane - amountToSend: - $ref: '#/components/schemas/CurrencyAmount' - description: |- - The amount to send to the invitee when the invitation is claimed. This is optional and if not provided, the invitee will not receive any amount. Note that the actual sending of the amount must be done by the inviter platform once the INVITATION_CLAIMED webhook is received. If the inviter platform either does not send the payment or the payment fails, the invitee will not receive this amount. This field is primarily used for display purposes on the claiming side of the invitation. - This field is useful for "send-by-link" style customer flows where an inviter can send a payment simply by sharing a link without knowing the receiver's UMA address. Note that these sends can only be sender-locked, meaning that the sender will not know ahead of time how much the receiver will receive in the receiving currency. - UmaInvitationClaimRequest: + description: Base64url-encoded signature produced by the authenticator over `authenticatorData || SHA-256(clientDataJSON)`. Corresponds to `AuthenticatorAssertionResponse.signature`. The signature byte format is determined by the credential's public-key algorithm — DER-encoded ECDSA for ES256 (P-256, typical for passkeys), PKCS#1 v1.5 for RS256, or a raw 64-byte signature for EdDSA. + example: MEUCIQDYXBOpCWSWq2Ll4558GJKD2RoWg958lvJSB_GdeokxogIgWuEVQ7ee6AswQY0OsuQ6y8Ks6jhd45bDx92wjXKs900 + userHandle: + type: string + description: Base64url-encoded user handle returned by the authenticator. Corresponds to `AuthenticatorAssertionResponse.userHandle`. Populated (and required by the WebAuthn spec) for discoverable credentials — resident keys used in the "Sign in with passkey" autofill flow — and typically present for passkey registrations. Omit this field entirely for non-discoverable credentials specified via `allowCredentials` where the authenticator returns no user handle. + example: dXNlci1oYW5kbGUtZXhhbXBsZQ + PasskeyCredentialVerifyRequestFields: type: object required: - - inviteeUma + - type + - assertion properties: - inviteeUma: + type: type: string - description: The UMA address of the customer claiming the invitation - example: $invitee@uma.domain - Error403: + enum: + - PASSKEY + description: Discriminator value identifying this as a passkey verification. + assertion: + $ref: '#/components/schemas/PasskeyAssertion' + PasskeyCredentialVerifyRequest: + title: Passkey Credential Verify Request + allOf: + - $ref: '#/components/schemas/AuthCredentialVerifyRequest' + - $ref: '#/components/schemas/PasskeyCredentialVerifyRequestFields' + AuthCredentialVerifyRequestOneOf: + oneOf: + - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequest' + - $ref: '#/components/schemas/OauthCredentialVerifyRequest' + - $ref: '#/components/schemas/PasskeyCredentialVerifyRequest' + discriminator: + propertyName: type + mapping: + EMAIL_OTP: '#/components/schemas/EmailOtpCredentialVerifyRequest' + OAUTH: '#/components/schemas/OauthCredentialVerifyRequest' + PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' + AuthSession: + title: Authentication Session + description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/refresh` (on mid-session refresh). Only session-issuing responses include `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. + allOf: + - $ref: '#/components/schemas/AuthMethod' + - type: object + required: + - id + - expiresAt + properties: + id: + type: string + description: System-generated unique identifier for the session. Pass this value to `DELETE /auth/sessions/{id}` to revoke the session before `expiresAt`. Overrides the `id` inherited from `AuthMethod` so this response identifies the session rather than the authenticating credential. + example: Session:019542f5-b3e7-1d02-0000-000000000003 + encryptedSessionSigningKey: + type: string + description: |- + HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verification or refresh request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. + + Returned only by session-issuing responses for `OAUTH` and `PASSKEY` credentials. `EMAIL_OTP` sessions omit this field — the client generates a TEK keypair before verification and retains the private key throughout, so the server has nothing to deliver. Always omitted from list responses (`GET /auth/sessions`) since Grid does not retain the plaintext key after the client has decrypted it. + example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf + expiresAt: + type: string + format: date-time + description: Timestamp after which the session is no longer valid and the `encryptedSessionSigningKey` must not be used to sign further requests. + example: '2026-04-09T15:30:01Z' + Error429: type: object required: - message @@ -17182,22 +18684,16 @@ components: status: type: integer enum: - - 403 + - 429 description: HTTP status code code: type: string description: | | Error Code | Description | |------------|-------------| - | FORBIDDEN | Insufficient permissions | - | USER_NOT_READY | Customer exists but is not ready for operation | - | COUNTERPARTY_NOT_ALLOWED | Counterparty has not been enabled for your account | - | VELOCITY_LIMIT_EXCEEDED | Counterparty has exceeded velocity limits | + | RATE_LIMITED | Too many requests in a short window; retry after the interval indicated by the `Retry-After` response header | enum: - - FORBIDDEN - - USER_NOT_READY - - COUNTERPARTY_NOT_ALLOWED - - VELOCITY_LIMIT_EXCEEDED + - RATE_LIMITED message: type: string description: Error message @@ -17205,1079 +18701,1048 @@ components: type: object description: Additional error details additionalProperties: true - SandboxSendRequest: - type: object - required: - - quoteId - - currencyCode - properties: - quoteId: - type: string - description: The unique identifier of the quote - example: Quote:019542f5-b3e7-1d02-0000-000000000006 - currencyCode: - type: string - description: Currency code for the funds to be sent - example: USD - currencyAmount: - type: integer - format: int64 - description: The amount to send in the smallest unit of the currency (eg. cents). If not provided, the amount will be derived from the quote. - exclusiveMinimum: 0 - example: 1000 - SandboxUmaReceiveRequest: - type: object - required: - - senderUmaAddress - - receivingCurrencyCode - - receivingCurrencyAmount - properties: - senderUmaAddress: - type: string - description: UMA address of the sender from the sandbox - example: $success.usd@sandbox.grid.uma.money - receiverUmaAddress: - type: string - description: UMA address of the receiver (optional if customerId is provided) - example: $receiver@uma.domain - customerId: - type: string - description: System ID of the receiver (optional if receiverUmaAddress is provided) - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - receivingCurrencyCode: - type: string - description: The currency code for the receiving amount - example: USD - receivingCurrencyAmount: - type: integer - format: int64 - description: The amount to be received in the smallest unit of the currency (eg. cents) - exclusiveMinimum: 0 - example: 1000 - SandboxFundRequest: - type: object - required: - - amount - properties: - amount: - type: integer - format: int64 - description: Amount to add in the smallest unit of the account's currency (e.g., cents for USD/EUR, satoshis for BTC) - exclusiveMinimum: 0 - maximum: 100000000000 - example: 100000 - UmaProvider: + AuthCredentialChallengeRequest: + title: Auth Credential Challenge Request + description: Request body for `POST /auth/credentials/{id}/challenge`. Required when re-challenging a `PASSKEY` credential — must carry `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from. Ignored for `EMAIL_OTP`, where the credential type alone is sufficient because the OTP is delivered out-of-band. OAuth credentials do not use this endpoint; authenticate or reauthenticate them with `POST /auth/credentials/{id}/verify`. type: object properties: - name: - type: string - description: Name of the UMA Provider - example: Lightspark Group - supportedRegions: - type: array - items: - type: string - description: Region(s) this UMA Provider operates in - example: - - US - domain: - type: string - description: Domain this VASP uses for UMA addresses - example: uma.me - logoUrl: - type: string - description: Logo URL for the VASP - format: uri - example: https://uma.me/logo.png - supportedCurrencies: - type: array - items: - $ref: '#/components/schemas/Currency' - description: List of currencies supported by this UMA Provider - example: - - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - lei: + clientPublicKey: type: string - description: Legal Entity Identifier for the UMA Provider - example: 5493001KJTIIGC8Y1R12 - allowListStatus: - type: boolean - description: Whether this UMA Provider is on your allow list - example: true - UmaProviderListResponse: + pattern: ^04[0-9a-fA-F]{128}$ + minLength: 130 + maxLength: 130 + description: Required for `PASSKEY` credentials. Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid bakes this key into the Turnkey session-creation payload that the returned `challenge` is computed from, so the resulting session signing key is sealed to the client. Ignored for `EMAIL_OTP`. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + PasskeyAuthChallenge: + title: Passkey Auth Challenge + description: Extended `AuthMethod` shape returned for `PASSKEY` credentials from `POST /auth/credentials/{id}/challenge`. Includes the WebAuthn `credentialId` needed to target the passkey, plus the Grid-issued `challenge`, corresponding `requestId`, and challenge `expiresAt`. The `challenge` value is the lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body, not a base64url string. The client UTF-8 encodes this string as the WebAuthn challenge and signs it with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. + allOf: + - $ref: '#/components/schemas/AuthMethod' + - type: object + required: + - credentialId + - challenge + - requestId + - expiresAt + properties: + credentialId: + type: string + description: Base64url-encoded WebAuthn credential identifier for this passkey. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. + example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew + challenge: + type: string + description: Lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body for the pending passkey authentication. Do not base64url-decode this field; pass UTF-8 bytes of the string (for example, `new TextEncoder().encode(challenge)`) as the WebAuthn challenge to `navigator.credentials.get()`. Single-use; a new challenge is issued on the next call to `POST /auth/credentials/{id}/challenge`. + example: 6b35a4c41d9aa7a2a0e742f9f9e7a1c2d65a2db33a3fb748f6d4f1ce78d9a729 + requestId: + type: string + description: Grid-issued `Request:` identifier for this pending passkey authentication request. Echo this value exactly as the `Request-Id` header on the subsequent `POST /auth/credentials/{id}/verify` call so Grid can correlate the assertion with the issued challenge. + example: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 + expiresAt: + type: string + format: date-time + description: Timestamp after which the issued challenge is no longer valid. The assertion must reach `POST /auth/credentials/{id}/verify` before this time; otherwise the client must request a fresh challenge via `POST /auth/credentials/{id}/challenge`. + example: '2026-04-08T15:35:00Z' + AuthCredentialResponseOneOf: + title: Auth Credential Response + description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. + oneOf: + - $ref: '#/components/schemas/AuthMethodResponse' + - $ref: '#/components/schemas/PasskeyAuthChallenge' + discriminator: + propertyName: type + mapping: + EMAIL_OTP: '#/components/schemas/AuthMethodResponse' + PASSKEY: '#/components/schemas/PasskeyAuthChallenge' + SessionListResponse: type: object + required: + - data properties: data: - description: List of available UMA Providers using Grid type: array + description: List of active authentication sessions for the internal account. items: - $ref: '#/components/schemas/UmaProvider' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: - type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: - type: integer - description: Total number of transactions matching the criteria (excluding pagination) - Permission: - type: string - enum: - - VIEW - - TRANSACT - - MANAGE - description: 'Permission of an API token that determines what actions the token can perform: VIEW: Can view all data, including platform config, customers and transactions TRANSACT: Can send payments MANAGE: Can manage platform config, api tokens and customers' - ApiToken: + $ref: '#/components/schemas/AuthSession' + AuthSessionRefreshRequest: + title: Auth Session Refresh Request + description: Request body for refreshing an active authentication session. The `clientPublicKey` is required on both steps of the signed-retry flow. On the initial call, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the signed retry, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. type: object required: - - id - - name - - permissions - - clientId - - createdAt - - updatedAt + - clientPublicKey properties: - id: - type: string - description: System-generated unique identifier - example: Token:019542f5-b3e7-1d02-0000-000000000001 - name: - type: string - description: Name of the token - example: Sandbox read-only token - permissions: - type: array - description: A list of permissions granted to the token - items: - $ref: '#/components/schemas/Permission' - clientId: - type: string - description: An opaque identifier that should be used as a client_id (or username) in the HTTP Basic Authentication scheme when issuing http requests to Grid. - example: 01947d2284054f890000e63bca4810df - clientSecret: - type: string - description: The secret that should be used to authenticate against Grid API. This secret is not stored and will never be available again after creation. Platform must keep this secret secure as it grants access to the account. - example: ed0ad25881e234cc28fb2dec0a4fe64e4172 - createdAt: - type: string - format: date-time - description: Creation timestamp - example: '2025-07-21T17:32:28Z' - updatedAt: + clientPublicKey: type: string - format: date-time - description: Last update timestamp - example: '2025-07-21T17:32:28Z' - TokenListResponse: + pattern: ^04[0-9a-fA-F]{128}$ + description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the initial call and seals the returned `encryptedSessionSigningKey` to it on the signed retry. + example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 + AgentPermission: + type: string + enum: + - VIEW_TRANSACTIONS + - CREATE_TRANSFERS + - CREATE_QUOTES + - EXECUTE_QUOTES + - MANAGE_EXTERNAL_ACCOUNTS + description: 'Permission granted to an agent that determines what actions it can perform. VIEW_TRANSACTIONS: Can list and retrieve transactions and account balances. CREATE_TRANSFERS: Can initiate same-currency transfers. CREATE_QUOTES: Can create cross-currency quotes. EXECUTE_QUOTES: Can execute cross-currency quotes. MANAGE_EXTERNAL_ACCOUNTS: Can create and manage external accounts.' + AgentExecutionMode: + type: string + enum: + - AUTO + - APPROVAL_REQUIRED + description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' + AgentSpendingLimits: type: object + description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: - - data - - hasMore + - currency + - perTransactionLimit properties: - data: - type: array - description: List of tokens matching the filter criteria - items: - $ref: '#/components/schemas/ApiToken' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page - nextCursor: + currency: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) - totalCount: + description: ISO 4217 currency code that all amount limits are denominated in. + example: USD + perTransactionLimit: type: integer - description: Total number of tokens matching the criteria (excluding pagination) - ApiTokenCreateRequest: + description: Maximum amount the agent can transfer in a single transaction. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per day. Null means no daily limit. + example: 500000 + dailyTransactionLimit: + type: integer + description: Maximum number of transactions the agent can initiate per day. + example: 10 + monthlyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per month. Null means no monthly limit. + example: 5000000 + AgentAccountRule: type: object + description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: - - name - - permissions + - accountId properties: - name: + accountId: type: string - description: Name of the token to help identify it - example: Sandbox read-only - permissions: + description: The internal account ID this rule applies to. + example: Account:019542f5-b3e7-1d02-0000-000000000001 + executionMode: + $ref: '#/components/schemas/AgentExecutionMode' + perTransactionLimit: + type: + - integer + - 'null' + description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. + example: 10000 + AgentAccountRestrictions: + type: object + description: Optional restrictions that limit the agent to specific accounts or override policy per account. + properties: + allowedAccountIds: + type: + - array + - 'null' + description: If set, restricts the agent to operate only on the specified internal account IDs. Null means the agent can access all accounts. + items: + type: string + example: Account:019542f5-b3e7-1d02-0000-000000000001 + accountRules: type: array - description: A list of permissions to grant to the token + description: Per-account rules that override the agent's default policy for specific accounts. items: - $ref: '#/components/schemas/Permission' - InternalAccountUpdateRequest: - title: Internal Account Update Request - description: Partial request body for `PATCH /internal-accounts/{id}`. At least one update field must be provided. On step 1 of the signed-retry flow Grid binds the submitted update fields into `payloadToSign`; on step 2 the client echoes the same fields back and Grid applies the update to the internal account. + $ref: '#/components/schemas/AgentAccountRule' + AgentApprovalThresholds: type: object + description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: - privateEnabled: - type: boolean - description: Whether wallet privacy should be enabled for the Embedded Wallet. - example: true - InternalAccountExportRequest: - title: Internal Account Export Request - description: Request body for `POST /internal-accounts/{id}/export`. The `clientPublicKey` is required on both steps of the signed-retry flow. On step 1 Grid binds it into `payloadToSign` so the subsequent stamp in `Grid-Wallet-Signature` commits to the target pubkey; on step 2 the client echoes the same `clientPublicKey` back and Grid uses it to encrypt the wallet credentials returned in the `200` response. + currency: + type: string + description: ISO 4217 currency code that the amount threshold is denominated in. Required when amount is set. + example: USD + amount: + type: + - integer + - 'null' + description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. + example: 100000 + AgentPolicy: type: object + description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: - - clientPublicKey + - permissions + - defaultExecutionMode + - spendingLimits properties: - clientPublicKey: - type: string - description: Fresh P-256 public key, uncompressed SEC1 hex — 130 hex chars where the first two are `04` (the uncompressed-point indicator). Generate a new keypair for each export and discard the private key after decrypting the response. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - InternalAccountExportResponse: - title: Internal Account Export Response + permissions: + type: array + description: List of permissions granted to the agent. + items: + $ref: '#/components/schemas/AgentPermission' + defaultExecutionMode: + $ref: '#/components/schemas/AgentExecutionMode' + spendingLimits: + $ref: '#/components/schemas/AgentSpendingLimits' + accountRestrictions: + $ref: '#/components/schemas/AgentAccountRestrictions' + approvalThresholds: + $ref: '#/components/schemas/AgentApprovalThresholds' + AgentUsage: type: object + description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: - - id - - encryptedWalletCredentials + - dailyTransactionCount + - dailySpend + - monthlySpend properties: - id: + dailyTransactionCount: + type: integer + description: Number of transactions initiated by the agent today. + example: 3 + dailySpend: + type: integer + description: Total amount spent by the agent today, in the smallest unit of the policy's `spendingLimits.currency`. + example: 150000 + dailyResetDate: type: string - description: The id of the internal account that was exported. - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - encryptedWalletCredentials: + format: date + description: The date when daily usage counters will reset. + example: '2025-07-22' + monthlySpend: + type: integer + description: Total amount spent by the agent this month, in the smallest unit of the policy's `spendingLimits.currency`. + example: 750000 + monthlyResetMonth: type: string - description: |- - Encrypted wallet mnemonic, sealed to the `clientPublicKey` from the request body using HPKE: DHKEM(P-256, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM. Decrypt with the matching private key, then manage the mnemonic securely because it is the master key of the self-custodial Embedded Wallet. - The value is a JSON string of the form `{"version": "v1.0.0", "data": "", "dataSignature": "", "enclaveQuorumPublic": ""}`. `data` hex-decodes to JSON `{"encappedPublic": "", "ciphertext": "", "organizationId": ""}`, where `encappedPublic` is the uncompressed SEC1 ephemeral public key. `dataSignature` is an ECDSA-P256-SHA256 signature over the `data` bytes produced by the issuer key in `enclaveQuorumPublic`; verify before decrypting. - In sandbox, `dataSignature` and `enclaveQuorumPublic` are empty strings. Clients should bypass attestation verification when calling against sandbox. - example: '{"version":"v1.0.0","data":"7b22656e6361707065645075626c6963223a22303433...","dataSignature":"3045022100c9...","enclaveQuorumPublic":"04a1b2c3..."}' - AuthMethodType: - type: string - enum: - - OAUTH - - EMAIL_OTP - - PASSKEY - description: |- - The type of authentication credential. - - `OAUTH`: OpenID Connect (OIDC) token issued by an identity provider such as Google or Apple. - - `EMAIL_OTP`: A one-time password delivered to the user's email address. - - `PASSKEY`: A WebAuthn passkey bound to the user's device. - AuthMethod: + description: The year-month (YYYY-MM) when monthly usage counters will reset. + example: 2025-08 + Agent: type: object + description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: - id - - accountId - - type - - nickname + - name + - customerId + - isPaused + - isConnected + - policy + - usage - createdAt - updatedAt properties: id: type: string - description: System-generated unique identifier for the authentication credential. - example: AuthMethod:019542f5-b3e7-1d02-0000-000000000001 - accountId: - type: string - description: Identifier of the internal account that this credential authenticates. - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - type: - $ref: '#/components/schemas/AuthMethodType' - credentialId: + description: System-generated unique identifier for the agent. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + name: type: string - description: Base64url-encoded WebAuthn credential identifier for this passkey. Present only for `PASSKEY` authentication credentials. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. - example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew - nickname: + description: Human-readable name for the agent. + example: Payroll Automation Agent + customerId: type: string - description: Human-readable identifier for this credential. For EMAIL_OTP credentials this is the email address; for OAUTH credentials it is typically the email claim from the OIDC token; for PASSKEY credentials it is the validated nickname provided at registration time. - example: example@lightspark.com + description: The ID of the customer this agent operates on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + isPaused: + type: boolean + description: Whether the agent is currently paused. Paused agents cannot initiate any actions. + example: false + isConnected: + type: boolean + description: Whether the agent has been installed and connected (i.e., its device code has been redeemed). + example: true + policy: + $ref: '#/components/schemas/AgentPolicy' + usage: + $ref: '#/components/schemas/AgentUsage' createdAt: type: string format: date-time description: Creation timestamp. - example: '2026-04-08T15:30:01Z' + example: '2025-07-21T17:32:28Z' updatedAt: type: string format: date-time description: Last update timestamp. - example: '2026-04-08T15:35:00Z' - AuthCredentialListResponse: + example: '2025-07-21T17:32:28Z' + AgentListResponse: type: object required: - data + - hasMore properties: data: type: array - description: List of authentication credentials registered on the internal account. + description: List of agents matching the filter criteria. items: - $ref: '#/components/schemas/AuthMethod' - AuthCredentialCreateRequest: - type: object - required: - - type - - accountId - properties: - type: - $ref: '#/components/schemas/AuthMethodType' - accountId: - type: string - description: Identifier of the internal account that this credential will authenticate. - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - EmailOtpCredentialCreateRequestFields: - type: object - required: - - type - properties: - type: - type: string - enum: - - EMAIL_OTP - description: Discriminator value identifying this as an email OTP credential. - EmailOtpCredentialCreateRequest: - title: Email OTP Credential Create Request - allOf: - - $ref: '#/components/schemas/AuthCredentialCreateRequest' - - $ref: '#/components/schemas/EmailOtpCredentialCreateRequestFields' - OauthCredentialCreateRequestFields: - type: object - required: - - type - - oidcToken - properties: - type: - type: string - enum: - - OAUTH - description: Discriminator value identifying this as an OAuth credential. - oidcToken: + $ref: '#/components/schemas/Agent' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: type: string - description: OIDC ID token issued by the identity provider (e.g. Google, Apple). The token's `iss`, `aud`, and `sub` claims define the OAuth identity registered to this credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and `iat` less than 60 seconds before the request timestamp, but the signature segment may be a dummy value. - example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q - OauthCredentialCreateRequest: - title: OAuth Credential Create Request - allOf: - - $ref: '#/components/schemas/AuthCredentialCreateRequest' - - $ref: '#/components/schemas/OauthCredentialCreateRequestFields' - PasskeyAttestation: - title: Passkey Attestation + description: Cursor to retrieve the next page of results (only present if hasMore is true). + totalCount: + type: integer + description: Total number of agents matching the criteria (excluding pagination). + AgentCreateRequest: type: object required: - - credentialId - - clientDataJson - - attestationObject + - name + - customerId + - policy properties: - credentialId: - type: string - description: Base64url-encoded credential identifier produced by the authenticator at registration time. Typically the base64url of `PublicKeyCredential.rawId`. - example: AdKXJEch1aV5Wo7bj7qLHskVY4OoNaj9qu8TPdJ7kSAgUeRxWNngXlcNIGt4gexZGKVGcqZpqqWordXb_he1izY - clientDataJson: + name: type: string - description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.create()` call. Corresponds to `AuthenticatorAttestationResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.create"`.' - example: eyJjaGFsbGVuZ2UiOiJBcktRaTJ5QVlIUGxnbkpORkJsbmVJd2NoUWRXWEJPVHJkQi1BbU1VQjIxTHgiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0 - attestationObject: + description: Human-readable name to identify the agent. + example: Payroll Automation Agent + customerId: type: string - description: Base64url-encoded CBOR attestation object produced by the authenticator during registration. Corresponds to `AuthenticatorAttestationResponse.attestationObject`. - example: o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjFPdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KBFAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQHSlyRHIdWleVqO24-6ix7JFWODqDWo_arvEz3Se5EgIFHkcVjZ4F5XDSBreIHsWRilRnKmaaqlqK3V2_4XtYs2pQECAyYgASFYID5PQTZQQg6haZFQWFzqfAOyQ_ENsMH8xxQ4GRiNPsqrIlggU8IVUOV8qpgk_Jh-OTaLuZL52KdX1fTht07X4DiQPow - transports: - type: array - items: - type: string - enum: - - usb - - nfc - - ble - - internal - - hybrid - description: Optional. WebAuthn transports as returned by `AuthenticatorAttestationResponse.getTransports()`. Values follow the W3C `AuthenticatorTransport` enum — pass the raw values through to Grid; provider-specific translation is handled server-side. Some authenticators return an empty array; omit the field or send `[]` in that case. - example: - - internal - - hybrid - PasskeyCredentialCreateRequestFields: + description: The ID of the customer this agent will operate on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + policy: + $ref: '#/components/schemas/AgentPolicy' + AgentDeviceCode: type: object required: - - type - - nickname - - challenge - - attestation + - code + - agentId + - expiresAt + - redeemed properties: - type: + code: type: string - enum: - - PASSKEY - description: Discriminator value identifying this as a passkey credential. - nickname: + description: Human-readable device code used to install and connect the agent software. + example: GRID-AGENT-X7K9-M2P4 + agentId: type: string - description: 'Human-readable identifier for the passkey, chosen by the user at registration time (e.g. "iPhone Face-ID", "YubiKey 5C"). Leading and trailing whitespace is ignored. Must be 1-100 characters and may contain Unicode letters, numbers, spaces, and the following separators: period, underscore, hyphen, apostrophe, and parentheses. Shown back on AuthMethod responses and in credential listings.' - example: iPhone Face-ID - challenge: + description: The agent this device code belongs to. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + expiresAt: type: string - description: Base64url-encoded WebAuthn challenge issued by the platform backend and passed to the client before `navigator.credentials.create()`. Grid verifies it matches the challenge embedded in the attestation's `clientDataJson`, binding the attestation to this registration. Must be single-use. - example: ArkQi2yAYHPlgnJNFBlneIwchQdWXBOTrdB-AmMUB21Lx - attestation: - $ref: '#/components/schemas/PasskeyAttestation' - PasskeyCredentialCreateRequest: - title: Passkey Credential Create Request - allOf: - - $ref: '#/components/schemas/AuthCredentialCreateRequest' - - $ref: '#/components/schemas/PasskeyCredentialCreateRequestFields' - AuthCredentialCreateRequestOneOf: - oneOf: - - $ref: '#/components/schemas/EmailOtpCredentialCreateRequest' - - $ref: '#/components/schemas/OauthCredentialCreateRequest' - - $ref: '#/components/schemas/PasskeyCredentialCreateRequest' - discriminator: - propertyName: type - mapping: - EMAIL_OTP: '#/components/schemas/EmailOtpCredentialCreateRequest' - OAUTH: '#/components/schemas/OauthCredentialCreateRequest' - PASSKEY: '#/components/schemas/PasskeyCredentialCreateRequest' - AuthMethodResponse: - title: Auth Method Response - description: |- - Strict wrapper around `AuthMethod`. Used directly as the registration response on `POST /auth/credentials` (all three credential types) and inside `AuthCredentialResponseOneOf` for the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/challenge`. The only difference from `AuthMethod` is `unevaluatedProperties: false`, which disambiguates the oneOf against `PasskeyAuthChallenge` — without the strictness, an `AuthMethod` with extra fields would ambiguously match both branches. - - For `EMAIL_OTP` credentials, responses that initiate or reissue an OTP challenge carry `otpEncryptionTargetBundle` so the client can HPKE-encrypt the OTP code in the subsequent `POST /auth/credentials/{id}/verify` call without the plaintext code ever transiting the server. First-time EMAIL_OTP wallet bootstrap registration can omit it; call `POST /auth/credentials/{id}/challenge` if it is absent. - allOf: - - $ref: '#/components/schemas/AuthMethod' - - type: object - properties: - otpEncryptionTargetBundle: - type: string - description: HPKE encryption target bundle for a freshly initiated OTP challenge. Returned only on `EMAIL_OTP` responses that initiate or reissue an OTP challenge, such as `POST /auth/credentials/{id}/challenge` and the add-EMAIL_OTP signed-retry response. It is omitted from first-time EMAIL_OTP wallet bootstrap registration; call `POST /auth/credentials/{id}/challenge` for the new credential if it is absent. The client generates an ephemeral P-256 keypair (the Target Encryption Key, or TEK) and uses this bundle as the recipient when HPKE-encrypting `{otp_code, public_key}`; the encrypted payload is submitted as `encryptedOtpBundle` on `POST /auth/credentials/{id}/verify`. The bundle is one-time-use per OTP issuance — re-issue via `POST /auth/credentials/{id}/challenge` to obtain a fresh bundle. The matching TEK private key must remain on the client and is used to sign the `verificationToken` returned on the subsequent signed-retry. Treat the bundle as opaque and pass it to your HPKE library; the Global Accounts client-keys guide shows how. - example: '{"version":"v1.0.0","data":"7b227461726765745075626c6963...","dataSignature":"30450221...","enclaveQuorumPublic":"04a1b2c3..."}' - unevaluatedProperties: false - AuthSignedRequestChallenge: - title: Authentication Signed Request Challenge - description: |- - 202 response returned from Embedded Wallet Auth endpoints that require a signed retry — `POST /auth/credentials` (adding an additional credential), `DELETE /auth/credentials/{id}` (revoking a credential), `DELETE /auth/sessions/{id}` (revoking a session), and the `EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify` (the secure OTP login flow, where the client submits an `encryptedOtpBundle` and receives a `verificationToken` to sign for the second-leg session issuance). Carries the signing fields from `SignedRequestChallenge` plus the `type` of the authentication credential involved (being added, revoked, that issued the session being revoked, or being authenticated). The client already knows the target resource id from the request path / body it just sent, so nothing beyond `type` is echoed in the response. - - The keypair used to compute the stamp depends on the operation. For credential / session management retries, sign with the session API keypair of an existing verified credential on the same internal account. For the `EMAIL_OTP` verify retry, sign with the ephemeral Target Encryption Key (TEK) the client generated for this login — its public key is the one carried inside the `encryptedOtpBundle` and bound into the `verificationToken`, and it becomes the client's session API key on successful completion. - allOf: - - $ref: '#/components/schemas/SignedRequestChallenge' - - type: object - required: - - type - properties: - type: - $ref: '#/components/schemas/AuthMethodType' - description: 'Credential type relevant to this challenge: the credential type being added (`POST /auth/credentials`), revoked (`DELETE /auth/credentials/{id}`), or authenticated (`EMAIL_OTP` branch of `POST /auth/credentials/{id}/verify`). For session revocation, this is the type of credential that issued the session (`DELETE /auth/sessions/{id}`).' - AuthCredentialVerifyRequest: + format: date-time + description: Timestamp when this device code expires. + example: '2025-07-22T17:32:28Z' + redeemed: + type: boolean + description: Whether this device code has already been redeemed by the agent. + example: false + AgentCreateResponse: type: object + description: Response returned when an agent is created, including the agent and a device code for installation. required: - - type + - agent + - deviceCode properties: - type: - $ref: '#/components/schemas/AuthMethodType' - EmailOtpCredentialVerifyRequestFields: + agent: + $ref: '#/components/schemas/Agent' + deviceCode: + $ref: '#/components/schemas/AgentDeviceCode' + AgentActionStatus: + type: string + enum: + - PENDING_APPROVAL + - APPROVED + - REJECTED + - FAILED + description: | + Status of an agent action. + + | Status | Description | + |--------|-------------| + | `PENDING_APPROVAL` | Submitted by the agent, awaiting platform approval before execution | + | `APPROVED` | Approved by the platform; execution is in progress or completed | + | `REJECTED` | Rejected by the platform; the underlying transaction was not executed | + | `FAILED` | Approved but execution failed (e.g. quote expired, insufficient funds) | + AgentActionType: + type: string + enum: + - EXECUTE_QUOTE + - TRANSFER_OUT + - TRANSFER_IN + description: | + The type of action the agent is requesting. + + | Type | Description | + |------|-------------| + | `EXECUTE_QUOTE` | Execute a cross-currency quote | + | `TRANSFER_OUT` | Transfer from an internal account to an external account | + | `TRANSFER_IN` | Transfer from an external account to an internal account | + AgentTransferDetails: type: object + description: Details of a transfer-type agent action (TRANSFER_OUT or TRANSFER_IN). required: - - type - - encryptedOtpBundle - description: Verify an email-OTP credential via the secure two-leg flow. The client HPKE-encrypts the OTP code (together with its public key) under the `otpEncryptionTargetBundle` returned from registration when present, or from `POST /auth/credentials/{id}/challenge` when registration omitted it or the OTP must be reissued, submits the result here, and receives `202` with a `payloadToSign` carrying a `verificationToken` bound to the client's public key. The client signs that token with the matching private key and retries this request with `Grid-Wallet-Signature` + `Request-Id` headers to obtain the session. Plaintext OTP codes are never sent over the wire. + - amount + - currency + - sourceAccountId + - destinationAccountId properties: - type: + amount: + type: integer + format: int64 + description: Transfer amount in the smallest unit of the specified currency. + example: 50000 + currency: type: string - enum: - - EMAIL_OTP - description: Discriminator value identifying this as an email OTP verification. - encryptedOtpBundle: + description: ISO 4217 currency code for the transfer amount. + example: USD + sourceAccountId: type: string - description: |- - HPKE-sealed OTP attempt — the OTP code never reaches Grid in plaintext. The client generates a fresh ephemeral P-256 key pair (the session signing key pair it keeps once login completes), HPKE-encrypts `{otp_code, public_key}` (the code the user entered plus that key pair's public key) to the key in `otpEncryptionTargetBundle`, and submits the encrypted result here. The value is the `{encappedPublic, ciphertext}` JSON an HPKE library produces; the Global Accounts client-keys guide has a worked example. - - On success the response is `202` with a `payloadToSign` carrying a `verificationToken` bound to the public key sealed in this bundle. Sign that token with the matching private key, then retry this request with the full stamp in `Grid-Wallet-Signature` and the `requestId` in `Request-Id` to complete the flow and receive the session. The client keeps that private key as the session signing key, and its public key becomes the session API key. - example: '{"encappedPublic":"044f631a2d890bc6668d997ee184e190650d06adf970987568ec641214a00403b73effe1ef406c60a5cde8508a4484567ddb8056fbd493bee614cd727aef02a838","ciphertext":"1fa1023390a56539aa48cbb380aa28f544ed5cc04861566bb806e25ba026f14660eaf4140a05b388dd012eaa899759a6a92576cdca8c1b7d12e147bd96cc26ed9f74886794155d8ac5cf0fdc"}' - EmailOtpCredentialVerifyRequest: - title: Email OTP Credential Verify Request - allOf: - - $ref: '#/components/schemas/AuthCredentialVerifyRequest' - - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequestFields' - OauthCredentialVerifyRequestFields: + description: ID of the source account (internal or external). + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destinationAccountId: + type: string + description: ID of the destination account (internal or external). + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + AgentAction: type: object + description: An action submitted by an agent that may require platform approval before execution. All agent-initiated operations (quote execution, transfers) are represented as AgentActions, giving the platform a consistent object to approve, reject, and audit regardless of the underlying operation type. required: + - id + - agentId + - customerId + - platformCustomerId + - status - type - - oidcToken - - clientPublicKey + - createdAt + - updatedAt properties: + id: + type: string + description: System-generated unique identifier for this action. + example: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: + type: string + description: The agent that submitted this action. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: + type: string + description: The customer on whose behalf the action was submitted. + example: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: + type: string + description: Platform-specific ID of the customer. + example: user-a1b2c3 + status: + $ref: '#/components/schemas/AgentActionStatus' type: + $ref: '#/components/schemas/AgentActionType' + quote: + allOf: + - $ref: '#/components/schemas/Quote' + description: The quote being executed. Populated for `EXECUTE_QUOTE` actions; absent for transfer actions. Contains the full amount, currency, destination, and rate details needed to present an approval decision to the user. + transferDetails: + allOf: + - $ref: '#/components/schemas/AgentTransferDetails' + description: Details of the transfer being requested. Populated for `TRANSFER_OUT` and `TRANSFER_IN` actions; absent for `EXECUTE_QUOTE` actions. + transaction: + allOf: + - $ref: '#/components/schemas/TransactionOneOf' + description: The resulting transaction, populated once the action has been approved and execution has begun. Absent while the action is `PENDING_APPROVAL` or `REJECTED`. + rejectionReason: type: string - enum: - - OAUTH - description: Discriminator value identifying this as an OAuth verification. - oidcToken: + description: Human-readable reason provided by the platform when rejecting the action. Only present when status is `REJECTED`. + example: Transaction amount exceeds customer's current risk limit. + createdAt: type: string - description: OIDC ID token issued by the identity provider. For reauthentication after a prior session expired, supply a fresh token — the token's `iat` claim must be less than 60 seconds before the request timestamp. The token identity (`iss`, `aud`, and `sub`) must match the registered OAuth credential. In production, the provider signature is verified against the issuer's JWKS. In sandbox, the token must still be JWT-shaped with supported `iss`, non-empty `aud` and `sub`, numeric `iat` and `exp`, and a `nonce` equal to `sha256(clientPublicKey)`, but the signature segment may be a dummy value. - example: eyJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMTIyMzM0NDU1IiwiYXVkIjoiMTIzNDU2Ny5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTc0NjczNjUwOSwiZXhwIjoxNzQ2NzQwMTA5fQ.-3_ETmSGOl4wGNLR1QSOMlHk5IvADpX3YdHFmTH9KmRu6sEhM20RsURjKrI4-_EKj7J_HtsdS1tCHm0iw2J0qtoczYFQqEW_U9qJD6QsuvTFx8Fj9rFa3ieYhZKi3kkBu6cADogUiudP50kf9345ATys2GrYm-ba5esgReW1WzGJG3SgCyIDnHFfxmeLjE2YE9EFxT73To3mPYAk0ywPL2MpFFV9F8I3PsnbDAxinaY75GeA8vJXATr8weEIXqHD2lxmXVE95qd2ZlcuyLUaEYyp9GXcOnx7SjhdJG88jl5BZQvxOVgBMo42iGjK674lSwsMiHpzLX98j6C786Rd9Q - clientPublicKey: + format: date-time + description: When the action was submitted by the agent. + example: '2025-10-03T15:00:00Z' + updatedAt: type: string - description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (0x04 prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid encrypts the session signing key returned in the response to this public key. The key is ephemeral and one-time-use per verification request. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - OauthCredentialVerifyRequest: - title: OAuth Credential Verify Request - allOf: - - $ref: '#/components/schemas/AuthCredentialVerifyRequest' - - $ref: '#/components/schemas/OauthCredentialVerifyRequestFields' - PasskeyAssertion: - title: Passkey Assertion + format: date-time + description: When the action was last updated. + example: '2025-10-03T15:02:00Z' + AgentActionListResponse: type: object - description: WebAuthn assertion returned by `navigator.credentials.get()`. In sandbox, Grid validates the assertion against the registered passkey credential so the client-side flow can match production. In production, Turnkey validates the WebAuthn assertion. required: - - credentialId - - clientDataJson - - authenticatorData - - signature + - data + - hasMore properties: - credentialId: - type: string - description: Base64url-encoded credential identifier returned during the WebAuthn assertion. Corresponds to `PublicKeyCredential.rawId`. - example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew - clientDataJson: + data: + type: array + description: List of agent actions matching the filter criteria. + items: + $ref: '#/components/schemas/AgentAction' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: type: string - description: 'Base64url-encoded JSON client data collected by the browser during the WebAuthn `navigator.credentials.get()` call. Corresponds to `AuthenticatorAssertionResponse.clientDataJSON` from the WebAuthn spec — Grid''s field name is intentionally camelCased as `clientDataJson` (lowercase JSON) for consistency with the rest of the API; the value is the same bytes the browser returns. Contains the challenge, origin, and `type: "webauthn.get"`.' - example: eyJjaGFsbGVuZ2UiOiJkRzkwWVd4c2VWVnVhWEYxWlZaaGJIVmxSWFpsY25sVWFXMWwiLCJjbGllbnRFeHRlbnNpb25zIjp7fSwiaGFzaEFsZ29yaXRobSI6IlNIQS0yNTYiLCJvcmlnaW4iOiJodHRwczovL2Rldi5kb250bmVlZGEucHciLCJ0eXBlIjoid2ViYXV0aG4uZ2V0In0 - authenticatorData: + description: Cursor to retrieve the next page of results (only present if hasMore is true). + totalCount: + type: integer + description: Total number of actions matching the criteria (excluding pagination). + AgentUpdateRequest: + type: object + description: Partial update to an agent's basic fields. At least one field must be provided. + properties: + name: type: string - description: Base64url-encoded authenticator data returned by the authenticator during the assertion. Corresponds to `AuthenticatorAssertionResponse.authenticatorData`. - example: PdxHEOnAiLIp26idVjIguzn3Ipr_RlsKZWsa-5qK-KABAAAAkA - signature: + description: Updated name for the agent. + example: Updated Payroll Agent + isPaused: + type: boolean + description: Set to true to pause the agent or false to resume it. + example: true + AgentSpendingLimitsUpdate: + type: object + description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. + properties: + currency: type: string - description: Base64url-encoded signature produced by the authenticator over `authenticatorData || SHA-256(clientDataJSON)`. Corresponds to `AuthenticatorAssertionResponse.signature`. The signature byte format is determined by the credential's public-key algorithm — DER-encoded ECDSA for ES256 (P-256, typical for passkeys), PKCS#1 v1.5 for RS256, or a raw 64-byte signature for EdDSA. - example: MEUCIQDYXBOpCWSWq2Ll4558GJKD2RoWg958lvJSB_GdeokxogIgWuEVQ7ee6AswQY0OsuQ6y8Ks6jhd45bDx92wjXKs900 - userHandle: + description: ISO 4217 currency code that all amount limits are denominated in. Updating this recasts all existing limits into the new currency denomination. + example: USD + perTransactionLimit: + type: integer + description: Maximum amount per transaction. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum daily spend. Set to null to remove the daily limit. + example: 500000 + dailyTransactionLimit: + type: integer + description: Maximum number of transactions per day. + example: 10 + monthlyLimit: + type: + - integer + - 'null' + description: Maximum monthly spend. Set to null to remove the monthly limit. + example: 5000000 + AgentPolicyUpdateRequest: + type: object + description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. + properties: + permissions: + type: array + description: Updated list of permissions. Replaces the entire permissions list when provided. + items: + $ref: '#/components/schemas/AgentPermission' + defaultExecutionMode: + $ref: '#/components/schemas/AgentExecutionMode' + spendingLimits: + $ref: '#/components/schemas/AgentSpendingLimitsUpdate' + accountRestrictions: + $ref: '#/components/schemas/AgentAccountRestrictions' + approvalThresholds: + $ref: '#/components/schemas/AgentApprovalThresholds' + AgentActionRejectRequest: + type: object + properties: + reason: type: string - description: Base64url-encoded user handle returned by the authenticator. Corresponds to `AuthenticatorAssertionResponse.userHandle`. Populated (and required by the WebAuthn spec) for discoverable credentials — resident keys used in the "Sign in with passkey" autofill flow — and typically present for passkey registrations. Omit this field entirely for non-discoverable credentials specified via `allowCredentials` where the authenticator returns no user handle. - example: dXNlci1oYW5kbGUtZXhhbXBsZQ - PasskeyCredentialVerifyRequestFields: + description: Optional human-readable reason for the rejection, stored on the action and visible to the platform. + example: Transaction amount exceeds customer's current risk limit. + AgentDeviceCodeStatusResponse: + type: object + required: + - code + - redeemed + properties: + code: + type: string + description: The device code. + example: GRID-AGENT-X7K9-M2P4 + redeemed: + type: boolean + description: Whether this device code has been redeemed. + example: false + AgentDeviceCodeRedeemResponse: type: object required: - - type - - assertion + - agentId + - agentName + - accessToken + - policy properties: - type: + agentId: type: string - enum: - - PASSKEY - description: Discriminator value identifying this as a passkey verification. - assertion: - $ref: '#/components/schemas/PasskeyAssertion' - PasskeyCredentialVerifyRequest: - title: Passkey Credential Verify Request - allOf: - - $ref: '#/components/schemas/AuthCredentialVerifyRequest' - - $ref: '#/components/schemas/PasskeyCredentialVerifyRequestFields' - AuthCredentialVerifyRequestOneOf: - oneOf: - - $ref: '#/components/schemas/EmailOtpCredentialVerifyRequest' - - $ref: '#/components/schemas/OauthCredentialVerifyRequest' - - $ref: '#/components/schemas/PasskeyCredentialVerifyRequest' - discriminator: - propertyName: type - mapping: - EMAIL_OTP: '#/components/schemas/EmailOtpCredentialVerifyRequest' - OAUTH: '#/components/schemas/OauthCredentialVerifyRequest' - PASSKEY: '#/components/schemas/PasskeyCredentialVerifyRequest' - AuthSession: - title: Authentication Session - description: An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/refresh` (on mid-session refresh). Only session-issuing responses include `encryptedSessionSigningKey` — it is delivered exactly once at the moment the session is issued and is never returned by the list endpoint. - allOf: - - $ref: '#/components/schemas/AuthMethod' - - type: object - required: - - id - - expiresAt - properties: - id: - type: string - description: System-generated unique identifier for the session. Pass this value to `DELETE /auth/sessions/{id}` to revoke the session before `expiresAt`. Overrides the `id` inherited from `AuthMethod` so this response identifies the session rather than the authenticating credential. - example: Session:019542f5-b3e7-1d02-0000-000000000003 - encryptedSessionSigningKey: - type: string - description: |- - HPKE-encrypted session signing key, sealed to the `clientPublicKey` supplied on the verification or refresh request. Encoded as a base58check string: the decoded payload is a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext. The client decrypts this key with its private key and uses it to sign subsequent Embedded Wallet requests until `expiresAt`. + description: The agent's system-generated ID. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + agentName: + type: string + description: The agent's name. + example: Payroll Automation Agent + accessToken: + type: string + description: 'Bearer token used to authenticate all subsequent API calls as this agent. Pass as `Authorization: Bearer `. This token is returned only once and must be stored securely — it cannot be retrieved again.' + example: gat_ed0ad25881e234cc28fb2dec0a4fe64e4172a3b9 + policy: + $ref: '#/components/schemas/AgentPolicy' + CardState: + type: string + enum: + - PENDING_KYC + - PENDING_ISSUE + - ACTIVE + - FROZEN + - CLOSED + description: | + Lifecycle state of a card. - Returned only by session-issuing responses for `OAUTH` and `PASSKEY` credentials. `EMAIL_OTP` sessions omit this field — the client generates a TEK keypair before verification and retains the private key throughout, so the server has nothing to deliver. Always omitted from list responses (`GET /auth/sessions`) since Grid does not retain the plaintext key after the client has decrypted it. - example: w99a5xV6A75TfoAUkZn869fVyDYvgVsKrawMALZXmrauZd8hEv66EkPU1Z42CUaHESQjcA5bqd8dynTGBMLWB9ewtXWPEVbZvocB4Tw2K1vQVp7uwjf - expiresAt: - type: string - format: date-time - description: Timestamp after which the session is no longer valid and the `encryptedSessionSigningKey` must not be used to sign further requests. - example: '2026-04-09T15:30:01Z' - Error429: + | State | Description | + |-------|-------------| + | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this state cannot transact. | + | `PENDING_ISSUE` | The card has been requested and is being provisioned with the issuer. | + | `ACTIVE` | The card is live and can authorize transactions. | + | `FROZEN` | The card is temporarily disabled by the platform. New authorizations are declined with `CARD_PAUSED`. Existing settlements and refunds continue to reconcile. | + | `CLOSED` | The card is permanently closed. Terminal, irreversible state. | + CardStateReason: + type: string + enum: + - ISSUER_REJECTED + - CLOSED_BY_PLATFORM + - CLOSED_BY_GRID + description: | + Reason a card reached a terminal or non-active state. Present on + `CLOSED` cards, and on cards that fail provisioning before reaching + `ACTIVE`. + + | Reason | Description | + |--------|-------------| + | `ISSUER_REJECTED` | The card issuer rejected provisioning during `PENDING_ISSUE`. | + | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`state: CLOSED`) by the platform. | + | `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or risk action). | + CardBrand: + type: string + enum: + - VISA + - MASTERCARD + description: | + Card network brand. Read-only — determined by Grid when the card is + provisioned with the issuer. + CardForm: + type: string + enum: + - VIRTUAL + description: | + Physical form factor of the card. Only `VIRTUAL` is supported in v1; + `PHYSICAL` will be added in a later release. + Card: type: object required: - - message - - status - - code + - id + - cardholderId + - state + - form + - fundingSources + - createdAt + - updatedAt properties: - status: - type: integer - enum: - - 429 - description: HTTP status code - code: + id: type: string - description: | - | Error Code | Description | - |------------|-------------| - | RATE_LIMITED | Too many requests in a short window; retry after the interval indicated by the `Retry-After` response header | - enum: - - RATE_LIMITED - message: + description: System-generated unique card identifier + readOnly: true + example: Card:019542f5-b3e7-1d02-0000-000000000010 + cardholderId: type: string - description: Error message - details: - type: object - description: Additional error details - additionalProperties: true - AuthCredentialChallengeRequest: - title: Auth Credential Challenge Request - description: Request body for `POST /auth/credentials/{id}/challenge`. Required when re-challenging a `PASSKEY` credential — must carry `clientPublicKey` so Grid can bake it into the Turnkey session-creation payload the returned challenge is computed from. Ignored for `EMAIL_OTP`, where the credential type alone is sufficient because the OTP is delivered out-of-band. OAuth credentials do not use this endpoint; authenticate or reauthenticate them with `POST /auth/credentials/{id}/verify`. - type: object - properties: - clientPublicKey: + description: The id of the `Customer` who holds this card. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCardId: type: string - pattern: ^04[0-9a-fA-F]{128}$ - minLength: 130 - maxLength: 130 - description: Required for `PASSKEY` credentials. Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid bakes this key into the Turnkey session-creation payload that the returned `challenge` is computed from, so the resulting session signing key is sealed to the client. Ignored for `EMAIL_OTP`. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - PasskeyAuthChallenge: - title: Passkey Auth Challenge - description: Extended `AuthMethod` shape returned for `PASSKEY` credentials from `POST /auth/credentials/{id}/challenge`. Includes the WebAuthn `credentialId` needed to target the passkey, plus the Grid-issued `challenge`, corresponding `requestId`, and challenge `expiresAt`. The `challenge` value is the lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body, not a base64url string. The client UTF-8 encodes this string as the WebAuthn challenge and signs it with the passkey to produce the assertion submitted to `POST /auth/credentials/{id}/verify`. - allOf: - - $ref: '#/components/schemas/AuthMethod' - - type: object - required: - - credentialId - - challenge - - requestId - - expiresAt - properties: - credentialId: - type: string - description: Base64url-encoded WebAuthn credential identifier for this passkey. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method. - example: KEbWNCc7NgaYnUyrNeFGX9_3Y-8oJ3KwzjnaiD1d1LVTxR7v3CaKfCz2Vy_g_MHSh7yJ8yL0Pxg6jo_o0hYiew - challenge: - type: string - description: Lowercase hex-encoded SHA-256 digest of the canonical Turnkey session-creation request body for the pending passkey authentication. Do not base64url-decode this field; pass UTF-8 bytes of the string (for example, `new TextEncoder().encode(challenge)`) as the WebAuthn challenge to `navigator.credentials.get()`. Single-use; a new challenge is issued on the next call to `POST /auth/credentials/{id}/challenge`. - example: 6b35a4c41d9aa7a2a0e742f9f9e7a1c2d65a2db33a3fb748f6d4f1ce78d9a729 - requestId: - type: string - description: Grid-issued `Request:` identifier for this pending passkey authentication request. Echo this value exactly as the `Request-Id` header on the subsequent `POST /auth/credentials/{id}/verify` call so Grid can correlate the assertion with the issued challenge. - example: Request:7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21 - expiresAt: - type: string - format: date-time - description: Timestamp after which the issued challenge is no longer valid. The assertion must reach `POST /auth/credentials/{id}/verify` before this time; otherwise the client must request a fresh challenge via `POST /auth/credentials/{id}/challenge`. - example: '2026-04-08T15:35:00Z' - AuthCredentialResponseOneOf: - title: Auth Credential Response - description: Discriminated response shape returned from `POST /auth/credentials/{id}/challenge`. For `EMAIL_OTP` credentials the body is a plain `AuthMethod` (wrapped as `AuthMethodResponse` to disambiguate the oneOf). For `PASSKEY` credentials the body is a `PasskeyAuthChallenge` — the passkey auth method fields plus the WebAuthn `credentialId`, Grid-issued `challenge`, `requestId`, and `expiresAt` that drive the subsequent assertion. OAuth credentials do not use the challenge endpoint. Registration responses from `POST /auth/credentials` use the simpler `AuthMethodResponse` shape directly for all three credential types. - oneOf: - - $ref: '#/components/schemas/AuthMethodResponse' - - $ref: '#/components/schemas/PasskeyAuthChallenge' - discriminator: - propertyName: type - mapping: - EMAIL_OTP: '#/components/schemas/AuthMethodResponse' - PASSKEY: '#/components/schemas/PasskeyAuthChallenge' - SessionListResponse: + description: Platform-specific card identifier. Optional on create — system-generated if omitted, mirroring `platformCustomerId` semantics. + example: card-emp-aary-001 + state: + $ref: '#/components/schemas/CardState' + stateReason: + anyOf: + - $ref: '#/components/schemas/CardStateReason' + - type: 'null' + description: Reason associated with the current `state`. Populated when the card is `CLOSED` or when provisioning was rejected; otherwise null. + brand: + $ref: '#/components/schemas/CardBrand' + form: + $ref: '#/components/schemas/CardForm' + last4: + type: string + description: Last four digits of the card PAN. + example: '4242' + expMonth: + type: integer + minimum: 1 + maximum: 12 + description: Card expiration month (1–12). + example: 12 + expYear: + type: integer + description: Card expiration year (four digits). + example: 2029 + panEmbedUrl: + type: string + format: uri + description: URL of the card issuer's iframe that securely displays the PAN, CVV, and expiry to the cardholder. The full PAN and CVV never cross Grid's servers — render this URL in an iframe in your client to reveal card details. + example: https://embed.lithic.com/iframe/...?t=... + fundingSources: + type: array + description: Internal account ids bound to this card as funding sources, in priority order — the first entry is tried first by Authorization Decisioning. Every card has at least one funding source. + items: + type: string + example: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 + currency: + type: string + description: Currency the card transacts in (ISO 4217 for fiat, tickers for crypto). Derived from the funding sources at issue time — all funding sources bound to a card must be denominated in the same card-eligible currency. + example: USD + readOnly: true + issuerRef: + type: string + description: Opaque identifier for the card on the underlying issuer. Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. + example: lithic_card_4f8d3a2b1c + readOnly: true + createdAt: + type: string + format: date-time + description: Creation timestamp + readOnly: true + example: '2026-05-08T14:10:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + readOnly: true + example: '2026-05-08T14:11:00Z' + CardListResponse: type: object required: - data + - hasMore properties: data: type: array - description: List of active authentication sessions for the internal account. + description: List of cards matching the filter criteria items: - $ref: '#/components/schemas/AuthSession' - AuthSessionRefreshRequest: - title: Auth Session Refresh Request - description: Request body for refreshing an active authentication session. The `clientPublicKey` is required on both steps of the signed-retry flow. On the initial call, Grid binds this key into the Turnkey session-creation payload returned as `payloadToSign`; on the signed retry, the client echoes the same key back and Grid uses it to encrypt the newly issued session signing key. + $ref: '#/components/schemas/Card' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true) + totalCount: + type: integer + description: Total number of cards matching the criteria (excluding pagination) + CardCreateRequest: type: object required: - - clientPublicKey + - cardholderId + - form + - fundingSources properties: - clientPublicKey: + cardholderId: type: string - pattern: ^04[0-9a-fA-F]{128}$ - description: Client-generated P-256 public key, hex-encoded in uncompressed SEC1 format (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters total). The matching private key must remain on the client. Grid binds this key into the session-creation payload on the initial call and seals the returned `encryptedSessionSigningKey` to it on the signed retry. - example: 04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2 - AgentPermission: - type: string - enum: - - VIEW_TRANSACTIONS - - CREATE_TRANSFERS - - CREATE_QUOTES - - EXECUTE_QUOTES - - MANAGE_EXTERNAL_ACCOUNTS - description: 'Permission granted to an agent that determines what actions it can perform. VIEW_TRANSACTIONS: Can list and retrieve transactions and account balances. CREATE_TRANSFERS: Can initiate same-currency transfers. CREATE_QUOTES: Can create cross-currency quotes. EXECUTE_QUOTES: Can execute cross-currency quotes. MANAGE_EXTERNAL_ACCOUNTS: Can create and manage external accounts.' - AgentExecutionMode: - type: string - enum: - - AUTO - - APPROVAL_REQUIRED - description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' - AgentSpendingLimits: + description: The id of the `Customer` to issue the card to. The customer must have KYC status `APPROVED`; otherwise the request is rejected with `CARDHOLDER_KYC_NOT_APPROVED`. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCardId: + type: string + description: Optional platform-specific card identifier. System-generated when omitted, mirroring `platformCustomerId` semantics. + example: card-emp-aary-001 + form: + $ref: '#/components/schemas/CardForm' + fundingSources: + type: array + description: Internal account ids to bind as funding sources, in priority order. The first entry is tried first by Authorization Decisioning. Every card must be bound to at least one source, and every source must belong to the cardholder and be denominated in a card-eligible currency (USDB in v1); otherwise the request is rejected with `FUNDING_SOURCE_INELIGIBLE`. + minItems: 1 + items: + type: string + example: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + CardUpdateRequest: type: object - description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. - required: - - currency - - perTransactionLimit + description: Update request for `PATCH /cards/{id}`. At least one of `state` or `fundingSources` must be supplied. `state` transitions are limited to `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`; any other transition returns `409 INVALID_STATE_TRANSITION`. `CLOSED` is terminal and irreversible and cannot be combined with `fundingSources`. `fundingSources`, when supplied, fully replaces the card's bound funding sources — the array order determines the priority Authorization Decisioning tries them in. properties: - currency: + state: type: string - description: ISO 4217 currency code that all amount limits are denominated in. - example: USD - perTransactionLimit: - type: integer - description: Maximum amount the agent can transfer in a single transaction. - example: 50000 - dailyLimit: - type: - - integer - - 'null' - description: Maximum total amount the agent can transfer per day. Null means no daily limit. - example: 500000 - dailyTransactionLimit: - type: integer - description: Maximum number of transactions the agent can initiate per day. - example: 10 - monthlyLimit: - type: - - integer - - 'null' - description: Maximum total amount the agent can transfer per month. Null means no monthly limit. - example: 5000000 - AgentAccountRule: + enum: + - ACTIVE + - FROZEN + - CLOSED + description: Target state for the card. Permitted transitions are `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`. `CLOSED` is terminal and irreversible; once closed, the card stays in the system for audit and reconciliation but cannot transact again. + example: FROZEN + fundingSources: + type: array + description: 'New ordered list of internal account ids to bind as funding sources. Fully replaces the previous binding. Each id must belong to the cardholder and be denominated in the card''s currency. The list must contain at least one source — to stop a card from spending without removing all sources, transition it to `FROZEN` instead. Cannot be supplied alongside `state: CLOSED`.' + minItems: 1 + items: + type: string + example: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 + CardMerchant: type: object - description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: - - accountId + - descriptor properties: - accountId: + descriptor: type: string - description: The internal account ID this rule applies to. - example: Account:019542f5-b3e7-1d02-0000-000000000001 - executionMode: - $ref: '#/components/schemas/AgentExecutionMode' - perTransactionLimit: - type: - - integer - - 'null' - description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. - example: 10000 - AgentAccountRestrictions: + description: Merchant descriptor string captured from the card network at authorization time. + example: BLUE BOTTLE COFFEE SF + mcc: + type: string + description: Merchant Category Code (ISO 18245) — four-digit numeric string. + example: '5814' + country: + type: string + description: Two-letter ISO 3166-1 alpha-2 country code of the merchant. + example: US + SandboxCardAuthorizationRequest: type: object - description: Optional restrictions that limit the agent to specific accounts or override policy per account. + required: + - amount + - currency + - merchant + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/authorization`. Drives the same internal authorization + reconcile paths that the issuer would call in production. The decisioning outcome is controlled by the last three characters of `merchant.descriptor` — see the endpoint documentation for the suffix table. properties: - allowedAccountIds: - type: - - array - - 'null' - description: If set, restricts the agent to operate only on the specified internal account IDs. Null means the agent can access all accounts. - items: - type: string - example: Account:019542f5-b3e7-1d02-0000-000000000001 - accountRules: - type: array - description: Per-account rules that override the agent's default policy for specific accounts. - items: - $ref: '#/components/schemas/AgentAccountRule' - AgentApprovalThresholds: + amount: + type: integer + format: int64 + description: Authorization amount in the smallest unit of `currency` (e.g. cents for USD). + exclusiveMinimum: 0 + example: 1250 + currency: + $ref: '#/components/schemas/Currency' + merchant: + $ref: '#/components/schemas/CardMerchant' + CardTransactionStatus: + type: string + enum: + - AUTHORIZED + - PARTIALLY_SETTLED + - SETTLED + - REFUNDED + - EXCEPTION + description: | + Lifecycle status of a card transaction. + + | Status | Description | + |--------|-------------| + | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | + | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | + | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. | + | `REFUNDED` | A `RETURN` was received from the merchant; the net settled amount has been refunded in part or whole. | + | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. | + CardPullSummary: type: object - description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. + required: + - count + - totalAmount properties: - currency: - type: string - description: ISO 4217 currency code that the amount threshold is denominated in. Required when amount is set. - example: USD - amount: - type: - - integer - - 'null' - description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. - example: 100000 - AgentPolicy: + count: + type: integer + description: Total number of pulls (debits) executed against the funding source for this transaction. `> 1` indicates one or more post-hoc pulls — e.g. restaurant tip / over-auth clearings. + example: 2 + totalAmount: + type: integer + format: int64 + description: Sum of all pull amounts in the smallest unit of the funding source's currency. + example: 1500 + pendingCount: + type: integer + description: Number of pulls still in the `PENDING` state. Drops to zero when every pull has reached a terminal state. Non-zero values that persist beyond the expected settlement window are an early signal for the `EXCEPTION` path. + example: 0 + CardRefundSummary: type: object - description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: - - permissions - - defaultExecutionMode - - spendingLimits + - count + - totalAmount properties: - permissions: - type: array - description: List of permissions granted to the agent. - items: - $ref: '#/components/schemas/AgentPermission' - defaultExecutionMode: - $ref: '#/components/schemas/AgentExecutionMode' - spendingLimits: - $ref: '#/components/schemas/AgentSpendingLimits' - accountRestrictions: - $ref: '#/components/schemas/AgentAccountRestrictions' - approvalThresholds: - $ref: '#/components/schemas/AgentApprovalThresholds' - AgentUsage: + count: + type: integer + description: Number of refund (return) events received for this transaction. + example: 0 + totalAmount: + type: integer + format: int64 + description: Sum of all refund amounts in the smallest unit of the funding source's currency. + example: 0 + CardSettlementSummary: type: object - description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: - - dailyTransactionCount - - dailySpend - - monthlySpend + - count + - totalAmount properties: - dailyTransactionCount: - type: integer - description: Number of transactions initiated by the agent today. - example: 3 - dailySpend: + count: type: integer - description: Total amount spent by the agent today, in the smallest unit of the policy's `spendingLimits.currency`. - example: 150000 - dailyResetDate: - type: string - format: date - description: The date when daily usage counters will reset. - example: '2025-07-22' - monthlySpend: + description: Number of settlement (clearing) events received for this transaction. + example: 1 + totalAmount: type: integer - description: Total amount spent by the agent this month, in the smallest unit of the policy's `spendingLimits.currency`. - example: 750000 - monthlyResetMonth: - type: string - description: The year-month (YYYY-MM) when monthly usage counters will reset. - example: 2025-08 - Agent: + format: int64 + description: Sum of all settled amounts in the smallest unit of the funding source's currency. + example: 1500 + CardTransaction: type: object - description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: - id - - name - - customerId - - isPaused - - isConnected - - policy - - usage + - cardId + - status + - merchant + - authorizedAmount + - accountId + - pullSummary + - refundSummary + - settlementSummary + - authorizedAt - createdAt - updatedAt + description: Parent transaction row for a card authorization and all of the pulls / settlements / refunds that reconcile against it. Child events are rolled up into the `pullSummary`, `refundSummary`, and `settlementSummary` aggregates. Delivered as the payload of the generic transaction webhook stream (extends the Transaction model with a card destination type) on every transition. properties: id: type: string - description: System-generated unique identifier for the agent. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - name: + description: System-generated unique card transaction identifier + readOnly: true + example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + cardId: type: string - description: Human-readable name for the agent. - example: Payroll Automation Agent - customerId: + description: The id of the `Card` this transaction was made on. + example: Card:019542f5-b3e7-1d02-0000-000000000010 + issuerTransactionToken: type: string - description: The ID of the customer this agent operates on behalf of. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - isPaused: - type: boolean - description: Whether the agent is currently paused. Paused agents cannot initiate any actions. - example: false - isConnected: - type: boolean - description: Whether the agent has been installed and connected (i.e., its device code has been redeemed). - example: true - policy: - $ref: '#/components/schemas/AgentPolicy' - usage: - $ref: '#/components/schemas/AgentUsage' + description: Opaque identifier for the transaction on the underlying issuer. Used to cross-reference Grid records against issuer dashboards and webhooks. + example: lithic_txn_b81c2a4f + readOnly: true + status: + $ref: '#/components/schemas/CardTransactionStatus' + merchant: + $ref: '#/components/schemas/CardMerchant' + authorizedAmount: + $ref: '#/components/schemas/CurrencyAmount' + settledAmount: + $ref: '#/components/schemas/CurrencyAmount' + refundedAmount: + $ref: '#/components/schemas/CurrencyAmount' + accountId: + type: string + description: Internal account id that funded this transaction (the funding source selected by Authorization Decisioning at auth time). + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + pullSummary: + $ref: '#/components/schemas/CardPullSummary' + refundSummary: + $ref: '#/components/schemas/CardRefundSummary' + settlementSummary: + $ref: '#/components/schemas/CardSettlementSummary' + authorizedAt: + type: string + format: date-time + description: When the auth was approved. + example: '2026-05-08T14:30:00Z' + lastEventAt: + type: string + format: date-time + description: Timestamp of the most recent reconcile event (pull / clearing / refund) against this transaction. + example: '2026-05-08T15:42:11Z' createdAt: type: string format: date-time - description: Creation timestamp. - example: '2025-07-21T17:32:28Z' + description: Creation timestamp (same as `authorizedAt` for card transactions). + readOnly: true + example: '2026-05-08T14:30:00Z' updatedAt: type: string format: date-time description: Last update timestamp. - example: '2025-07-21T17:32:28Z' - AgentListResponse: + readOnly: true + example: '2026-05-08T15:42:11Z' + SandboxCardClearingRequest: type: object required: - - data - - hasMore + - cardTransactionId + - amount + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/clearing`. Drives a clearing event against an existing `CardTransaction`. Pass an `amount` greater than the authorized amount to exercise the over-auth / restaurant-tip post-hoc-pull path; pass `0` to exercise `AUTHORIZATION_EXPIRY`. Suffix-driven outcomes on the parent transaction's id govern whether the post-hoc pull succeeds. properties: - data: - type: array - description: List of agents matching the filter criteria. - items: - $ref: '#/components/schemas/Agent' - hasMore: - type: boolean - description: Indicates if more results are available beyond this page. - nextCursor: + cardTransactionId: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true). - totalCount: + description: The id of the `CardTransaction` to clear against. Must be in `AUTHORIZED` or `PARTIALLY_SETTLED` state. + example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + amount: type: integer - description: Total number of agents matching the criteria (excluding pagination). - AgentCreateRequest: - type: object - required: - - name - - customerId - - policy - properties: - name: - type: string - description: Human-readable name to identify the agent. - example: Payroll Automation Agent - customerId: - type: string - description: The ID of the customer this agent will operate on behalf of. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - policy: - $ref: '#/components/schemas/AgentPolicy' - AgentDeviceCode: - type: object - required: - - code - - agentId - - expiresAt - - redeemed - properties: - code: - type: string - description: Human-readable device code used to install and connect the agent software. - example: GRID-AGENT-X7K9-M2P4 - agentId: - type: string - description: The agent this device code belongs to. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - expiresAt: - type: string - format: date-time - description: Timestamp when this device code expires. - example: '2025-07-22T17:32:28Z' - redeemed: - type: boolean - description: Whether this device code has already been redeemed by the agent. - example: false - AgentCreateResponse: - type: object - description: Response returned when an agent is created, including the agent and a device code for installation. - required: - - agent - - deviceCode - properties: - agent: - $ref: '#/components/schemas/Agent' - deviceCode: - $ref: '#/components/schemas/AgentDeviceCode' - AgentActionStatus: - type: string - enum: - - PENDING_APPROVAL - - APPROVED - - REJECTED - - FAILED - description: | - Status of an agent action. - - | Status | Description | - |--------|-------------| - | `PENDING_APPROVAL` | Submitted by the agent, awaiting platform approval before execution | - | `APPROVED` | Approved by the platform; execution is in progress or completed | - | `REJECTED` | Rejected by the platform; the underlying transaction was not executed | - | `FAILED` | Approved but execution failed (e.g. quote expired, insufficient funds) | - AgentActionType: - type: string - enum: - - EXECUTE_QUOTE - - TRANSFER_OUT - - TRANSFER_IN - description: | - The type of action the agent is requesting. - - | Type | Description | - |------|-------------| - | `EXECUTE_QUOTE` | Execute a cross-currency quote | - | `TRANSFER_OUT` | Transfer from an internal account to an external account | - | `TRANSFER_IN` | Transfer from an external account to an internal account | - AgentTransferDetails: + format: int64 + description: Clearing amount in the smallest unit of the transaction's currency. Set to `0` to simulate an authorization expiry with no clearing. + minimum: 0 + example: 1500 + SandboxCardReturnRequest: type: object - description: Details of a transfer-type agent action (TRANSFER_OUT or TRANSFER_IN). required: + - cardTransactionId - amount - - currency - - sourceAccountId - - destinationAccountId - properties: - amount: - type: integer - format: int64 - description: Transfer amount in the smallest unit of the specified currency. - example: 50000 - currency: - type: string - description: ISO 4217 currency code for the transfer amount. - example: USD - sourceAccountId: - type: string - description: ID of the source account (internal or external). - example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 - destinationAccountId: + description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and pushes the parent transaction towards `REFUNDED` (full) or keeps it `SETTLED` (partial). + properties: + cardTransactionId: type: string - description: ID of the destination account (internal or external). - example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - AgentAction: + description: The id of the `CardTransaction` to refund against. Must have at least one settled clearing. + example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + amount: + type: integer + format: int64 + description: Return amount in the smallest unit of the transaction's currency. Must be less than or equal to the net settled amount (settled minus previously-refunded). + exclusiveMinimum: 0 + example: 1500 + StablecoinProvider: + type: string + enum: + - BRALE + description: Stablecoin provider backing the linked account, stablecoin, or operation. + StablecoinProviderAccountStatus: + type: string + enum: + - ACTIVE + - INVALID + - REVOKED + description: Status of the linked stablecoin provider account credentials. + StablecoinProviderEnvironment: + type: string + enum: + - SANDBOX + - PRODUCTION + description: Provider environment derived from the authenticated Grid platform mode. + StablecoinProviderAccount: type: object - description: An action submitted by an agent that may require platform approval before execution. All agent-initiated operations (quote execution, transfers) are represented as AgentActions, giving the platform a consistent object to approve, reject, and audit regardless of the underlying operation type. required: - id - - agentId - - customerId - - platformCustomerId + - provider + - providerAccountId + - providerEnvironment - status - - type - createdAt - updatedAt properties: id: type: string - description: System-generated unique identifier for this action. - example: AgentAction:019542f5-b3e7-1d02-0000-000000000099 - agentId: - type: string - description: The agent that submitted this action. - example: Agent:019542f5-b3e7-1d02-0000-000000000042 - customerId: - type: string - description: The customer on whose behalf the action was submitted. - example: Customer:019542f5-b3e7-1d02-0000-000000000010 - platformCustomerId: + description: System-generated stablecoin provider account link identifier. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + provider: + $ref: '#/components/schemas/StablecoinProvider' + providerAccountId: type: string - description: Platform-specific ID of the customer. - example: user-a1b2c3 + description: Provider account id. + example: 2VcUIonJeVQzFoBuC7LdFT0dRe4 + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' status: - $ref: '#/components/schemas/AgentActionStatus' - type: - $ref: '#/components/schemas/AgentActionType' - quote: - allOf: - - $ref: '#/components/schemas/Quote' - description: The quote being executed. Populated for `EXECUTE_QUOTE` actions; absent for transfer actions. Contains the full amount, currency, destination, and rate details needed to present an approval decision to the user. - transferDetails: - allOf: - - $ref: '#/components/schemas/AgentTransferDetails' - description: Details of the transfer being requested. Populated for `TRANSFER_OUT` and `TRANSFER_IN` actions; absent for `EXECUTE_QUOTE` actions. - transaction: - allOf: - - $ref: '#/components/schemas/TransactionOneOf' - description: The resulting transaction, populated once the action has been approved and execution has begun. Absent while the action is `PENDING_APPROVAL` or `REJECTED`. - rejectionReason: + $ref: '#/components/schemas/StablecoinProviderAccountStatus' + lastVerifiedAt: type: string - description: Human-readable reason provided by the platform when rejecting the action. Only present when status is `REJECTED`. - example: Transaction amount exceeds customer's current risk limit. + format: date-time + description: Timestamp of the last successful provider credential verification. + example: '2026-05-20T16:35:00Z' createdAt: type: string format: date-time - description: When the action was submitted by the agent. - example: '2025-10-03T15:00:00Z' + description: Creation timestamp. + example: '2026-05-20T16:35:00Z' updatedAt: type: string format: date-time - description: When the action was last updated. - example: '2025-10-03T15:02:00Z' - AgentActionListResponse: + description: Last update timestamp. + example: '2026-05-20T16:35:00Z' + StablecoinProviderAccountListResponse: type: object required: - data @@ -18285,252 +19750,349 @@ components: properties: data: type: array - description: List of agent actions matching the filter criteria. items: - $ref: '#/components/schemas/AgentAction' + $ref: '#/components/schemas/StablecoinProviderAccount' hasMore: type: boolean description: Indicates if more results are available beyond this page. nextCursor: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true). + description: Cursor to retrieve the next page of results. totalCount: type: integer - description: Total number of actions matching the criteria (excluding pagination). - AgentUpdateRequest: + description: Total number of stablecoin provider account links matching the criteria. + StablecoinProviderAccountLinkRequest: type: object - description: Partial update to an agent's basic fields. At least one field must be provided. + required: + - provider + - apiClientId + - apiClientSecret properties: - name: + provider: + $ref: '#/components/schemas/StablecoinProvider' + apiClientId: type: string - description: Updated name for the agent. - example: Updated Payroll Agent - isPaused: - type: boolean - description: Set to true to pause the agent or false to resume it. - example: true - AgentSpendingLimitsUpdate: + description: Provider API client id used to verify and link the provider account. + example: provider_client_123 + apiClientSecret: + type: string + writeOnly: true + description: Provider API client secret. Grid verifies and stores this secret encrypted; it is never returned. + example: provider_secret_456 + providerAccountId: + type: string + description: Provider account id. Optional when the submitted credentials expose exactly one provider account. + example: 2VcUIonJeVQzFoBuC7LdFT0dRe4 + StablecoinIssuanceStatus: + type: string + enum: + - PENDING_REVIEW + - PROVISIONING + - PROVISIONED + - REJECTED + - FAILED + description: Provider issuance/linking status for the registered stablecoin. + StablecoinGridOperationsStatus: + type: string + enum: + - NOT_ENABLED + - PENDING_APPROVAL + - ENABLING + - ENABLED + - DISABLED + description: Whether the stablecoin has been enabled for normal Grid operations. + StablecoinNetwork: + type: string + enum: + - SPARK_MAINNET + description: Network namespace for the stablecoin token identifier. + Stablecoin: type: object - description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. + required: + - id + - name + - symbol + - baseCurrency + - network + - decimals + - issuanceStatus + - gridOperationsStatus + - networkTokenIdentifier + - provider + - stablecoinProviderAccountId + - providerEnvironment + - providerTokenIdentifier + - createdAt + - updatedAt properties: - currency: + id: type: string - description: ISO 4217 currency code that all amount limits are denominated in. Updating this recasts all existing limits into the new currency denomination. + description: System-generated stablecoin identifier. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + name: + type: string + description: Stablecoin display name. + example: Acme Dollar + symbol: + type: string + description: Stablecoin symbol. + example: ACME + baseCurrency: + type: string + description: Fiat currency the stablecoin is denominated against. example: USD - perTransactionLimit: - type: integer - description: Maximum amount per transaction. - example: 50000 - dailyLimit: - type: - - integer - - 'null' - description: Maximum daily spend. Set to null to remove the daily limit. - example: 500000 - dailyTransactionLimit: + network: + $ref: '#/components/schemas/StablecoinNetwork' + decimals: type: integer - description: Maximum number of transactions per day. - example: 10 - monthlyLimit: - type: - - integer - - 'null' - description: Maximum monthly spend. Set to null to remove the monthly limit. - example: 5000000 - AgentPolicyUpdateRequest: - type: object - description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. - properties: - permissions: - type: array - description: Updated list of permissions. Replaces the entire permissions list when provided. - items: - $ref: '#/components/schemas/AgentPermission' - defaultExecutionMode: - $ref: '#/components/schemas/AgentExecutionMode' - spendingLimits: - $ref: '#/components/schemas/AgentSpendingLimitsUpdate' - accountRestrictions: - $ref: '#/components/schemas/AgentAccountRestrictions' - approvalThresholds: - $ref: '#/components/schemas/AgentApprovalThresholds' - AgentActionRejectRequest: - type: object - properties: - reason: + description: Number of decimal places used by the stablecoin. + example: 6 + issuanceStatus: + $ref: '#/components/schemas/StablecoinIssuanceStatus' + gridOperationsStatus: + $ref: '#/components/schemas/StablecoinGridOperationsStatus' + networkTokenIdentifier: + type: string + description: Token identifier in the namespace selected by `network`. + example: btkn1qw508d6qejxtdg4y5r3zarvary0c5xw7k + currency: type: string - description: Optional human-readable reason for the rejection, stored on the action and visible to the platform. - example: Transaction amount exceeds customer's current risk limit. - AgentDeviceCodeStatusResponse: + description: Grid currency code after the stablecoin is enabled for Grid operations. + example: ACME + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link selected for this stablecoin. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + providerTokenIdentifier: + type: string + description: Provider token identifier. For Brale this maps to `value_type`. + example: ACME + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T16:40:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:10:00Z' + StablecoinListResponse: type: object required: - - code - - redeemed + - data + - hasMore properties: - code: - type: string - description: The device code. - example: GRID-AGENT-X7K9-M2P4 - redeemed: + data: + type: array + items: + $ref: '#/components/schemas/Stablecoin' + hasMore: type: boolean - description: Whether this device code has been redeemed. - example: false - AgentDeviceCodeRedeemResponse: + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results. + totalCount: + type: integer + description: Total number of stablecoins matching the criteria. + StablecoinRegisterRequest: type: object required: - - agentId - - agentName - - accessToken - - policy + - providerTokenIdentifier + - networkTokenIdentifier + - network properties: - agentId: + providerTokenIdentifier: type: string - description: The agent's system-generated ID. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - agentName: + description: Provider identifier for the stablecoin. For Brale this maps to `value_type`. + example: ACME + networkTokenIdentifier: type: string - description: The agent's name. - example: Payroll Automation Agent - accessToken: + description: Token identifier in the namespace selected by `network`. + example: btkn1qw508d6qejxtdg4y5r3zarvary0c5xw7k + network: + $ref: '#/components/schemas/StablecoinNetwork' + stablecoinProviderAccountId: type: string - description: 'Bearer token used to authenticate all subsequent API calls as this agent. Pass as `Authorization: Bearer `. This token is returned only once and must be stored securely — it cannot be retrieved again.' - example: gat_ed0ad25881e234cc28fb2dec0a4fe64e4172a3b9 - policy: - $ref: '#/components/schemas/AgentPolicy' - CardState: + description: Provider account link to register against. Optional when exactly one active link exists for the authenticated platform; required to resolve STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED when multiple links exist. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + StablecoinExternalAccountType: type: string enum: - - PENDING_KYC - - PENDING_ISSUE - - ACTIVE - - FROZEN - - CLOSED - description: | - Lifecycle state of a card. - - | State | Description | - |-------|-------------| - | `PENDING_KYC` | The cardholder has not yet completed KYC. Cards in this state cannot transact. | - | `PENDING_ISSUE` | The card has been requested and is being provisioned with the issuer. | - | `ACTIVE` | The card is live and can authorize transactions. | - | `FROZEN` | The card is temporarily disabled by the platform. New authorizations are declined with `CARD_PAUSED`. Existing settlements and refunds continue to reconcile. | - | `CLOSED` | The card is permanently closed. Terminal, irreversible state. | - CardStateReason: + - US_BANK_ACCOUNT + description: External account type supported for stablecoin provider linking. + StablecoinTransferType: type: string enum: - - ISSUER_REJECTED - - CLOSED_BY_PLATFORM - - CLOSED_BY_GRID - description: | - Reason a card reached a terminal or non-active state. Present on - `CLOSED` cards, and on cards that fail provisioning before reaching - `ACTIVE`. - - | Reason | Description | - |--------|-------------| - | `ISSUER_REJECTED` | The card issuer rejected provisioning during `PENDING_ISSUE`. | - | `CLOSED_BY_PLATFORM` | The card was closed via `PATCH /cards/{id}` (`state: CLOSED`) by the platform. | - | `CLOSED_BY_GRID` | The card was closed by Grid (e.g. compliance or risk action). | - CardBrand: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Provider-supported transfer type for stablecoin funding or redemption. + StablecoinExternalAccountOwner: + type: object + required: + - legalName + properties: + legalName: + type: string + description: Legal name of the account owner. + example: Acme Inc + emailAddress: + type: string + format: email + description: Email address for the account owner. + example: finance@example.com + phoneNumber: + type: string + description: Phone number for the account owner. + example: '+14155550100' + dateOfBirth: + type: string + format: date + description: Date of birth when required by the provider link flow. + example: '1990-01-01' + StablecoinExternalAccountLinkSessionCreateRequest: + type: object + required: + - provider + - accountType + - requestedTransferTypes + - owner + properties: + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link that should own the linked external account. Optional when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + requestedTransferTypes: + type: array + items: + $ref: '#/components/schemas/StablecoinTransferType' + owner: + $ref: '#/components/schemas/StablecoinExternalAccountOwner' + StablecoinExternalAccountLinkSession: + type: object + required: + - id + - provider + - stablecoinProviderAccountId + - accountType + - linkToken + - expiresAt + - createdAt + properties: + id: + type: string + description: System-generated stablecoin external-account link-session identifier. + example: StablecoinExternalAccountLinkSession:019542f5-b3e7-1d02-0000-000000000003 + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link selected for this session. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + linkToken: + type: string + description: Provider/Plaid frontend token for the link flow. + example: link-sandbox-123 + expiresAt: + type: string + format: date-time + description: Link token expiration timestamp. + example: '2026-05-20T18:20:00Z' + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:20:00Z' + StablecoinExternalAccountStatus: type: string enum: - - VISA - - MASTERCARD - description: | - Card network brand. Read-only — determined by Grid when the card is - provisioned with the issuer. - CardForm: + - ACTIVE + - INACTIVE + - NEEDS_UPDATE + - FAILED + description: Status of a provider-linked stablecoin external account. NEEDS_UPDATE indicates the provider link requires attention (for example Plaid reauthentication). + StablecoinExternalAccountCreationMethod: type: string enum: - - VIRTUAL - description: | - Physical form factor of the card. Only `VIRTUAL` is supported in v1; - `PHYSICAL` will be added in a later release. - Card: + - GRID_EXTERNAL_ACCOUNT + - PLAID + - DIRECT_BANK_ENTRY + description: How the stablecoin external account was linked. + StablecoinExternalAccount: type: object required: - id - - cardholderId - - state - - form - - fundingSources + - provider + - stablecoinProviderAccountId + - providerEnvironment + - accountType + - creationMethod + - status + - supportedTransferTypes - createdAt - updatedAt properties: id: type: string - description: System-generated unique card identifier - readOnly: true - example: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: - type: string - description: The id of the `Customer` who holds this card. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: - type: string - description: Platform-specific card identifier. Optional on create — system-generated if omitted, mirroring `platformCustomerId` semantics. - example: card-emp-aary-001 - state: - $ref: '#/components/schemas/CardState' - stateReason: - anyOf: - - $ref: '#/components/schemas/CardStateReason' - - type: 'null' - description: Reason associated with the current `state`. Populated when the card is `CLOSED` or when provisioning was rejected; otherwise null. - brand: - $ref: '#/components/schemas/CardBrand' - form: - $ref: '#/components/schemas/CardForm' - last4: + description: System-generated stablecoin external account identifier. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: type: string - description: Last four digits of the card PAN. - example: '4242' - expMonth: - type: integer - minimum: 1 - maximum: 12 - description: Card expiration month (1–12). - example: 12 - expYear: - type: integer - description: Card expiration year (four digits). - example: 2029 - panEmbedUrl: + description: Stablecoin provider account link for this external account. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + creationMethod: + $ref: '#/components/schemas/StablecoinExternalAccountCreationMethod' + status: + $ref: '#/components/schemas/StablecoinExternalAccountStatus' + gridExternalAccountId: type: string - format: uri - description: URL of the card issuer's iframe that securely displays the PAN, CVV, and expiry to the cardholder. The full PAN and CVV never cross Grid's servers — render this URL in an iframe in your client to reveal card details. - example: https://embed.lithic.com/iframe/...?t=... - fundingSources: + description: Linked normal Grid external account id, when one exists. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000004 + supportedTransferTypes: type: array - description: Internal account ids bound to this card as funding sources, in priority order — the first entry is tried first by Authorization Decisioning. Every card has at least one funding source. items: - type: string - example: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 - currency: + $ref: '#/components/schemas/StablecoinTransferType' + providerStatus: type: string - description: Currency the card transacts in (ISO 4217 for fiat, tickers for crypto). Derived from the funding sources at issue time — all funding sources bound to a card must be denominated in the same card-eligible currency. - example: USD - readOnly: true - issuerRef: + description: Safe provider status summary. + example: active + lastVerifiedAt: type: string - description: Opaque identifier for the card on the underlying issuer. Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. - example: lithic_card_4f8d3a2b1c - readOnly: true + format: date-time + description: Timestamp of the last successful provider external-account verification. + example: '2026-05-20T17:25:00Z' createdAt: type: string format: date-time - description: Creation timestamp - readOnly: true - example: '2026-05-08T14:10:00Z' + description: Creation timestamp. + example: '2026-05-20T17:25:00Z' updatedAt: type: string format: date-time - description: Last update timestamp - readOnly: true - example: '2026-05-08T14:11:00Z' - CardListResponse: + description: Last update timestamp. + example: '2026-05-20T17:25:00Z' + StablecoinExternalAccountListResponse: type: object required: - data @@ -18538,273 +20100,579 @@ components: properties: data: type: array - description: List of cards matching the filter criteria items: - $ref: '#/components/schemas/Card' + $ref: '#/components/schemas/StablecoinExternalAccount' hasMore: type: boolean - description: Indicates if more results are available beyond this page + description: Indicates if more results are available beyond this page. nextCursor: type: string - description: Cursor to retrieve the next page of results (only present if hasMore is true) + description: Cursor to retrieve the next page of results. totalCount: type: integer - description: Total number of cards matching the criteria (excluding pagination) - CardCreateRequest: + description: Total number of stablecoin external accounts matching the criteria. + StablecoinExternalAccountGridLinkRequest: type: object required: - - cardholderId - - form - - fundingSources + - creationMethod + - provider + - gridExternalAccountId + - requestedTransferTypes properties: - cardholderId: + creationMethod: type: string - description: The id of the `Customer` to issue the card to. The customer must have KYC status `APPROVED`; otherwise the request is rejected with `CARDHOLDER_KYC_NOT_APPROVED`. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: + enum: + - GRID_EXTERNAL_ACCOUNT + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: type: string - description: Optional platform-specific card identifier. System-generated when omitted, mirroring `platformCustomerId` semantics. - example: card-emp-aary-001 - form: - $ref: '#/components/schemas/CardForm' - fundingSources: + description: Stablecoin provider account link that should own the linked external account. Optional when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + gridExternalAccountId: + type: string + description: Existing Grid external account to link to the provider. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000004 + requestedTransferTypes: type: array - description: Internal account ids to bind as funding sources, in priority order. The first entry is tried first by Authorization Decisioning. Every card must be bound to at least one source, and every source must belong to the cardholder and be denominated in a card-eligible currency (USDB in v1); otherwise the request is rejected with `FUNDING_SOURCE_INELIGIBLE`. - minItems: 1 items: - type: string - example: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - CardUpdateRequest: + $ref: '#/components/schemas/StablecoinTransferType' + StablecoinExternalAccountProviderLinkRequest: type: object - description: Update request for `PATCH /cards/{id}`. At least one of `state` or `fundingSources` must be supplied. `state` transitions are limited to `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`; any other transition returns `409 INVALID_STATE_TRANSITION`. `CLOSED` is terminal and irreversible and cannot be combined with `fundingSources`. `fundingSources`, when supplied, fully replaces the card's bound funding sources — the array order determines the priority Authorization Decisioning tries them in. + required: + - creationMethod + - provider + - linkSessionId + - linkResultToken + - requestedTransferTypes properties: - state: + creationMethod: type: string enum: - - ACTIVE - - FROZEN - - CLOSED - description: Target state for the card. Permitted transitions are `ACTIVE ⇄ FROZEN` and `ACTIVE | FROZEN → CLOSED`. `CLOSED` is terminal and irreversible; once closed, the card stays in the system for audit and reconciliation but cannot transact again. - example: FROZEN - fundingSources: + - PLAID + provider: + $ref: '#/components/schemas/StablecoinProvider' + linkSessionId: + type: string + description: Stablecoin external-account link-session id. + example: StablecoinExternalAccountLinkSession:019542f5-b3e7-1d02-0000-000000000003 + linkResultToken: + type: string + writeOnly: true + description: Provider/Plaid public token returned by the frontend link flow. + example: public-sandbox-123 + requestedTransferTypes: type: array - description: 'New ordered list of internal account ids to bind as funding sources. Fully replaces the previous binding. Each id must belong to the cardholder and be denominated in the card''s currency. The list must contain at least one source — to stop a card from spending without removing all sources, transition it to `FROZEN` instead. Cannot be supplied alongside `state: CLOSED`.' - minItems: 1 items: - type: string - example: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - - InternalAccount:019542f5-b3e7-1d02-0000-000000000003 - CardMerchant: + $ref: '#/components/schemas/StablecoinTransferType' + StablecoinDirectEntryUsBankDetails: type: object required: - - descriptor + - routingNumber + - accountNumber + - accountType + - accountHolderName properties: - descriptor: + routingNumber: type: string - description: Merchant descriptor string captured from the card network at authorization time. - example: BLUE BOTTLE COFFEE SF - mcc: + writeOnly: true + description: US bank routing number. + example: '021000021' + accountNumber: + type: string + writeOnly: true + description: US bank account number. + example: '123456789' + accountType: + type: string + enum: + - CHECKING + - SAVINGS + description: US bank account type. + accountHolderName: + type: string + description: Bank account holder legal name. + example: Acme Inc + institutionName: + type: string + description: Bank/institution display name. + example: Example Bank + beneficiaryAddress: + allOf: + - $ref: '#/components/schemas/Address' + description: Beneficiary postal address. Required by some payout rails (especially WIRE) and when `createGridExternalAccount` is true. + bankAddress: + allOf: + - $ref: '#/components/schemas/Address' + description: Bank branch postal address. Required by some payout rails (especially WIRE). + StablecoinExternalAccountDirectEntryRequest: + type: object + required: + - creationMethod + - provider + - accountType + - requestedTransferTypes + - bankDetails + properties: + creationMethod: + type: string + enum: + - DIRECT_BANK_ENTRY + provider: + $ref: '#/components/schemas/StablecoinProvider' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link that should own the linked external account. Optional when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: '#/components/schemas/StablecoinExternalAccountType' + requestedTransferTypes: + type: array + items: + $ref: '#/components/schemas/StablecoinTransferType' + bankDetails: + $ref: '#/components/schemas/StablecoinDirectEntryUsBankDetails' + createGridExternalAccount: + type: boolean + description: Whether Grid should also create a normal Grid external account when the request contains enough data. + example: true + StablecoinExternalAccountLinkRequest: + oneOf: + - $ref: '#/components/schemas/StablecoinExternalAccountGridLinkRequest' + - $ref: '#/components/schemas/StablecoinExternalAccountProviderLinkRequest' + - $ref: '#/components/schemas/StablecoinExternalAccountDirectEntryRequest' + discriminator: + propertyName: creationMethod + mapping: + GRID_EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinExternalAccountGridLinkRequest' + PLAID: '#/components/schemas/StablecoinExternalAccountProviderLinkRequest' + DIRECT_BANK_ENTRY: '#/components/schemas/StablecoinExternalAccountDirectEntryRequest' + StablecoinAmount: + type: string + pattern: ^[1-9][0-9]*$ + description: Amount in the stablecoin's smallest unit, as a base-10 integer string (uint128 range). Strings avoid JavaScript precision loss. Must convert exactly to a provider-representable fiat amount (whole cents for USD). + example: '100000000' + StablecoinWireMintFundingSource: + type: object + required: + - type + properties: + type: + type: string + enum: + - WIRE + StablecoinAchDebitMintFundingSource: + type: object + required: + - type + - stablecoinExternalAccountId + properties: + type: + type: string + enum: + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + stablecoinExternalAccountId: + type: string + description: Linked provider external account to debit. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + StablecoinCryptoNetwork: + type: string + enum: + - ETHEREUM + - SOLANA + - BASE + - POLYGON + - SPARK + - TRON + description: Crypto network used by a provider token-balance funding source. + StablecoinProviderTokenBalanceMintFundingSource: + type: object + required: + - type + - sourceTokenIdentifier + - cryptoNetwork + properties: + type: + type: string + enum: + - PROVIDER_TOKEN_BALANCE + sourceTokenIdentifier: + type: string + description: Provider token/value identifier to fund the mint from. + example: USDC + cryptoNetwork: + $ref: '#/components/schemas/StablecoinCryptoNetwork' + StablecoinMintFundingSource: + oneOf: + - $ref: '#/components/schemas/StablecoinWireMintFundingSource' + - $ref: '#/components/schemas/StablecoinAchDebitMintFundingSource' + - $ref: '#/components/schemas/StablecoinProviderTokenBalanceMintFundingSource' + discriminator: + propertyName: type + mapping: + WIRE: '#/components/schemas/StablecoinWireMintFundingSource' + ACH_DEBIT: '#/components/schemas/StablecoinAchDebitMintFundingSource' + SAME_DAY_ACH_DEBIT: '#/components/schemas/StablecoinAchDebitMintFundingSource' + PROVIDER_TOKEN_BALANCE: '#/components/schemas/StablecoinProviderTokenBalanceMintFundingSource' + StablecoinMintDestination: + type: object + required: + - type + - sparkAddress + properties: + type: + type: string + enum: + - SPARK_ADDRESS + sparkAddress: + type: string + description: Destination Spark address that should receive the minted stablecoin. + example: sp1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq + StablecoinMintQuoteRequest: + type: object + required: + - operationType + - amount + - fundingSource + - destination + properties: + operationType: + type: string + enum: + - MINT + amount: + $ref: '#/components/schemas/StablecoinAmount' + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + destination: + $ref: '#/components/schemas/StablecoinMintDestination' + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Initial mint + StablecoinBurnSource: + type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + accountId: type: string - description: Merchant Category Code (ISO 18245) — four-digit numeric string. - example: '5814' - country: + description: Grid-controlled internal account holding the stablecoin balance to redeem. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000006 + StablecoinPayoutRail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail for a burn/redemption. Debit rails are funding-only and are not valid payout rails. + StablecoinBurnDestination: + type: object + required: + - type + - stablecoinExternalAccountId + - rail + properties: + type: type: string - description: Two-letter ISO 3166-1 alpha-2 country code of the merchant. - example: US - SandboxCardAuthorizationRequest: + enum: + - STABLECOIN_EXTERNAL_ACCOUNT + stablecoinExternalAccountId: + type: string + description: Linked stablecoin external account to receive the fiat redemption. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + rail: + $ref: '#/components/schemas/StablecoinPayoutRail' + StablecoinBurnQuoteRequest: type: object required: + - operationType - amount - - currency - - merchant - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/authorization`. Drives the same internal authorization + reconcile paths that the issuer would call in production. The decisioning outcome is controlled by the last three characters of `merchant.descriptor` — see the endpoint documentation for the suffix table. + - source + - destination properties: + operationType: + type: string + enum: + - BURN amount: - type: integer - format: int64 - description: Authorization amount in the smallest unit of `currency` (e.g. cents for USD). - exclusiveMinimum: 0 - example: 1250 - currency: - $ref: '#/components/schemas/Currency' - merchant: - $ref: '#/components/schemas/CardMerchant' - CardTransactionStatus: + $ref: '#/components/schemas/StablecoinAmount' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + destination: + $ref: '#/components/schemas/StablecoinBurnDestination' + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Redeem ACME + StablecoinQuoteRequest: + oneOf: + - $ref: '#/components/schemas/StablecoinMintQuoteRequest' + - $ref: '#/components/schemas/StablecoinBurnQuoteRequest' + discriminator: + propertyName: operationType + mapping: + MINT: '#/components/schemas/StablecoinMintQuoteRequest' + BURN: '#/components/schemas/StablecoinBurnQuoteRequest' + StablecoinOperationType: type: string enum: - - AUTHORIZED - - PARTIALLY_SETTLED - - SETTLED - - REFUNDED - - EXCEPTION - description: | - Lifecycle status of a card transaction. - - | Status | Description | - |--------|-------------| - | `AUTHORIZED` | The auth has been approved and a hold placed on the funding source; no clearing has arrived yet. | - | `PARTIALLY_SETTLED` | At least one clearing has arrived and posted, but more clearings are still expected (split shipments, tips, multi-leg trips). | - | `SETTLED` | All clearings for the auth have posted and the transaction is closed against the funding source. | - | `REFUNDED` | A `RETURN` was received from the merchant; the net settled amount has been refunded in part or whole. | - | `EXCEPTION` | The transaction settled to the card network but the corresponding pull from the funding source failed (e.g. balance no longer covers the post-hoc clearing). Surfaces high-urgency alerts and is the dashboard query for stuck reconciliations. | - CardPullSummary: + - MINT + - BURN + description: Stablecoin issuer operation type. + StablecoinQuoteStatus: + type: string + enum: + - OPEN + - EXECUTED + - EXPIRED + - FAILED + description: Current status of the stablecoin quote. + StablecoinFee: type: object required: - - count - - totalAmount + - type + - amount + - currency properties: - count: - type: integer - description: Total number of pulls (debits) executed against the funding source for this transaction. `> 1` indicates one or more post-hoc pulls — e.g. restaurant tip / over-auth clearings. - example: 2 - totalAmount: - type: integer - format: int64 - description: Sum of all pull amounts in the smallest unit of the funding source's currency. - example: 1500 - pendingCount: - type: integer - description: Number of pulls still in the `PENDING` state. Drops to zero when every pull has reached a terminal state. Non-zero values that persist beyond the expected settlement window are an early signal for the `EXCEPTION` path. - example: 0 - CardRefundSummary: + type: + type: string + description: Fee type identifier (for example PROVIDER, GRID, RAIL, NETWORK). + example: PROVIDER + amount: + type: string + pattern: ^[0-9]+$ + description: Fee amount as a base-10 integer string in the smallest unit of `currency`. + example: '0' + currency: + type: string + description: Currency of the fee amount. + example: USD + StablecoinFundingInstructions: type: object + description: Sanitized funding instructions for the selected funding rail. Shape varies by rail; contains only intentionally public deposit coordinates. required: - - count - - totalAmount + - rail properties: - count: - type: integer - description: Number of refund (return) events received for this transaction. - example: 0 - totalAmount: - type: integer - format: int64 - description: Sum of all refund amounts in the smallest unit of the funding source's currency. - example: 0 - CardSettlementSummary: + rail: + $ref: '#/components/schemas/StablecoinTransferType' + additionalProperties: true + StablecoinEstimatedDelivery: type: object + description: Sanitized fiat delivery estimate for a burn/redemption. required: - - count - - totalAmount + - rail + - amount + - currency properties: - count: - type: integer - description: Number of settlement (clearing) events received for this transaction. - example: 1 - totalAmount: - type: integer - format: int64 - description: Sum of all settled amounts in the smallest unit of the funding source's currency. - example: 1500 - CardTransaction: + rail: + $ref: '#/components/schemas/StablecoinPayoutRail' + amount: + type: string + pattern: ^[0-9]+$ + description: Estimated delivery amount as a base-10 integer string in the smallest unit of `currency`. + example: '100000000' + currency: + type: string + description: Currency of the estimated delivery. + example: USD + StablecoinQuote: type: object required: - id - - cardId + - stablecoinId + - operationType - status - - merchant - - authorizedAmount - - accountId - - pullSummary - - refundSummary - - settlementSummary - - authorizedAt + - amount + - expiresAt + - fees - createdAt - - updatedAt - description: Parent transaction row for a card authorization and all of the pulls / settlements / refunds that reconcile against it. Child events are rolled up into the `pullSummary`, `refundSummary`, and `settlementSummary` aggregates. Delivered as the payload of the generic transaction webhook stream (extends the Transaction model with a card destination type) on every transition. properties: id: type: string - description: System-generated unique card transaction identifier - readOnly: true - example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 - cardId: - type: string - description: The id of the `Card` this transaction was made on. - example: Card:019542f5-b3e7-1d02-0000-000000000010 - issuerTransactionToken: + description: System-generated stablecoin quote identifier. + example: StablecoinQuote:019542f5-b3e7-1d02-0000-000000000008 + stablecoinId: type: string - description: Opaque identifier for the transaction on the underlying issuer. Used to cross-reference Grid records against issuer dashboards and webhooks. - example: lithic_txn_b81c2a4f - readOnly: true + description: Stablecoin this quote belongs to. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + operationType: + $ref: '#/components/schemas/StablecoinOperationType' status: - $ref: '#/components/schemas/CardTransactionStatus' - merchant: - $ref: '#/components/schemas/CardMerchant' - authorizedAmount: - $ref: '#/components/schemas/CurrencyAmount' - settledAmount: - $ref: '#/components/schemas/CurrencyAmount' - refundedAmount: - $ref: '#/components/schemas/CurrencyAmount' - accountId: - type: string - description: Internal account id that funded this transaction (the funding source selected by Authorization Decisioning at auth time). - example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - pullSummary: - $ref: '#/components/schemas/CardPullSummary' - refundSummary: - $ref: '#/components/schemas/CardRefundSummary' - settlementSummary: - $ref: '#/components/schemas/CardSettlementSummary' - authorizedAt: + $ref: '#/components/schemas/StablecoinQuoteStatus' + amount: + $ref: '#/components/schemas/StablecoinAmount' + expiresAt: type: string format: date-time - description: When the auth was approved. - example: '2026-05-08T14:30:00Z' - lastEventAt: + description: Quote expiration time. Execution rejects expired quotes. + example: '2026-05-20T17:25:00Z' + fees: + type: array + items: + $ref: '#/components/schemas/StablecoinFee' + description: Previewed provider, Grid, rail, or network fees. + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + destination: + description: Quoted destination. For mints this is a Spark address destination; for burns this is a linked stablecoin external account destination. + oneOf: + - $ref: '#/components/schemas/StablecoinMintDestination' + - $ref: '#/components/schemas/StablecoinBurnDestination' + discriminator: + propertyName: type + mapping: + SPARK_ADDRESS: '#/components/schemas/StablecoinMintDestination' + STABLECOIN_EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinBurnDestination' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + fundingInstructions: + $ref: '#/components/schemas/StablecoinFundingInstructions' + estimatedDelivery: + $ref: '#/components/schemas/StablecoinEstimatedDelivery' + operationId: + type: string + description: Operation created by executing this quote, when the quote has been executed. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000007 + description: type: string - format: date-time - description: Timestamp of the most recent reconcile event (pull / clearing / refund) against this transaction. - example: '2026-05-08T15:42:11Z' + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Initial mint createdAt: type: string format: date-time - description: Creation timestamp (same as `authorizedAt` for card transactions). - readOnly: true - example: '2026-05-08T14:30:00Z' + description: Creation timestamp. + example: '2026-05-20T17:20:00Z' updatedAt: type: string format: date-time description: Last update timestamp. - readOnly: true - example: '2026-05-08T15:42:11Z' - SandboxCardClearingRequest: + example: '2026-05-20T17:25:00Z' + StablecoinOperationStatus: + type: string + enum: + - CREATED + - PENDING + - PROCESSING + - COMPLETED + - FAILED + - EXPIRED + description: Current status of the stablecoin operation. EXPIRED applies to wire-funded mints that were never funded within the expiry window. Provider-canceled states map to FAILED with a stable failure reason. + StablecoinOperation: type: object required: - - cardTransactionId + - id + - stablecoinId + - operationType + - status - amount - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/clearing`. Drives a clearing event against an existing `CardTransaction`. Pass an `amount` greater than the authorized amount to exercise the over-auth / restaurant-tip post-hoc-pull path; pass `0` to exercise `AUTHORIZATION_EXPIRY`. Suffix-driven outcomes on the parent transaction's id govern whether the post-hoc pull succeeds. + - provider + - providerEnvironment + - stablecoinProviderAccountId + - createdAt + - updatedAt properties: - cardTransactionId: + id: type: string - description: The id of the `CardTransaction` to clear against. Must be in `AUTHORIZED` or `PARTIALLY_SETTLED` state. - example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 + description: System-generated stablecoin operation identifier. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000007 + stablecoinId: + type: string + description: Stablecoin this operation belongs to. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + operationType: + $ref: '#/components/schemas/StablecoinOperationType' + status: + $ref: '#/components/schemas/StablecoinOperationStatus' amount: - type: integer - format: int64 - description: Clearing amount in the smallest unit of the transaction's currency. Set to `0` to simulate an authorization expiry with no clearing. - minimum: 0 - example: 1500 - SandboxCardReturnRequest: + $ref: '#/components/schemas/StablecoinAmount' + quoteId: + type: string + description: Quote that produced this operation. + example: StablecoinQuote:019542f5-b3e7-1d02-0000-000000000008 + provider: + $ref: '#/components/schemas/StablecoinProvider' + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link used by this operation. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + fundingInstructions: + $ref: '#/components/schemas/StablecoinFundingInstructions' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + destination: + description: Stablecoin operation destination. For mints this is a Spark address; for burns this is a linked stablecoin external account. + oneOf: + - $ref: '#/components/schemas/StablecoinMintDestination' + - $ref: '#/components/schemas/StablecoinBurnDestination' + discriminator: + propertyName: type + mapping: + SPARK_ADDRESS: '#/components/schemas/StablecoinMintDestination' + STABLECOIN_EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinBurnDestination' + estimatedDelivery: + $ref: '#/components/schemas/StablecoinEstimatedDelivery' + expiresAt: + type: string + format: date-time + description: Expiry for operations that wait on external funding (wire-funded mints). Past-due unfunded operations transition to EXPIRED. + example: '2026-06-19T17:20:00Z' + providerStatus: + type: string + description: Safe provider status summary. + example: processing + failureReason: + type: string + description: Safe failure reason, when the operation failed. + example: provider_rejected + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description copied from the executed quote. + example: Initial mint + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:30:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:35:00Z' + StablecoinOperationListResponse: type: object required: - - cardTransactionId - - amount - description: Sandbox-only request body for `POST /sandbox/cards/{id}/simulate/return`. Drives a `RETURN` event against an existing settled `CardTransaction`, which creates a `CardRefund` and pushes the parent transaction towards `REFUNDED` (full) or keeps it `SETTLED` (partial). + - data + - hasMore properties: - cardTransactionId: + data: + type: array + items: + $ref: '#/components/schemas/StablecoinOperation' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: type: string - description: The id of the `CardTransaction` to refund against. Must have at least one settled clearing. - example: CardTransaction:019542f5-b3e7-1d02-0000-000000000100 - amount: + description: Cursor to retrieve the next page of results. + totalCount: type: integer - format: int64 - description: Return amount in the smallest unit of the transaction's currency. Must be less than or equal to the net settled amount (settled minus previously-refunded). - exclusiveMinimum: 0 - example: 1500 + description: Total number of stablecoin operations matching the criteria. WebhookType: type: string enum: diff --git a/openapi/components/schemas/errors/Error400.yaml b/openapi/components/schemas/errors/Error400.yaml index 10c75ed8..0ecb8c8f 100644 --- a/openapi/components/schemas/errors/Error400.yaml +++ b/openapi/components/schemas/errors/Error400.yaml @@ -49,6 +49,22 @@ properties: | INCOMPLETE | Document is missing pages or sides | | EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS | An EMAIL_OTP credential is already registered on the target internal account; only one email OTP credential is supported per internal account at this time | | PASSKEY_CREDENTIAL_ALREADY_EXISTS | A PASSKEY credential with the same WebAuthn credentialId is already registered on the target internal account | + | STABLECOIN_PROVIDER_ACCOUNT_INVALID | The stablecoin provider account link is not usable | + | STABLECOIN_PROVIDER_ACCOUNT_REVOKED | The stablecoin provider account link has been revoked | + | STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED | Multiple active provider account links exist; pass `stablecoinProviderAccountId` to select one | + | STABLECOIN_VERIFICATION_FAILED | Provider verification of the stablecoin or credentials failed | + | STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED | Linking the external account with the provider failed | + | STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED | The request must specify a supported external-account link method | + | STABLECOIN_NOT_PROVISIONED | The stablecoin is not provisioned with the provider | + | STABLECOIN_GRID_OPERATIONS_NOT_ENABLED | Grid operations are not enabled for this stablecoin | + | STABLECOIN_QUOTE_EXPIRED | The stablecoin quote has expired | + | STABLECOIN_AMOUNT_NOT_REPRESENTABLE | The amount cannot be represented in the target currency or token precision | + | STABLECOIN_OPERATION_NOT_SUPPORTED | The requested stablecoin operation is not supported | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED | The stablecoin external account is not linked or not active | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED | The stablecoin external account does not support the requested transfer type | + | STABLECOIN_BURN_SOURCE_NOT_SUPPORTED | The burn source account is not supported | + | STABLECOIN_PROVIDER_SOURCE_NOT_LINKED | The provider token-balance funding source is not linked | + | STABLECOIN_PROVIDER_ERROR | The stablecoin provider rejected or failed the request | enum: - INVALID_INPUT - MISSING_MANDATORY_USER_INFO @@ -85,6 +101,22 @@ properties: - INCOMPLETE - EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS - PASSKEY_CREDENTIAL_ALREADY_EXISTS + - STABLECOIN_PROVIDER_ACCOUNT_INVALID + - STABLECOIN_PROVIDER_ACCOUNT_REVOKED + - STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED + - STABLECOIN_VERIFICATION_FAILED + - STABLECOIN_EXTERNAL_ACCOUNT_LINK_FAILED + - STABLECOIN_EXTERNAL_ACCOUNT_LINK_METHOD_REQUIRED + - STABLECOIN_NOT_PROVISIONED + - STABLECOIN_GRID_OPERATIONS_NOT_ENABLED + - STABLECOIN_QUOTE_EXPIRED + - STABLECOIN_AMOUNT_NOT_REPRESENTABLE + - STABLECOIN_OPERATION_NOT_SUPPORTED + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_LINKED + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_SUPPORTED + - STABLECOIN_BURN_SOURCE_NOT_SUPPORTED + - STABLECOIN_PROVIDER_SOURCE_NOT_LINKED + - STABLECOIN_PROVIDER_ERROR message: type: string description: Error message diff --git a/openapi/components/schemas/errors/Error404.yaml b/openapi/components/schemas/errors/Error404.yaml index 3f4cab3b..681f0d7b 100644 --- a/openapi/components/schemas/errors/Error404.yaml +++ b/openapi/components/schemas/errors/Error404.yaml @@ -23,6 +23,11 @@ properties: | BULK_UPLOAD_JOB_NOT_FOUND | Bulk upload job not found | | REFERENCE_NOT_FOUND | Reference not found | | UMA_NOT_FOUND | The UMA address is well-formed but no receiver exists at the counterparty VASP | + | STABLECOIN_NOT_FOUND | Stablecoin not found | + | STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND | Stablecoin provider account link not found | + | STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND | Stablecoin external account not found | + | STABLECOIN_QUOTE_NOT_FOUND | Stablecoin quote not found | + | STABLECOIN_OPERATION_NOT_FOUND | Stablecoin operation not found | enum: - TRANSACTION_NOT_FOUND - INVITATION_NOT_FOUND @@ -33,6 +38,11 @@ properties: - BULK_UPLOAD_JOB_NOT_FOUND - REFERENCE_NOT_FOUND - UMA_NOT_FOUND + - STABLECOIN_NOT_FOUND + - STABLECOIN_PROVIDER_ACCOUNT_NOT_FOUND + - STABLECOIN_EXTERNAL_ACCOUNT_NOT_FOUND + - STABLECOIN_QUOTE_NOT_FOUND + - STABLECOIN_OPERATION_NOT_FOUND message: type: string description: Error message diff --git a/openapi/components/schemas/errors/Error409.yaml b/openapi/components/schemas/errors/Error409.yaml index 09db54cb..1800089e 100644 --- a/openapi/components/schemas/errors/Error409.yaml +++ b/openapi/components/schemas/errors/Error409.yaml @@ -19,12 +19,16 @@ properties: | EMAIL_OTP_EMAIL_ALREADY_EXISTS | Email address is already associated with an EMAIL_OTP credential | | EMAIL_OTP_CREDENTIAL_SET_CHANGED | Tied EMAIL_OTP credential set changed after the signed-retry challenge was issued | | CONFLICT | Generic resource-state conflict. Returned, for example, when `platformCustomerId` on a customer create call collides with an existing active customer on the same platform | + | STABLECOIN_SYMBOL_ALREADY_EXISTS | A stablecoin with the same symbol is already registered for this platform | + | STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS | A stablecoin with the same network token identifier is already registered | enum: - TRANSACTION_NOT_PENDING_PLATFORM_APPROVAL - UMA_ADDRESS_EXISTS - EMAIL_OTP_EMAIL_ALREADY_EXISTS - EMAIL_OTP_CREDENTIAL_SET_CHANGED - CONFLICT + - STABLECOIN_SYMBOL_ALREADY_EXISTS + - STABLECOIN_TOKEN_IDENTIFIER_ALREADY_EXISTS message: type: string description: Error message diff --git a/openapi/components/schemas/stablecoins/Stablecoin.yaml b/openapi/components/schemas/stablecoins/Stablecoin.yaml new file mode 100644 index 00000000..4a41e1f5 --- /dev/null +++ b/openapi/components/schemas/stablecoins/Stablecoin.yaml @@ -0,0 +1,74 @@ +type: object +required: +- id +- name +- symbol +- baseCurrency +- network +- decimals +- issuanceStatus +- gridOperationsStatus +- networkTokenIdentifier +- provider +- stablecoinProviderAccountId +- providerEnvironment +- providerTokenIdentifier +- createdAt +- updatedAt +properties: + id: + type: string + description: System-generated stablecoin identifier. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + name: + type: string + description: Stablecoin display name. + example: Acme Dollar + symbol: + type: string + description: Stablecoin symbol. + example: ACME + baseCurrency: + type: string + description: Fiat currency the stablecoin is denominated against. + example: USD + network: + $ref: StablecoinNetwork.yaml + decimals: + type: integer + description: Number of decimal places used by the stablecoin. + example: 6 + issuanceStatus: + $ref: StablecoinIssuanceStatus.yaml + gridOperationsStatus: + $ref: StablecoinGridOperationsStatus.yaml + networkTokenIdentifier: + type: string + description: Token identifier in the namespace selected by `network`. + example: btkn1qw508d6qejxtdg4y5r3zarvary0c5xw7k + currency: + type: string + description: Grid currency code after the stablecoin is enabled for Grid operations. + example: ACME + provider: + $ref: StablecoinProvider.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link selected for this stablecoin. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + providerEnvironment: + $ref: StablecoinProviderEnvironment.yaml + providerTokenIdentifier: + type: string + description: Provider token identifier. For Brale this maps to `value_type`. + example: ACME + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T16:40:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:10:00Z' diff --git a/openapi/components/schemas/stablecoins/StablecoinAchDebitMintFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinAchDebitMintFundingSource.yaml new file mode 100644 index 00000000..1c748e22 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinAchDebitMintFundingSource.yaml @@ -0,0 +1,14 @@ +type: object +required: +- type +- stablecoinExternalAccountId +properties: + type: + type: string + enum: + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + stablecoinExternalAccountId: + type: string + description: Linked provider external account to debit. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 diff --git a/openapi/components/schemas/stablecoins/StablecoinAmount.yaml b/openapi/components/schemas/stablecoins/StablecoinAmount.yaml new file mode 100644 index 00000000..e545924b --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinAmount.yaml @@ -0,0 +1,6 @@ +type: string +pattern: ^[1-9][0-9]*$ +description: Amount in the stablecoin's smallest unit, as a base-10 integer string (uint128 range). Strings + avoid JavaScript precision loss. Must convert exactly to a provider-representable fiat amount (whole + cents for USD). +example: '100000000' diff --git a/openapi/components/schemas/stablecoins/StablecoinBurnDestination.yaml b/openapi/components/schemas/stablecoins/StablecoinBurnDestination.yaml new file mode 100644 index 00000000..0268f081 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinBurnDestination.yaml @@ -0,0 +1,16 @@ +type: object +required: +- type +- stablecoinExternalAccountId +- rail +properties: + type: + type: string + enum: + - STABLECOIN_EXTERNAL_ACCOUNT + stablecoinExternalAccountId: + type: string + description: Linked stablecoin external account to receive the fiat redemption. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + rail: + $ref: StablecoinPayoutRail.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinBurnQuoteRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinBurnQuoteRequest.yaml new file mode 100644 index 00000000..4905afb3 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinBurnQuoteRequest.yaml @@ -0,0 +1,22 @@ +type: object +required: +- operationType +- amount +- source +- destination +properties: + operationType: + type: string + enum: + - BURN + amount: + $ref: StablecoinAmount.yaml + source: + $ref: StablecoinBurnSource.yaml + destination: + $ref: StablecoinBurnDestination.yaml + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Redeem ACME diff --git a/openapi/components/schemas/stablecoins/StablecoinBurnSource.yaml b/openapi/components/schemas/stablecoins/StablecoinBurnSource.yaml new file mode 100644 index 00000000..fb72d66f --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinBurnSource.yaml @@ -0,0 +1,13 @@ +type: object +required: +- type +- accountId +properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + accountId: + type: string + description: Grid-controlled internal account holding the stablecoin balance to redeem. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000006 diff --git a/openapi/components/schemas/stablecoins/StablecoinCryptoNetwork.yaml b/openapi/components/schemas/stablecoins/StablecoinCryptoNetwork.yaml new file mode 100644 index 00000000..c9e71903 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinCryptoNetwork.yaml @@ -0,0 +1,9 @@ +type: string +enum: +- ETHEREUM +- SOLANA +- BASE +- POLYGON +- SPARK +- TRON +description: Crypto network used by a provider token-balance funding source. diff --git a/openapi/components/schemas/stablecoins/StablecoinDirectEntryUsBankDetails.yaml b/openapi/components/schemas/stablecoins/StablecoinDirectEntryUsBankDetails.yaml new file mode 100644 index 00000000..4106ec6e --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinDirectEntryUsBankDetails.yaml @@ -0,0 +1,40 @@ +type: object +required: +- routingNumber +- accountNumber +- accountType +- accountHolderName +properties: + routingNumber: + type: string + writeOnly: true + description: US bank routing number. + example: '021000021' + accountNumber: + type: string + writeOnly: true + description: US bank account number. + example: '123456789' + accountType: + type: string + enum: + - CHECKING + - SAVINGS + description: US bank account type. + accountHolderName: + type: string + description: Bank account holder legal name. + example: Acme Inc + institutionName: + type: string + description: Bank/institution display name. + example: Example Bank + beneficiaryAddress: + allOf: + - $ref: ../common/Address.yaml + description: Beneficiary postal address. Required by some payout rails (especially WIRE) and when + `createGridExternalAccount` is true. + bankAddress: + allOf: + - $ref: ../common/Address.yaml + description: Bank branch postal address. Required by some payout rails (especially WIRE). diff --git a/openapi/components/schemas/stablecoins/StablecoinEstimatedDelivery.yaml b/openapi/components/schemas/stablecoins/StablecoinEstimatedDelivery.yaml new file mode 100644 index 00000000..34c96075 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinEstimatedDelivery.yaml @@ -0,0 +1,18 @@ +type: object +description: Sanitized fiat delivery estimate for a burn/redemption. +required: +- rail +- amount +- currency +properties: + rail: + $ref: StablecoinPayoutRail.yaml + amount: + type: string + pattern: ^[0-9]+$ + description: Estimated delivery amount as a base-10 integer string in the smallest unit of `currency`. + example: '100000000' + currency: + type: string + description: Currency of the estimated delivery. + example: USD diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccount.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccount.yaml new file mode 100644 index 00000000..87834d8a --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccount.yaml @@ -0,0 +1,58 @@ +type: object +required: +- id +- provider +- stablecoinProviderAccountId +- providerEnvironment +- accountType +- creationMethod +- status +- supportedTransferTypes +- createdAt +- updatedAt +properties: + id: + type: string + description: System-generated stablecoin external account identifier. + example: StablecoinExternalAccount:019542f5-b3e7-1d02-0000-000000000005 + provider: + $ref: StablecoinProvider.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link for this external account. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + providerEnvironment: + $ref: StablecoinProviderEnvironment.yaml + accountType: + $ref: StablecoinExternalAccountType.yaml + creationMethod: + $ref: StablecoinExternalAccountCreationMethod.yaml + status: + $ref: StablecoinExternalAccountStatus.yaml + gridExternalAccountId: + type: string + description: Linked normal Grid external account id, when one exists. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000004 + supportedTransferTypes: + type: array + items: + $ref: StablecoinTransferType.yaml + providerStatus: + type: string + description: Safe provider status summary. + example: active + lastVerifiedAt: + type: string + format: date-time + description: Timestamp of the last successful provider external-account verification. + example: '2026-05-20T17:25:00Z' + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:25:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:25:00Z' diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountCreationMethod.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountCreationMethod.yaml new file mode 100644 index 00000000..f06aa682 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountCreationMethod.yaml @@ -0,0 +1,6 @@ +type: string +enum: +- GRID_EXTERNAL_ACCOUNT +- PLAID +- DIRECT_BANK_ENTRY +description: How the stablecoin external account was linked. diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountDirectEntryRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountDirectEntryRequest.yaml new file mode 100644 index 00000000..30f8ad6f --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountDirectEntryRequest.yaml @@ -0,0 +1,33 @@ +type: object +required: +- creationMethod +- provider +- accountType +- requestedTransferTypes +- bankDetails +properties: + creationMethod: + type: string + enum: + - DIRECT_BANK_ENTRY + provider: + $ref: StablecoinProvider.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link that should own the linked external account. Optional + when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` + error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: StablecoinExternalAccountType.yaml + requestedTransferTypes: + type: array + items: + $ref: StablecoinTransferType.yaml + bankDetails: + $ref: StablecoinDirectEntryUsBankDetails.yaml + createGridExternalAccount: + type: boolean + description: Whether Grid should also create a normal Grid external account when the request contains + enough data. + example: true diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountGridLinkRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountGridLinkRequest.yaml new file mode 100644 index 00000000..e7359da5 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountGridLinkRequest.yaml @@ -0,0 +1,27 @@ +type: object +required: +- creationMethod +- provider +- gridExternalAccountId +- requestedTransferTypes +properties: + creationMethod: + type: string + enum: + - GRID_EXTERNAL_ACCOUNT + provider: + $ref: StablecoinProvider.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link that should own the linked external account. Optional + when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` + error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + gridExternalAccountId: + type: string + description: Existing Grid external account to link to the provider. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000004 + requestedTransferTypes: + type: array + items: + $ref: StablecoinTransferType.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkRequest.yaml new file mode 100644 index 00000000..98abca2a --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkRequest.yaml @@ -0,0 +1,10 @@ +oneOf: +- $ref: StablecoinExternalAccountGridLinkRequest.yaml +- $ref: StablecoinExternalAccountProviderLinkRequest.yaml +- $ref: StablecoinExternalAccountDirectEntryRequest.yaml +discriminator: + propertyName: creationMethod + mapping: + GRID_EXTERNAL_ACCOUNT: StablecoinExternalAccountGridLinkRequest.yaml + PLAID: StablecoinExternalAccountProviderLinkRequest.yaml + DIRECT_BANK_ENTRY: StablecoinExternalAccountDirectEntryRequest.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkSession.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkSession.yaml new file mode 100644 index 00000000..5b7b9fc4 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkSession.yaml @@ -0,0 +1,36 @@ +type: object +required: +- id +- provider +- stablecoinProviderAccountId +- accountType +- linkToken +- expiresAt +- createdAt +properties: + id: + type: string + description: System-generated stablecoin external-account link-session identifier. + example: StablecoinExternalAccountLinkSession:019542f5-b3e7-1d02-0000-000000000003 + provider: + $ref: StablecoinProvider.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link selected for this session. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: StablecoinExternalAccountType.yaml + linkToken: + type: string + description: Provider/Plaid frontend token for the link flow. + example: link-sandbox-123 + expiresAt: + type: string + format: date-time + description: Link token expiration timestamp. + example: '2026-05-20T18:20:00Z' + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:20:00Z' diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkSessionCreateRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkSessionCreateRequest.yaml new file mode 100644 index 00000000..41f66db6 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountLinkSessionCreateRequest.yaml @@ -0,0 +1,23 @@ +type: object +required: +- provider +- accountType +- requestedTransferTypes +- owner +properties: + provider: + $ref: StablecoinProvider.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link that should own the linked external account. Optional + when the platform has exactly one active provider account link; required (via a `STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED` + error) when the selection is ambiguous. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + accountType: + $ref: StablecoinExternalAccountType.yaml + requestedTransferTypes: + type: array + items: + $ref: StablecoinTransferType.yaml + owner: + $ref: StablecoinExternalAccountOwner.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountListResponse.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountListResponse.yaml new file mode 100644 index 00000000..bfe5c80e --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountListResponse.yaml @@ -0,0 +1,18 @@ +type: object +required: +- data +- hasMore +properties: + data: + type: array + items: + $ref: StablecoinExternalAccount.yaml + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results. + totalCount: + type: integer + description: Total number of stablecoin external accounts matching the criteria. diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountOwner.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountOwner.yaml new file mode 100644 index 00000000..386864cb --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountOwner.yaml @@ -0,0 +1,22 @@ +type: object +required: +- legalName +properties: + legalName: + type: string + description: Legal name of the account owner. + example: Acme Inc + emailAddress: + type: string + format: email + description: Email address for the account owner. + example: finance@example.com + phoneNumber: + type: string + description: Phone number for the account owner. + example: '+14155550100' + dateOfBirth: + type: string + format: date + description: Date of birth when required by the provider link flow. + example: '1990-01-01' diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountProviderLinkRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountProviderLinkRequest.yaml new file mode 100644 index 00000000..b52e57c2 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountProviderLinkRequest.yaml @@ -0,0 +1,27 @@ +type: object +required: +- creationMethod +- provider +- linkSessionId +- linkResultToken +- requestedTransferTypes +properties: + creationMethod: + type: string + enum: + - PLAID + provider: + $ref: StablecoinProvider.yaml + linkSessionId: + type: string + description: Stablecoin external-account link-session id. + example: StablecoinExternalAccountLinkSession:019542f5-b3e7-1d02-0000-000000000003 + linkResultToken: + type: string + writeOnly: true + description: Provider/Plaid public token returned by the frontend link flow. + example: public-sandbox-123 + requestedTransferTypes: + type: array + items: + $ref: StablecoinTransferType.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountStatus.yaml new file mode 100644 index 00000000..197ec470 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountStatus.yaml @@ -0,0 +1,8 @@ +type: string +enum: +- ACTIVE +- INACTIVE +- NEEDS_UPDATE +- FAILED +description: Status of a provider-linked stablecoin external account. NEEDS_UPDATE indicates the provider + link requires attention (for example Plaid reauthentication). diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountType.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountType.yaml new file mode 100644 index 00000000..f9f5b0b5 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountType.yaml @@ -0,0 +1,4 @@ +type: string +enum: +- US_BANK_ACCOUNT +description: External account type supported for stablecoin provider linking. diff --git a/openapi/components/schemas/stablecoins/StablecoinFee.yaml b/openapi/components/schemas/stablecoins/StablecoinFee.yaml new file mode 100644 index 00000000..5a3b0294 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinFee.yaml @@ -0,0 +1,19 @@ +type: object +required: +- type +- amount +- currency +properties: + type: + type: string + description: Fee type identifier (for example PROVIDER, GRID, RAIL, NETWORK). + example: PROVIDER + amount: + type: string + pattern: ^[0-9]+$ + description: Fee amount as a base-10 integer string in the smallest unit of `currency`. + example: '0' + currency: + type: string + description: Currency of the fee amount. + example: USD diff --git a/openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml b/openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml new file mode 100644 index 00000000..4f173aca --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml @@ -0,0 +1,9 @@ +type: object +description: Sanitized funding instructions for the selected funding rail. Shape varies by rail; contains + only intentionally public deposit coordinates. +required: +- rail +properties: + rail: + $ref: StablecoinTransferType.yaml +additionalProperties: true diff --git a/openapi/components/schemas/stablecoins/StablecoinGridOperationsStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinGridOperationsStatus.yaml new file mode 100644 index 00000000..454213f6 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinGridOperationsStatus.yaml @@ -0,0 +1,8 @@ +type: string +enum: +- NOT_ENABLED +- PENDING_APPROVAL +- ENABLING +- ENABLED +- DISABLED +description: Whether the stablecoin has been enabled for normal Grid operations. diff --git a/openapi/components/schemas/stablecoins/StablecoinIssuanceStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinIssuanceStatus.yaml new file mode 100644 index 00000000..4368473c --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinIssuanceStatus.yaml @@ -0,0 +1,8 @@ +type: string +enum: +- PENDING_REVIEW +- PROVISIONING +- PROVISIONED +- REJECTED +- FAILED +description: Provider issuance/linking status for the registered stablecoin. diff --git a/openapi/components/schemas/stablecoins/StablecoinListResponse.yaml b/openapi/components/schemas/stablecoins/StablecoinListResponse.yaml new file mode 100644 index 00000000..954684cd --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinListResponse.yaml @@ -0,0 +1,18 @@ +type: object +required: +- data +- hasMore +properties: + data: + type: array + items: + $ref: Stablecoin.yaml + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results. + totalCount: + type: integer + description: Total number of stablecoins matching the criteria. diff --git a/openapi/components/schemas/stablecoins/StablecoinMintDestination.yaml b/openapi/components/schemas/stablecoins/StablecoinMintDestination.yaml new file mode 100644 index 00000000..741f03d5 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinMintDestination.yaml @@ -0,0 +1,13 @@ +type: object +required: +- type +- sparkAddress +properties: + type: + type: string + enum: + - SPARK_ADDRESS + sparkAddress: + type: string + description: Destination Spark address that should receive the minted stablecoin. + example: sp1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq diff --git a/openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml new file mode 100644 index 00000000..a5549fd6 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml @@ -0,0 +1,11 @@ +oneOf: +- $ref: StablecoinWireMintFundingSource.yaml +- $ref: StablecoinAchDebitMintFundingSource.yaml +- $ref: StablecoinProviderTokenBalanceMintFundingSource.yaml +discriminator: + propertyName: type + mapping: + WIRE: StablecoinWireMintFundingSource.yaml + ACH_DEBIT: StablecoinAchDebitMintFundingSource.yaml + SAME_DAY_ACH_DEBIT: StablecoinAchDebitMintFundingSource.yaml + PROVIDER_TOKEN_BALANCE: StablecoinProviderTokenBalanceMintFundingSource.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinMintQuoteRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinMintQuoteRequest.yaml new file mode 100644 index 00000000..31d6aab4 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinMintQuoteRequest.yaml @@ -0,0 +1,22 @@ +type: object +required: +- operationType +- amount +- fundingSource +- destination +properties: + operationType: + type: string + enum: + - MINT + amount: + $ref: StablecoinAmount.yaml + fundingSource: + $ref: StablecoinMintFundingSource.yaml + destination: + $ref: StablecoinMintDestination.yaml + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Initial mint diff --git a/openapi/components/schemas/stablecoins/StablecoinNetwork.yaml b/openapi/components/schemas/stablecoins/StablecoinNetwork.yaml new file mode 100644 index 00000000..1cd6a6c4 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinNetwork.yaml @@ -0,0 +1,4 @@ +type: string +enum: +- SPARK_MAINNET +description: Network namespace for the stablecoin token identifier. diff --git a/openapi/components/schemas/stablecoins/StablecoinOperation.yaml b/openapi/components/schemas/stablecoins/StablecoinOperation.yaml new file mode 100644 index 00000000..e34211f5 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperation.yaml @@ -0,0 +1,87 @@ +type: object +required: +- id +- stablecoinId +- operationType +- status +- amount +- provider +- providerEnvironment +- stablecoinProviderAccountId +- createdAt +- updatedAt +properties: + id: + type: string + description: System-generated stablecoin operation identifier. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000007 + stablecoinId: + type: string + description: Stablecoin this operation belongs to. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + operationType: + $ref: StablecoinOperationType.yaml + status: + $ref: StablecoinOperationStatus.yaml + amount: + $ref: StablecoinAmount.yaml + quoteId: + type: string + description: Quote that produced this operation. + example: StablecoinQuote:019542f5-b3e7-1d02-0000-000000000008 + provider: + $ref: StablecoinProvider.yaml + providerEnvironment: + $ref: StablecoinProviderEnvironment.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link used by this operation. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + fundingSource: + $ref: StablecoinMintFundingSource.yaml + fundingInstructions: + $ref: StablecoinFundingInstructions.yaml + source: + $ref: StablecoinBurnSource.yaml + destination: + description: Stablecoin operation destination. For mints this is a Spark address; for burns this is + a linked stablecoin external account. + oneOf: + - $ref: StablecoinMintDestination.yaml + - $ref: StablecoinBurnDestination.yaml + discriminator: + propertyName: type + mapping: + SPARK_ADDRESS: StablecoinMintDestination.yaml + STABLECOIN_EXTERNAL_ACCOUNT: StablecoinBurnDestination.yaml + estimatedDelivery: + $ref: StablecoinEstimatedDelivery.yaml + expiresAt: + type: string + format: date-time + description: Expiry for operations that wait on external funding (wire-funded mints). Past-due unfunded + operations transition to EXPIRED. + example: '2026-06-19T17:20:00Z' + providerStatus: + type: string + description: Safe provider status summary. + example: processing + failureReason: + type: string + description: Safe failure reason, when the operation failed. + example: provider_rejected + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description copied from the executed quote. + example: Initial mint + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:30:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:35:00Z' diff --git a/openapi/components/schemas/stablecoins/StablecoinOperationListResponse.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationListResponse.yaml new file mode 100644 index 00000000..c9a4cf91 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperationListResponse.yaml @@ -0,0 +1,18 @@ +type: object +required: +- data +- hasMore +properties: + data: + type: array + items: + $ref: StablecoinOperation.yaml + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results. + totalCount: + type: integer + description: Total number of stablecoin operations matching the criteria. diff --git a/openapi/components/schemas/stablecoins/StablecoinOperationStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationStatus.yaml new file mode 100644 index 00000000..239c1b30 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperationStatus.yaml @@ -0,0 +1,11 @@ +type: string +enum: +- CREATED +- PENDING +- PROCESSING +- COMPLETED +- FAILED +- EXPIRED +description: Current status of the stablecoin operation. EXPIRED applies to wire-funded mints that were + never funded within the expiry window. Provider-canceled states map to FAILED with a stable failure + reason. diff --git a/openapi/components/schemas/stablecoins/StablecoinOperationType.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationType.yaml new file mode 100644 index 00000000..cd4366c8 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperationType.yaml @@ -0,0 +1,5 @@ +type: string +enum: +- MINT +- BURN +description: Stablecoin issuer operation type. diff --git a/openapi/components/schemas/stablecoins/StablecoinPayoutRail.yaml b/openapi/components/schemas/stablecoins/StablecoinPayoutRail.yaml new file mode 100644 index 00000000..df571c70 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinPayoutRail.yaml @@ -0,0 +1,8 @@ +type: string +enum: +- WIRE +- ACH_CREDIT +- SAME_DAY_ACH_CREDIT +- RTP_CREDIT +description: Fiat payout rail for a burn/redemption. Debit rails are funding-only and are not valid payout + rails. diff --git a/openapi/components/schemas/stablecoins/StablecoinProvider.yaml b/openapi/components/schemas/stablecoins/StablecoinProvider.yaml new file mode 100644 index 00000000..6bf25756 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProvider.yaml @@ -0,0 +1,4 @@ +type: string +enum: +- BRALE +description: Stablecoin provider backing the linked account, stablecoin, or operation. diff --git a/openapi/components/schemas/stablecoins/StablecoinProviderAccount.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderAccount.yaml new file mode 100644 index 00000000..2a6dda6e --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderAccount.yaml @@ -0,0 +1,39 @@ +type: object +required: +- id +- provider +- providerAccountId +- providerEnvironment +- status +- createdAt +- updatedAt +properties: + id: + type: string + description: System-generated stablecoin provider account link identifier. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + provider: + $ref: StablecoinProvider.yaml + providerAccountId: + type: string + description: Provider account id. + example: 2VcUIonJeVQzFoBuC7LdFT0dRe4 + providerEnvironment: + $ref: StablecoinProviderEnvironment.yaml + status: + $ref: StablecoinProviderAccountStatus.yaml + lastVerifiedAt: + type: string + format: date-time + description: Timestamp of the last successful provider credential verification. + example: '2026-05-20T16:35:00Z' + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T16:35:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T16:35:00Z' diff --git a/openapi/components/schemas/stablecoins/StablecoinProviderAccountLinkRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderAccountLinkRequest.yaml new file mode 100644 index 00000000..7171ddc4 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderAccountLinkRequest.yaml @@ -0,0 +1,23 @@ +type: object +required: +- provider +- apiClientId +- apiClientSecret +properties: + provider: + $ref: StablecoinProvider.yaml + apiClientId: + type: string + description: Provider API client id used to verify and link the provider account. + example: provider_client_123 + apiClientSecret: + type: string + writeOnly: true + description: Provider API client secret. Grid verifies and stores this secret encrypted; it is never + returned. + example: provider_secret_456 + providerAccountId: + type: string + description: Provider account id. Optional when the submitted credentials expose exactly one provider + account. + example: 2VcUIonJeVQzFoBuC7LdFT0dRe4 diff --git a/openapi/components/schemas/stablecoins/StablecoinProviderAccountListResponse.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderAccountListResponse.yaml new file mode 100644 index 00000000..e565d473 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderAccountListResponse.yaml @@ -0,0 +1,18 @@ +type: object +required: +- data +- hasMore +properties: + data: + type: array + items: + $ref: StablecoinProviderAccount.yaml + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results. + totalCount: + type: integer + description: Total number of stablecoin provider account links matching the criteria. diff --git a/openapi/components/schemas/stablecoins/StablecoinProviderAccountStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderAccountStatus.yaml new file mode 100644 index 00000000..88f6fe64 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderAccountStatus.yaml @@ -0,0 +1,6 @@ +type: string +enum: +- ACTIVE +- INVALID +- REVOKED +description: Status of the linked stablecoin provider account credentials. diff --git a/openapi/components/schemas/stablecoins/StablecoinProviderEnvironment.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderEnvironment.yaml new file mode 100644 index 00000000..a4683267 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderEnvironment.yaml @@ -0,0 +1,5 @@ +type: string +enum: +- SANDBOX +- PRODUCTION +description: Provider environment derived from the authenticated Grid platform mode. diff --git a/openapi/components/schemas/stablecoins/StablecoinProviderTokenBalanceMintFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderTokenBalanceMintFundingSource.yaml new file mode 100644 index 00000000..2407579c --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderTokenBalanceMintFundingSource.yaml @@ -0,0 +1,16 @@ +type: object +required: +- type +- sourceTokenIdentifier +- cryptoNetwork +properties: + type: + type: string + enum: + - PROVIDER_TOKEN_BALANCE + sourceTokenIdentifier: + type: string + description: Provider token/value identifier to fund the mint from. + example: USDC + cryptoNetwork: + $ref: StablecoinCryptoNetwork.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinQuote.yaml b/openapi/components/schemas/stablecoins/StablecoinQuote.yaml new file mode 100644 index 00000000..a559b212 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinQuote.yaml @@ -0,0 +1,73 @@ +type: object +required: +- id +- stablecoinId +- operationType +- status +- amount +- expiresAt +- fees +- createdAt +properties: + id: + type: string + description: System-generated stablecoin quote identifier. + example: StablecoinQuote:019542f5-b3e7-1d02-0000-000000000008 + stablecoinId: + type: string + description: Stablecoin this quote belongs to. + example: Stablecoin:019542f5-b3e7-1d02-0000-000000000002 + operationType: + $ref: StablecoinOperationType.yaml + status: + $ref: StablecoinQuoteStatus.yaml + amount: + $ref: StablecoinAmount.yaml + expiresAt: + type: string + format: date-time + description: Quote expiration time. Execution rejects expired quotes. + example: '2026-05-20T17:25:00Z' + fees: + type: array + items: + $ref: StablecoinFee.yaml + description: Previewed provider, Grid, rail, or network fees. + fundingSource: + $ref: StablecoinMintFundingSource.yaml + destination: + description: Quoted destination. For mints this is a Spark address destination; for burns this is + a linked stablecoin external account destination. + oneOf: + - $ref: StablecoinMintDestination.yaml + - $ref: StablecoinBurnDestination.yaml + discriminator: + propertyName: type + mapping: + SPARK_ADDRESS: StablecoinMintDestination.yaml + STABLECOIN_EXTERNAL_ACCOUNT: StablecoinBurnDestination.yaml + source: + $ref: StablecoinBurnSource.yaml + fundingInstructions: + $ref: StablecoinFundingInstructions.yaml + estimatedDelivery: + $ref: StablecoinEstimatedDelivery.yaml + operationId: + type: string + description: Operation created by executing this quote, when the quote has been executed. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000007 + description: + type: string + maxLength: 1024 + description: Optional platform-supplied description carried through to the executed operation. + example: Initial mint + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2026-05-20T17:20:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2026-05-20T17:25:00Z' diff --git a/openapi/components/schemas/stablecoins/StablecoinQuoteRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinQuoteRequest.yaml new file mode 100644 index 00000000..b1e03e92 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinQuoteRequest.yaml @@ -0,0 +1,8 @@ +oneOf: +- $ref: StablecoinMintQuoteRequest.yaml +- $ref: StablecoinBurnQuoteRequest.yaml +discriminator: + propertyName: operationType + mapping: + MINT: StablecoinMintQuoteRequest.yaml + BURN: StablecoinBurnQuoteRequest.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinQuoteStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinQuoteStatus.yaml new file mode 100644 index 00000000..3a0514b8 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinQuoteStatus.yaml @@ -0,0 +1,7 @@ +type: string +enum: +- OPEN +- EXECUTED +- EXPIRED +- FAILED +description: Current status of the stablecoin quote. diff --git a/openapi/components/schemas/stablecoins/StablecoinRegisterRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinRegisterRequest.yaml new file mode 100644 index 00000000..191b0a71 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinRegisterRequest.yaml @@ -0,0 +1,22 @@ +type: object +required: +- providerTokenIdentifier +- networkTokenIdentifier +- network +properties: + providerTokenIdentifier: + type: string + description: Provider identifier for the stablecoin. For Brale this maps to `value_type`. + example: ACME + networkTokenIdentifier: + type: string + description: Token identifier in the namespace selected by `network`. + example: btkn1qw508d6qejxtdg4y5r3zarvary0c5xw7k + network: + $ref: StablecoinNetwork.yaml + stablecoinProviderAccountId: + type: string + description: Provider account link to register against. Optional when exactly one active link exists + for the authenticated platform; required to resolve STABLECOIN_PROVIDER_ACCOUNT_SELECTION_REQUIRED + when multiple links exist. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 diff --git a/openapi/components/schemas/stablecoins/StablecoinTransferType.yaml b/openapi/components/schemas/stablecoins/StablecoinTransferType.yaml new file mode 100644 index 00000000..4b8c8122 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinTransferType.yaml @@ -0,0 +1,9 @@ +type: string +enum: +- WIRE +- ACH_DEBIT +- SAME_DAY_ACH_DEBIT +- ACH_CREDIT +- SAME_DAY_ACH_CREDIT +- RTP_CREDIT +description: Provider-supported transfer type for stablecoin funding or redemption. diff --git a/openapi/components/schemas/stablecoins/StablecoinWireMintFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinWireMintFundingSource.yaml new file mode 100644 index 00000000..0999fec8 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinWireMintFundingSource.yaml @@ -0,0 +1,8 @@ +type: object +required: +- type +properties: + type: + type: string + enum: + - WIRE diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 7c509543..0e6c8bc2 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -77,6 +77,9 @@ tags: Card management endpoints. Issue debit cards against an internal account, freeze / unfreeze, close, manage card funding sources, and list card transactions. + - name: Stablecoins + description: >- + Stablecoin issuance endpoints. Register provider-created stablecoins, link provider accounts and external bank accounts, create mint/burn quotes, execute them, and track the resulting operations. servers: - url: https://api.lightspark.com/grid/2025-10-13 description: Production server @@ -280,6 +283,30 @@ paths: $ref: paths/sandbox/cards/sandbox_cards_{id}_simulate_clearing.yaml /sandbox/cards/{id}/simulate/return: $ref: paths/sandbox/cards/sandbox_cards_{id}_simulate_return.yaml + /stablecoin-provider-accounts: + $ref: paths/stablecoins/stablecoin-provider-accounts.yaml + /stablecoin-provider-accounts/{stablecoinProviderAccountId}: + $ref: paths/stablecoins/stablecoin-provider-accounts_{stablecoinProviderAccountId}.yaml + /stablecoins: + $ref: paths/stablecoins/stablecoins.yaml + /stablecoins/{stablecoinId}: + $ref: paths/stablecoins/stablecoins_{stablecoinId}.yaml + /stablecoin-external-account-link-sessions: + $ref: paths/stablecoins/stablecoin-external-account-link-sessions.yaml + /stablecoin-external-accounts: + $ref: paths/stablecoins/stablecoin-external-accounts.yaml + /stablecoin-external-accounts/{stablecoinExternalAccountId}: + $ref: paths/stablecoins/stablecoin-external-accounts_{stablecoinExternalAccountId}.yaml + /stablecoins/{stablecoinId}/quotes: + $ref: paths/stablecoins/stablecoins_{stablecoinId}_quotes.yaml + /stablecoins/{stablecoinId}/quotes/{stablecoinQuoteId}: + $ref: paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}.yaml + /stablecoins/{stablecoinId}/quotes/{stablecoinQuoteId}/execute: + $ref: paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}_execute.yaml + /stablecoins/{stablecoinId}/operations: + $ref: paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml + /stablecoin-operations/{stablecoinOperationId}: + $ref: paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml webhooks: agent-action: $ref: webhooks/agent-action.yaml diff --git a/openapi/paths/stablecoins/stablecoin-external-account-link-sessions.yaml b/openapi/paths/stablecoins/stablecoin-external-account-link-sessions.yaml new file mode 100644 index 00000000..4e0b2b33 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoin-external-account-link-sessions.yaml @@ -0,0 +1,54 @@ +post: + summary: Create a stablecoin external-account link session + description: Create a provider/Plaid link session for linking a bank account to the stablecoin provider. + operationId: createStablecoinExternalAccountLinkSession + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting + payloads are rejected. + required: true + schema: + type: string + maxLength: 255 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinExternalAccountLinkSessionCreateRequest.yaml + responses: + '201': + description: Link session created + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinExternalAccountLinkSession.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '409': + description: Conflict + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoin-external-accounts.yaml b/openapi/paths/stablecoins/stablecoin-external-accounts.yaml new file mode 100644 index 00000000..e7a762b9 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoin-external-accounts.yaml @@ -0,0 +1,124 @@ +post: + summary: Link a stablecoin external account + description: | + Link a Grid external account, provider/Plaid link result, or direct-entry bank account to the stablecoin provider. The returned resource stores provider address metadata used for stablecoin mints and burns. + operationId: linkStablecoinExternalAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting + payloads are rejected. + required: true + schema: + type: string + maxLength: 255 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinExternalAccountLinkRequest.yaml + responses: + '201': + description: Stablecoin external account linked + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinExternalAccount.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: External account or link session not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml +get: + summary: List stablecoin external accounts + operationId: listStablecoinExternalAccounts + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: provider + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProvider.yaml + - name: status + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinExternalAccountStatus.yaml + - name: gridExternalAccountId + in: query + required: false + schema: + type: string + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinExternalAccountListResponse.yaml + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoin-external-accounts_{stablecoinExternalAccountId}.yaml b/openapi/paths/stablecoins/stablecoin-external-accounts_{stablecoinExternalAccountId}.yaml new file mode 100644 index 00000000..7c3d7380 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoin-external-accounts_{stablecoinExternalAccountId}.yaml @@ -0,0 +1,39 @@ +parameters: +- name: stablecoinExternalAccountId + in: path + description: System-generated stablecoin external account identifier + required: true + schema: + type: string +get: + summary: Get a stablecoin external account + operationId: getStablecoinExternalAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinExternalAccount.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin external account not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml b/openapi/paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml new file mode 100644 index 00000000..cbb866c5 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml @@ -0,0 +1,39 @@ +parameters: +- name: stablecoinOperationId + in: path + description: System-generated stablecoin operation identifier + required: true + schema: + type: string +get: + summary: Get a stablecoin operation + operationId: getStablecoinOperation + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinOperation.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin operation not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoin-provider-accounts.yaml b/openapi/paths/stablecoins/stablecoin-provider-accounts.yaml new file mode 100644 index 00000000..f796c463 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoin-provider-accounts.yaml @@ -0,0 +1,114 @@ +post: + summary: Link a stablecoin provider account + description: | + Link provider API credentials for the authenticated platform. Provider credentials are account-scoped and can be reused for multiple stablecoins. In V1 the only supported provider is `BRALE`; the provider environment is derived from the authenticated Grid platform mode. + operationId: linkStablecoinProviderAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting + payloads are rejected. + required: true + schema: + type: string + maxLength: 255 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProviderAccountLinkRequest.yaml + responses: + '201': + description: Stablecoin provider account linked + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProviderAccount.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '409': + description: Conflict + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml +get: + summary: List stablecoin provider account links + description: Retrieve stablecoin provider account links for the authenticated platform. + operationId: listStablecoinProviderAccounts + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: provider + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProvider.yaml + - name: status + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProviderAccountStatus.yaml + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProviderAccountListResponse.yaml + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoin-provider-accounts_{stablecoinProviderAccountId}.yaml b/openapi/paths/stablecoins/stablecoin-provider-accounts_{stablecoinProviderAccountId}.yaml new file mode 100644 index 00000000..18223ef3 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoin-provider-accounts_{stablecoinProviderAccountId}.yaml @@ -0,0 +1,39 @@ +parameters: +- name: stablecoinProviderAccountId + in: path + description: System-generated stablecoin provider account link identifier + required: true + schema: + type: string +get: + summary: Get a stablecoin provider account link + operationId: getStablecoinProviderAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProviderAccount.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin provider account link not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoins.yaml b/openapi/paths/stablecoins/stablecoins.yaml new file mode 100644 index 00000000..ae4baf9f --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins.yaml @@ -0,0 +1,125 @@ +post: + summary: Register an existing provider-created stablecoin + description: | + Register an existing provider-created stablecoin as a Grid `Stablecoin`. This endpoint links provider token metadata to Grid; it does not create the token with the provider. Grid derives the active provider account link from the authenticated platform, provider, and provider environment. + operationId: registerStablecoin + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting + payloads are rejected. + required: true + schema: + type: string + maxLength: 255 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinRegisterRequest.yaml + responses: + '201': + description: Stablecoin registered + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/Stablecoin.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Referenced stablecoin provider account not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml +get: + summary: List stablecoins + description: Retrieve stablecoins registered to the authenticated platform. + operationId: listStablecoins + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: issuanceStatus + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinIssuanceStatus.yaml + - name: gridOperationsStatus + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinGridOperationsStatus.yaml + - name: provider + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinProvider.yaml + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinListResponse.yaml + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoins_{stablecoinId}.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}.yaml new file mode 100644 index 00000000..2e5b736e --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}.yaml @@ -0,0 +1,39 @@ +parameters: +- name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +get: + summary: Get a stablecoin + operationId: getStablecoin + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/Stablecoin.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml new file mode 100644 index 00000000..8f5b48d6 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml @@ -0,0 +1,71 @@ +parameters: +- name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +get: + summary: List stablecoin operations + operationId: listStablecoinOperations + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: type + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinOperationType.yaml + - name: status + in: query + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinOperationStatus.yaml + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinOperationListResponse.yaml + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes.yaml new file mode 100644 index 00000000..2fc7870b --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes.yaml @@ -0,0 +1,68 @@ +parameters: +- name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +post: + summary: Create a stablecoin quote + description: | + Create a MINT or BURN quote for this stablecoin. A quote is a validation preview only: it locks no exchange rate, reserves no fee, and holds no balance. Execution re-validates everything; for burns, the balance hold happens at execution time. Execute the quote with `executeStablecoinQuote` before it expires. + operationId: createStablecoinQuote + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key scoped to this quote request. Replays return the prior quote; conflicting + payloads are rejected. + required: true + schema: + type: string + maxLength: 255 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinQuoteRequest.yaml + responses: + '201': + description: Quote created + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinQuote.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin or linked account not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}.yaml new file mode 100644 index 00000000..61fbe226 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}.yaml @@ -0,0 +1,45 @@ +parameters: +- name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +- name: stablecoinQuoteId + in: path + description: System-generated stablecoin quote identifier + required: true + schema: + type: string +get: + summary: Get a stablecoin quote + operationId: getStablecoinQuote + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinQuote.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin or quote not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}_execute.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}_execute.yaml new file mode 100644 index 00000000..aace914f --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_quotes_{stablecoinQuoteId}_execute.yaml @@ -0,0 +1,68 @@ +parameters: +- name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +- name: stablecoinQuoteId + in: path + description: System-generated stablecoin quote identifier + required: true + schema: + type: string +post: + summary: Execute a stablecoin quote + description: | + Execute an open, unexpired quote, creating the StablecoinOperation and the first provider side effect. Execution re-validates the quoted inputs (stablecoin state, credential status, external-account capability, and for burns the source balance). Expired or already-executed quotes are rejected; create a new quote instead. + operationId: executeStablecoinQuote + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Idempotency key scoped to creating the operation and provider side effects. Replays against + the same quote return the prior operation; replays against a different quote are rejected. + required: true + schema: + type: string + maxLength: 255 + responses: + '201': + description: Operation created + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinOperation.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Stablecoin or quote not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml