diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 476be1e8d..c591121db 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -58,7 +58,7 @@ tags: - 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. Link provider accounts, register provider-created stablecoins, create mint/burn quotes, execute them, and track the resulting operations. + description: Stablecoin issuance endpoints. Link provider accounts, register provider-created stablecoins, create direct mint/burn issuer operations, and track operation status. paths: /config: get: @@ -7481,12 +7481,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /stablecoin-provider-accounts: + /stablecoins: post: - summary: Link a stablecoin provider account + summary: Register an existing provider-created stablecoin description: | - Link provider API credentials for the authenticated platform. Provider credentials are account-scoped and can be reused for multiple stablecoins. Currently, the only supported provider is `BRALE`; the provider environment is derived from the authenticated Grid platform mode. - operationId: linkStablecoinProviderAccount + 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: @@ -7494,7 +7494,7 @@ paths: parameters: - name: Idempotency-Key in: header - description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + description: Required idempotency key for retrying this request safely. required: true schema: type: string @@ -7504,14 +7504,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccountLinkRequest' + $ref: '#/components/schemas/StablecoinRegisterRequest' responses: '201': - description: Stablecoin provider account linked + description: Stablecoin registered content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccount' + $ref: '#/components/schemas/Stablecoin' '400': description: Bad request content: @@ -7524,6 +7524,12 @@ paths: 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 content: @@ -7537,24 +7543,29 @@ paths: schema: $ref: '#/components/schemas/Error500' get: - summary: List stablecoin provider account links - description: Retrieve stablecoin provider account links for the authenticated platform. - operationId: listStablecoinProviderAccounts + summary: List stablecoins + description: Retrieve stablecoins registered to the authenticated platform. + operationId: listStablecoins tags: - Stablecoins security: - BasicAuth: [] parameters: - - name: provider + - name: issuanceStatus in: query required: false schema: - $ref: '#/components/schemas/StablecoinProvider' - - name: status + $ref: '#/components/schemas/StablecoinIssuanceStatus' + - name: gridOperationsStatus in: query required: false schema: - $ref: '#/components/schemas/StablecoinProviderAccountStatus' + $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) @@ -7566,7 +7577,7 @@ paths: default: 20 - name: cursor in: query - description: Cursor for pagination (returned from previous request) + description: Opaque cursor returned as `nextCursor` from the previous response. required: false schema: type: string @@ -7576,7 +7587,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccountListResponse' + $ref: '#/components/schemas/StablecoinListResponse' '400': description: Bad request - Invalid parameters content: @@ -7595,18 +7606,18 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /stablecoin-provider-accounts/{stablecoinProviderAccountId}: + /stablecoins/{stablecoinId}: parameters: - - name: stablecoinProviderAccountId + - name: stablecoinId in: path - description: System-generated stablecoin provider account link identifier + description: System-generated stablecoin identifier required: true schema: type: string get: - summary: Get a stablecoin provider account link - description: Retrieve a stablecoin provider account link by id for the authenticated platform. - operationId: getStablecoinProviderAccount + summary: Get a stablecoin + description: Retrieve a single registered stablecoin by its Grid identifier. + operationId: getStablecoin tags: - Stablecoins security: @@ -7617,7 +7628,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccount' + $ref: '#/components/schemas/Stablecoin' '401': description: Unauthorized content: @@ -7625,7 +7636,7 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Stablecoin provider account link not found + description: Stablecoin not found content: application/json: schema: @@ -7636,247 +7647,118 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' -webhooks: - agent-action: + /stablecoins/{stablecoinId}/mints: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string post: - summary: Agent action pending approval webhook + summary: Create a stablecoin mint operation 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 + Create a provider-backed mint operation for a registered stablecoin. Funding and destination accounts are normal Grid `ExternalAccount` objects; any provider-specific Brale address linkage is managed internally by Grid. Wire-funded mints return funding instructions and remain pending until the provider reports funds received. + operationId: createStablecoinMint tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Required idempotency key for retrying this mint request safely. + 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/StablecoinMintRequest' responses: - '200': - description: Webhook received and acknowledged. + '201': + description: Mint operation created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperation' + '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' + '404': + description: Stablecoin or referenced 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' - incoming-payment: + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + '503': + description: Provider temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error503' + /stablecoins/{stablecoinId}/burns: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string post: - summary: Incoming payment webhook and approval mechanism + summary: Create a stablecoin burn operation 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 + Create a provider-backed burn/redemption operation for a registered stablecoin. Burn sources and fiat destinations are normal Grid account objects; provider-specific Brale address ids are resolved and stored internally. External Spark wallet sources return funding instructions and remain pending until the provider reports funds received. + operationId: createStablecoinBurn tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Required idempotency key for retrying this burn request safely. + required: true + schema: + type: string + maxLength: 255 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 - direction: CREDIT - 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 - direction: CREDIT - 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 - incomingCompletedCryptoPayment: - summary: Completed payment funded from an external crypto wallet - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000009 - type: INCOMING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000006 - status: COMPLETED - type: INCOMING - direction: CREDIT - source: - sourceType: REALTIME_FUNDING - currency: USDC - onChainTransaction: - transactionHash: 7RJWhvQBQPEjJmki5fhBboGBWRJhmcFkMvrr4Fu3tMSJ5EdynMEiYSyiWAH9GpcbHpeUzeSQF9ZY6q4x8AhBskUf - network: SOLANA - destination: - destinationType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - receivedAmount: - amount: 100000 - currency: - code: USDC - name: USD Coin - symbol: '' - decimals: 6 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: USDC deposit from self-custody wallet + $ref: '#/components/schemas/StablecoinBurnRequest' 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. + '201': + description: Burn operation created 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/StablecoinOperation' '400': description: Bad request content: @@ -7884,332 +7766,170 @@ webhooks: 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. + '404': + description: Stablecoin or referenced account not found content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookForbiddenResponse' + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - '422': - description: | - Unprocessable Entity - Additional counterparty information required. - Only applicable for PENDING transactions. + '500': + description: Internal service error 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 + $ref: '#/components/schemas/Error500' + '503': + description: Provider temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error503' + /stablecoins/{stablecoinId}/operations: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + get: + summary: List stablecoin issuer operations + description: List issuer mint and burn operations for a stablecoin, most recent first, with cursor pagination. + operationId: listStablecoinOperations tags: - - Webhooks + - Stablecoins 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 - direction: DEBIT - 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 - outgoingCompletedCryptoPayment: - summary: Completed crypto payout to an external wallet - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: OUTGOING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000009 - status: COMPLETED - type: OUTGOING - direction: DEBIT - source: - sourceType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:c34dcbd6-dced-4ec4-b756-3c3a9ea3d789 - onChainTransaction: - transactionHash: h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx - network: SOLANA - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - sentAmount: - amount: 100000 - currency: - code: USDC - name: USD Coin - symbol: '' - decimals: 6 - receivedAmount: - amount: 100000 - currency: - code: USDC - name: USD Coin - symbol: '' - decimals: 6 - quoteId: Quote:019542f5-b3e7-1d02-0000-000000000010 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: USDC withdrawal to self-custody wallet - paymentInstructions: [] - 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 - direction: DEBIT - 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 + - BasicAuth: [] + parameters: + - name: operationType + in: query + description: Filter operations by type. When omitted, both mints and burns are returned. + required: false + schema: + $ref: '#/components/schemas/StablecoinOperationType' + - 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: Opaque cursor returned as `nextCursor` from the previous response. + required: false + schema: + type: string responses: '200': - description: Webhook received successfully - '400': - description: Bad request + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error400' + $ref: '#/components/schemas/StablecoinOperationListResponse' '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' - 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 + $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 issuer operation identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin issuer operation + description: Retrieve a single stablecoin issuer operation by its Grid identifier. + operationId: getStablecoinOperation 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: [] responses: '200': - description: Webhook received successfully. This confirms your webhook endpoint is properly configured. - '400': - description: Bad request + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error400' + $ref: '#/components/schemas/StablecoinOperation' '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 operation not found content: application/json: schema: - $ref: '#/components/schemas/Error409' - bulk-upload: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-provider-accounts: post: - summary: Bulk upload status webhook + summary: Link a stablecoin provider account 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 + Link provider API credentials for the authenticated platform. Provider credentials are account-scoped and can be reused for multiple stablecoins. Currently, 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/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 + $ref: '#/components/schemas/StablecoinProviderAccountLinkRequest' responses: - '200': - description: Webhook received successfully + '201': + description: Stablecoin provider account linked + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinProviderAccount' '400': description: Bad request content: @@ -8217,108 +7937,143 @@ 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' - 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 + '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/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 + - 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 + description: Successful operation + content: + application/json: + schema: + $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' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '500': + description: Internal service error 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. + $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 + description: Retrieve a stablecoin provider account link by id for the authenticated platform. + operationId: getStablecoinProviderAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinProviderAccount' + '401': + description: Unauthorized + content: + application/json: + schema: + $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' +webhooks: + agent-action: + post: + summary: Agent action pending approval webhook + 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 API public key provided to you during integration + 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: customerStatusWebhook + + 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: @@ -8328,127 +8083,52 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/CustomerWebhook' + $ref: '#/components/schemas/AgentActionWebhook' 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 + pendingApproval: + summary: Agent action pending approval value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000010 - type: CUSTOMER.KYB_REJECTED - timestamp: '2025-08-15T14:32:00Z' + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: AGENT_ACTION.PENDING_APPROVAL + timestamp: '2025-10-03T15:00: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 + 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 successfully - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' + description: Webhook received and acknowledged. '401': description: Unauthorized - Signature validation failed content: @@ -8461,11 +8141,11 @@ webhooks: application/json: schema: $ref: '#/components/schemas/Error409' - internal-account-status: + incoming-payment: post: - summary: Internal account status webhook + summary: Incoming payment webhook and approval mechanism 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. + 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 @@ -8478,10 +8158,19 @@ webhooks: 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 + ### 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: @@ -8491,68 +8180,121 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/InternalAccountStatusWebhook' + $ref: '#/components/schemas/IncomingPaymentWebhook' examples: - balanceDecrease: - summary: A transaction just cleared a customer account and the balance has decreased + pendingPayment: + summary: Pending payment example requiring approval value: id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INTERNAL_ACCOUNT.BALANCE_UPDATED + type: INCOMING_PAYMENT.PENDING timestamp: '2025-08-15T14:32:00Z' data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: PENDING + type: INCOMING + direction: CREDIT + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain 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 - totalBalance: - amount: 12500 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 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) + 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-000000000008 - type: INTERNAL_ACCOUNT.STATUS_UPDATED + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INCOMING_PAYMENT.COMPLETED timestamp: '2025-08-15T14:32:00Z' data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: INCOMING + direction: CREDIT + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: INTERNAL_FIAT - status: FROZEN - balance: - amount: 10000 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 currency: code: USD name: United States Dollar symbol: $ decimals: 2 - totalBalance: - amount: 10000 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: Payment for services + reconciliationInstructions: + reference: REF-123456789 + incomingCompletedCryptoPayment: + summary: Completed payment funded from an external crypto wallet + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000009 + type: INCOMING_PAYMENT.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000006 + status: COMPLETED + type: INCOMING + direction: CREDIT + source: + sourceType: REALTIME_FUNDING + currency: USDC + onChainTransaction: + transactionHash: 7RJWhvQBQPEjJmki5fhBboGBWRJhmcFkMvrr4Fu3tMSJ5EdynMEiYSyiWAH9GpcbHpeUzeSQF9ZY6q4x8AhBskUf + network: SOLANA + destination: + destinationType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + receivedAmount: + amount: 100000 currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - fundingPaymentInstructions: [] - createdAt: '2025-08-01T10:00:00Z' - updatedAt: '2025-08-15T14:32:00Z' + code: USDC + name: USD Coin + symbol: '' + decimals: 6 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: USDC deposit from self-custody wallet responses: '200': description: | - Webhook received successfully + 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: @@ -8565,29 +8307,47 @@ webhooks: 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' - verification-update: + '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: Verification status change + summary: Outgoing payment status webhook description: | - Webhook that is called when a customer's KYC/KYB verification status changes. + 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 API public key provided to you during integration + 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: verificationStatusWebhook + + This webhook is informational only and is sent when an outgoing payment completes successfully, fails, or is refunded. + operationId: outgoingPaymentWebhook tags: - Webhooks security: @@ -8597,78 +8357,168 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/VerificationWebhook' + $ref: '#/components/schemas/OutgoingPaymentWebhook' examples: - approved: - summary: Verification approved + outgoingCompletedPayment: + summary: Completed outgoing payment value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: VERIFICATION.APPROVED + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: OUTGOING_PAYMENT.COMPLETED timestamp: '2025-08-15T14:32:00Z' data: - id: Verification:019542f5-b3e7-1d02-0000-000000000010 + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: OUTGOING + direction: DEBIT + 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 - verificationStatus: APPROVED - errors: [] - createdAt: '2025-08-15T14:00:00Z' - resolveErrors: - summary: Verification requires action + 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 + outgoingCompletedCryptoPayment: + summary: Completed crypto payout to an external wallet value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000031 - type: VERIFICATION.RESOLVE_ERRORS + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: OUTGOING_PAYMENT.COMPLETED timestamp: '2025-08-15T14:32:00Z' data: - id: Verification:019542f5-b3e7-1d02-0000-000000000011 + id: Transaction:019542f5-b3e7-1d02-0000-000000000009 + status: COMPLETED + type: OUTGOING + direction: DEBIT + source: + sourceType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:c34dcbd6-dced-4ec4-b756-3c3a9ea3d789 + onChainTransaction: + transactionHash: h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx + network: SOLANA 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 `PROCESSING → ACTIVE`, on `PROCESSING → 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 + platformCustomerId: 18d3e5f7b4a9c2 + sentAmount: + amount: 100000 + currency: + code: USDC + name: USD Coin + symbol: '' + decimals: 6 + receivedAmount: + amount: 100000 + currency: + code: USDC + name: USD Coin + symbol: '' + decimals: 6 + quoteId: Quote:019542f5-b3e7-1d02-0000-000000000010 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: USDC withdrawal to self-custody wallet + paymentInstructions: [] + 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 + direction: DEBIT + 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. - operationId: cardStateChangeWebhook + + This webhook is purely for testing your endpoint integration and signature verification. + operationId: testWebhook tags: - Webhooks security: @@ -8678,74 +8528,18 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/CardStateChangeWebhook' + $ref: '#/components/schemas/TestWebhookRequest' examples: - activated: - summary: Card transitioned from PROCESSING 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 - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - processorRef: card_b81c2a4f - issuerRef: lead_card_7a1b9c3d - 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 + testWebhook: + summary: Test webhook example 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' + id: Webhook:019542f5-b3e7-1d02-0000-000000000001 + type: TEST + timestamp: '2025-08-15T14:32:00Z' + data: {} responses: '200': - description: | - Webhook received successfully + description: Webhook received successfully. This confirms your webhook endpoint is properly configured. '400': description: Bad request content: @@ -8764,16 +8558,14 @@ webhooks: application/json: schema: $ref: '#/components/schemas/Error409' - card-funding-source-change: + bulk-upload: post: - summary: Card funding source change + summary: Bulk upload status webhook 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. - + 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 @@ -8782,7 +8574,9 @@ webhooks: 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 + + This webhook is sent when a bulk upload job completes or fails, providing detailed information about the results. + operationId: bulkUploadWebhook tags: - Webhooks security: @@ -8792,34 +8586,48 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/CardFundingSourceChangeWebhook' + $ref: '#/components/schemas/BulkUploadWebhook' examples: - fundingSourcesReplaced: - summary: Funding sources replaced via PATCH /cards/{id} + completedUpload: + summary: Successful bulk upload completion value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: CARD.FUNDING_SOURCE_CHANGE - timestamp: '2026-05-08T14:30:00Z' + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: BULK_UPLOAD.COMPLETED + timestamp: '2025-08-15T14:32: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' + 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 + description: Webhook received successfully '400': description: Bad request content: @@ -8838,28 +8646,638 @@ webhooks: 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 + invitation-claimed: + post: + summary: Invitation claimed webhook 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 - + 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 + totalBalance: + amount: 12500 + 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 + totalBalance: + 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 `PROCESSING → ACTIVE`, on `PROCESSING → 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 PROCESSING 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 + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + processorRef: card_b81c2a4f + issuerRef: lead_card_7a1b9c3d + 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: @@ -19784,43 +20202,296 @@ components: 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: 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 + 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 + format: date-time + description: When the action was submitted by the agent. + example: '2025-10-03T15:00:00Z' + updatedAt: + type: string + format: date-time + description: When the action was last updated. + example: '2025-10-03T15:02:00Z' + AgentActionListResponse: + type: object + required: + - data + - hasMore + properties: + 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: 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: 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: 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: 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: + - agentId + - agentName + - accessToken + - policy + properties: + agentId: + type: string + 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 + - PROCESSING + - 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. | + | `PROCESSING` | 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 `PROCESSING`. | + | `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: + - id + - cardholderId + - state + - form + - fundingSources + - 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: + 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 + 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 + processorRef: 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: + description: Opaque processor-side reference for the card (e.g. the Lithic card token). Useful for cross-referencing in the processor's dashboards; not used for any Grid request routing. + example: card_b81c2a4f + readOnly: true + issuerRef: 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. + description: Opaque identifier for the card on the issuer of record (e.g. the Lead Bank account/card identifier). Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. + example: lead_card_7a1b9c3d + readOnly: true createdAt: type: string format: date-time - description: When the action was submitted by the agent. - example: '2025-10-03T15:00:00Z' + description: Creation timestamp + readOnly: true + example: '2026-05-08T14:10: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 + readOnly: true + example: '2026-05-08T14:11:00Z' + CardListResponse: type: object required: - data @@ -19828,390 +20499,806 @@ components: properties: data: type: array - description: List of agent actions matching the filter criteria. + description: List of cards matching the filter criteria items: - $ref: '#/components/schemas/AgentAction' + $ref: '#/components/schemas/Card' 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 (only present if hasMore is true) totalCount: type: integer - description: Total number of actions matching the criteria (excluding pagination). - AgentUpdateRequest: + description: Total number of cards matching the criteria (excluding pagination) + CardCreateRequest: type: object - description: Partial update to an agent's basic fields. At least one field must be provided. + required: + - cardholderId + - form + - fundingSources properties: - name: + cardholderId: 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: 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: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. + 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: + state: + 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: + 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 + CardRevealResponse: + type: object + required: + - panEmbedUrl + - expiresAt + properties: + panEmbedUrl: + type: string + format: uri + description: 'Signed URL of the card processor''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. The URL is a short-lived bearer secret: render it immediately and never store, cache, or log it.' + example: https://embed.lithic.com/iframe/...?t=... + expiresAt: + type: string + format: date-time + description: When the signed URL stops loading. Request a new reveal rather than re-rendering an expired URL. + example: '2026-05-08T14:16:00Z' + SandboxCardAuthorizationRequest: + type: object + 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: + 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' + SandboxCardClearingRequest: + type: object + required: + - 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: + cardTransactionId: 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. - example: USD - perTransactionLimit: + 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: 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: + 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 + 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). + properties: + cardTransactionId: + 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: 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: + 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 + 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. + StablecoinProvider: + type: string + enum: + - BRALE + description: Stablecoin provider backing the linked account, stablecoin, or operation. + StablecoinNetwork: + type: string + enum: + - SPARK + description: Public network family for the stablecoin token identifier. The concrete Spark network is inferred from the platform mode. + StablecoinProviderEnvironment: + type: string + enum: + - SANDBOX + - PRODUCTION + description: Provider environment derived from the authenticated Grid platform mode. + Stablecoin: + 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: '#/components/schemas/StablecoinNetwork' + decimals: + type: integer + 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: 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 - description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. + required: + - data + - hasMore properties: - permissions: + data: 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: + $ref: '#/components/schemas/Stablecoin' + 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. + StablecoinRegisterRequest: type: object + required: + - providerTokenIdentifier + - networkTokenIdentifier + - network properties: - reason: + providerTokenIdentifier: 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: 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: '#/components/schemas/StablecoinNetwork' + 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 + StablecoinMintFundingSourceBase: type: object required: - - code - - redeemed + - type properties: - code: + type: 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: + enum: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Funding source variant. Grid internal account and provider internal balance funding are reserved for follow-up support. + example: ACH_DEBIT + StablecoinWireFundingSource: + title: Wire + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + properties: + type: + type: string + enum: + - WIRE + description: Wire-funded mint. Funding instructions are returned on the resulting operation. + example: WIRE + description: Wire funding source. The issuer wires fiat to the provider using the returned funding instructions. + StablecoinAchDebitFundingSource: + title: ACH Debit + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - ACH_DEBIT + description: ACH debit funding. + example: ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` debited to fund the mint. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + description: ACH debit funding source. The provider debits the referenced external account. + StablecoinSameDayAchDebitFundingSource: + title: Same-Day ACH Debit + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - SAME_DAY_ACH_DEBIT + description: Same-day ACH debit funding. + example: SAME_DAY_ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` debited to fund the mint. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + description: Same-day ACH debit funding source. The provider debits the referenced external account. + StablecoinGridInternalFundingSource: + title: Grid Internal Account + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + description: Grid internal account funding. Reserved for the follow-up Grid-funded mint flow. + example: GRID_INTERNAL_ACCOUNT + accountId: + type: string + description: Grid internal funding account id. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000102 + description: Grid internal account funding source, reserved for future Grid-funded mint flows. + StablecoinProviderBalanceFundingSource: + title: Provider Internal Balance + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - sourceTokenIdentifier + - cryptoNetwork + properties: + type: + type: string + enum: + - PROVIDER_INTERNAL_BALANCE + description: Provider internal balance funding. Reserved for the follow-up provider-balance mint flow. + example: PROVIDER_INTERNAL_BALANCE + sourceTokenIdentifier: + type: string + description: Provider token/value type spent from the provider internal balance. + example: USDC + cryptoNetwork: + type: string + description: Source crypto network for the provider internal balance funds. + example: SOLANA + description: Provider internal balance funding source, reserved for future provider-funded mint flows. + StablecoinMintFundingSource: + oneOf: + - $ref: '#/components/schemas/StablecoinWireFundingSource' + - $ref: '#/components/schemas/StablecoinAchDebitFundingSource' + - $ref: '#/components/schemas/StablecoinSameDayAchDebitFundingSource' + - $ref: '#/components/schemas/StablecoinGridInternalFundingSource' + - $ref: '#/components/schemas/StablecoinProviderBalanceFundingSource' + discriminator: + propertyName: type + mapping: + WIRE: '#/components/schemas/StablecoinWireFundingSource' + ACH_DEBIT: '#/components/schemas/StablecoinAchDebitFundingSource' + SAME_DAY_ACH_DEBIT: '#/components/schemas/StablecoinSameDayAchDebitFundingSource' + GRID_INTERNAL_ACCOUNT: '#/components/schemas/StablecoinGridInternalFundingSource' + PROVIDER_INTERNAL_BALANCE: '#/components/schemas/StablecoinProviderBalanceFundingSource' + StablecoinMintDestination: type: object + description: Account that receives the minted stablecoin. External and Grid-managed accounts are represented as a single account reference, matching the `accountId` pattern used elsewhere in the API; the id prefix (`ExternalAccount:` or `InternalAccount:`) determines which. In the initial Brale-backed flow this must reference an active Spark external account. required: - - agentId - - agentName - - accessToken - - policy + - accountId properties: - agentId: + accountId: type: string - description: The agent's system-generated ID. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - agentName: + description: Grid account receiving the minted stablecoin. Accepts an `ExternalAccount:` id (initial Brale-backed flow) or an `InternalAccount:` id for Grid-managed destinations. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000201 + StablecoinMintRequest: + type: object + required: + - amount + - fundingSource + - destination + properties: + amount: type: string - description: The agent's name. - example: Payroll Automation Agent - accessToken: + pattern: ^[0-9]+$ + description: Amount to mint in the stablecoin's smallest unit. The amount must convert exactly to a whole fiat cent for the token decimals. + example: '1000000' + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + destination: + $ref: '#/components/schemas/StablecoinMintDestination' + description: 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 - - PROCESSING - - 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. | - | `PROCESSING` | 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 `PROCESSING`. | - | `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: + maxLength: 1024 + description: Optional platform-provided operation description. + example: Initial program funding mint + StablecoinOperationType: type: string enum: - - VISA - - MASTERCARD - description: | - Card network brand. Read-only — determined by Grid when the card is - provisioned with the issuer. - CardForm: + - MINT + - BURN + description: Stablecoin issuer operation type. + StablecoinOperationStatus: 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: + - CREATED + - PENDING_FUNDING + - PENDING_PROVIDER + - PROCESSING + - COMPLETED + - FAILED + - EXPIRED + description: Stablecoin issuer operation lifecycle status. + StablecoinOperationSource: type: object + description: 'Source of a stablecoin operation, as reported on a `StablecoinOperation`. A single merged shape (superset of the mint funding source and burn source request variants) so the field is unambiguously deserializable regardless of operation type: `externalAccountId` is present for external-account funded mints and external-account burns, `accountId` for Grid internal account sources, and `sourceTokenIdentifier`/`cryptoNetwork` for provider internal balance sources.' required: - - id - - cardholderId - - state - - form - - fundingSources - - createdAt - - updatedAt + - type properties: - id: + type: type: string - description: System-generated unique card identifier - readOnly: true - example: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: + enum: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - EXTERNAL_ACCOUNT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Source variant. Mint funding uses `WIRE`, `ACH_DEBIT`, or `SAME_DAY_ACH_DEBIT`; burns use `EXTERNAL_ACCOUNT`. `GRID_INTERNAL_ACCOUNT` and `PROVIDER_INTERNAL_BALANCE` are shared across mint and burn. + example: ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` funding the operation, present for ACH debit mints and external-account burns. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + accountId: type: string - description: The id of the `Customer` who holds this card. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: + description: Grid internal account id, present for Grid internal account sources. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000102 + sourceTokenIdentifier: 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: Provider token/value type, present for provider internal balance sources. + example: USDC + cryptoNetwork: 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 - 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 + description: Source crypto network, present for provider internal balance sources. + example: SOLANA + StablecoinFundingInstructions: + type: object + description: Provider funding instructions safe to show publicly. Present for wire-funded mint operations and external-source burn operations when available. The common fields below are always declared; the exact set of remaining fields is rail- and provider-specific (for example, wire instructions carry bank beneficiary/account/routing details while Spark and on-chain instructions carry a deposit address), so `additionalProperties` stays open to pass those through without a spec change per rail. + additionalProperties: true + properties: + rail: + type: string + description: Funding rail these instructions apply to (e.g. `SPARK`, `WIRE`). + example: SPARK + network: + type: string + description: Network the funds should be sent on, when applicable. + example: SPARK + address: + type: string + description: Deposit address the issuer sends funds to, for on-chain or Spark rails. + example: spark1... + valueType: + type: string + description: Provider token/value type the deposit address expects. + example: ACME + example: + rail: SPARK + network: SPARK + address: spark1... + valueType: ACME + StablecoinOperationDestination: + type: object + description: 'Destination of a stablecoin operation, as reported on a `StablecoinOperation`. A single merged (flat) shape so the field is unambiguously deserializable regardless of operation type: `accountId` identifies the receiving account (its `ExternalAccount:` / `InternalAccount:` prefix disambiguates external vs Grid-managed), and `rail` is present for burn (fiat payout) destinations and absent for mint destinations.' + required: + - accountId + properties: + accountId: + type: string + description: Grid account that received the funds. An `ExternalAccount:` id for external destinations or an `InternalAccount:` id for Grid-managed destinations. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000205 + rail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail, present for burn (fiat redemption) destinations. + StablecoinEstimatedDelivery: + type: object + description: Static rail timing estimate for fiat redemption delivery. This is guidance, not a guaranteed arrival time. + additionalProperties: true + properties: + rail: + type: string + description: Fiat payout rail the estimate applies to. + example: ACH_CREDIT + amount: + type: string + pattern: ^[0-9]+$ + description: Estimated delivery amount in the smallest unit of `currency` (e.g. cents for USD). + example: '100' 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. + description: ISO 4217 currency code of the fiat payout. example: USD - readOnly: true - processorRef: + timing: type: string - description: Opaque processor-side reference for the card (e.g. the Lithic card token). Useful for cross-referencing in the processor's dashboards; not used for any Grid request routing. - example: card_b81c2a4f - readOnly: true - issuerRef: + description: Human-readable rail timing estimate. + example: 1-3 business days + example: + rail: ACH_CREDIT + amount: '100' + currency: USD + timing: 1-3 business days + StablecoinOperation: + type: object + required: + - id + - stablecoinId + - operationType + - status + - amount + - provider + - providerEnvironment + - stablecoinProviderAccountId + - createdAt + - updatedAt + properties: + id: type: string - description: Opaque identifier for the card on the issuer of record (e.g. the Lead Bank account/card identifier). Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. - example: lead_card_7a1b9c3d - readOnly: true + description: System-generated stablecoin issuer operation identifier. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000301 + 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: string + description: Operation amount in the stablecoin's smallest unit. + example: '1000000' + provider: + $ref: '#/components/schemas/StablecoinProvider' + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link used for the operation. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + source: + $ref: '#/components/schemas/StablecoinOperationSource' + fundingInstructions: + $ref: '#/components/schemas/StablecoinFundingInstructions' + destination: + $ref: '#/components/schemas/StablecoinOperationDestination' + estimatedDelivery: + $ref: '#/components/schemas/StablecoinEstimatedDelivery' + expiresAt: + type: string + format: date-time + description: Expiry for operations awaiting external funding. + example: '2026-05-27T16:40:00Z' + providerStatus: + type: string + description: Sanitized provider status when available. + example: pending + failureReason: + type: string + description: Stable internal failure code for terminal failed operations. + example: PROVIDER_TRANSFER_FAILED + description: + type: string + description: Platform-provided operation description. + example: Initial program funding mint createdAt: type: string format: date-time - description: Creation timestamp - readOnly: true - example: '2026-05-08T14:10:00Z' + description: Creation timestamp. + example: '2026-05-20T16:40: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:10:00Z' + Error503: type: object required: - - data - - hasMore + - message + - status + - code properties: - data: - type: array - description: List of cards matching the filter criteria - items: - $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: + status: type: integer - description: Total number of cards matching the criteria (excluding pagination) - CardCreateRequest: - type: object - required: - - cardholderId - - form - - fundingSources - properties: - cardholderId: + enum: + - 503 + description: HTTP status code + code: 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: + description: | + | Error Code | Description | + |------------|-------------| + | SERVICE_UNAVAILABLE | Downstream service is temporarily unavailable | + enum: + - SERVICE_UNAVAILABLE + message: 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: + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + StablecoinBurnSourceBase: 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: + - type properties: - state: + type: 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: - 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 - CardRevealResponse: + - EXTERNAL_ACCOUNT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Burn source variant. Grid internal account burns are reserved for the Grid-enabled ledger movement flow. + example: EXTERNAL_ACCOUNT + StablecoinExternalAccountBurnSource: + title: External Account + allOf: + - $ref: '#/components/schemas/StablecoinBurnSourceBase' + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - EXTERNAL_ACCOUNT + description: External account burn. References an active Spark external account and returns funding instructions. + example: EXTERNAL_ACCOUNT + externalAccountId: + type: string + description: Grid Spark `ExternalAccount` expected to fund the provider for the burn. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000203 + description: External account burn source. The issuer funds the provider from a Spark external account. + StablecoinGridInternalBurnSource: + title: Grid Internal Account + allOf: + - $ref: '#/components/schemas/StablecoinBurnSourceBase' + - type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + description: Grid internal account burn. Reserved for the Grid-controlled ledger movement flow. + example: GRID_INTERNAL_ACCOUNT + accountId: + type: string + description: Grid internal source account id. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000204 + description: Grid internal account burn source, reserved for future Grid-controlled burn flows. + StablecoinProviderBalanceBurnSource: + title: Provider Internal Balance + allOf: + - $ref: '#/components/schemas/StablecoinBurnSourceBase' + - type: object + required: + - type + properties: + type: + type: string + enum: + - PROVIDER_INTERNAL_BALANCE + description: Provider internal balance burn. Spends stablecoin funds already held at the provider. + example: PROVIDER_INTERNAL_BALANCE + description: Provider internal balance burn source. No external funding is required; the provider spends existing balance. + StablecoinBurnSource: + oneOf: + - $ref: '#/components/schemas/StablecoinExternalAccountBurnSource' + - $ref: '#/components/schemas/StablecoinGridInternalBurnSource' + - $ref: '#/components/schemas/StablecoinProviderBalanceBurnSource' + discriminator: + propertyName: type + mapping: + EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinExternalAccountBurnSource' + GRID_INTERNAL_ACCOUNT: '#/components/schemas/StablecoinGridInternalBurnSource' + PROVIDER_INTERNAL_BALANCE: '#/components/schemas/StablecoinProviderBalanceBurnSource' + StablecoinBurnDestination: type: object required: - - panEmbedUrl - - expiresAt + - type + - externalAccountId + - rail properties: - panEmbedUrl: + type: type: string - format: uri - description: 'Signed URL of the card processor''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. The URL is a short-lived bearer secret: render it immediately and never store, cache, or log it.' - example: https://embed.lithic.com/iframe/...?t=... - expiresAt: + enum: + - EXTERNAL_ACCOUNT + description: Burn destination variant. V1 supports fiat Grid `ExternalAccount` destinations. + externalAccountId: type: string - format: date-time - description: When the signed URL stops loading. Request a new reveal rather than re-rendering an expired URL. - example: '2026-05-08T14:16:00Z' - SandboxCardAuthorizationRequest: + description: Grid bank `ExternalAccount` receiving fiat redemption proceeds. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000205 + rail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail for the burn destination. + StablecoinBurnRequest: type: object 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. + - source + - destination properties: 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' - SandboxCardClearingRequest: - type: object - required: - - 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: - cardTransactionId: 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 - 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: + pattern: ^[0-9]+$ + description: Amount to burn in the stablecoin's smallest unit. The amount must convert exactly to a whole fiat cent for the token decimals. + example: '1000000' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + destination: + $ref: '#/components/schemas/StablecoinBurnDestination' + description: + type: string + maxLength: 1024 + description: Optional platform-provided operation description. + example: Redeem ACME + 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 - StablecoinProvider: - type: string - enum: - - BRALE - description: Stablecoin provider backing the linked account, stablecoin, or operation. + description: Total number of stablecoin operations matching the query. StablecoinProviderAccountStatus: type: string enum: @@ -20219,12 +21306,6 @@ components: - 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 required: diff --git a/openapi.yaml b/openapi.yaml index 476be1e8d..c591121db 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -58,7 +58,7 @@ tags: - 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. Link provider accounts, register provider-created stablecoins, create mint/burn quotes, execute them, and track the resulting operations. + description: Stablecoin issuance endpoints. Link provider accounts, register provider-created stablecoins, create direct mint/burn issuer operations, and track operation status. paths: /config: get: @@ -7481,12 +7481,12 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /stablecoin-provider-accounts: + /stablecoins: post: - summary: Link a stablecoin provider account + summary: Register an existing provider-created stablecoin description: | - Link provider API credentials for the authenticated platform. Provider credentials are account-scoped and can be reused for multiple stablecoins. Currently, the only supported provider is `BRALE`; the provider environment is derived from the authenticated Grid platform mode. - operationId: linkStablecoinProviderAccount + 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: @@ -7494,7 +7494,7 @@ paths: parameters: - name: Idempotency-Key in: header - description: Idempotency key for retrying this request safely. Replays return the prior result; conflicting payloads are rejected. + description: Required idempotency key for retrying this request safely. required: true schema: type: string @@ -7504,14 +7504,14 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccountLinkRequest' + $ref: '#/components/schemas/StablecoinRegisterRequest' responses: '201': - description: Stablecoin provider account linked + description: Stablecoin registered content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccount' + $ref: '#/components/schemas/Stablecoin' '400': description: Bad request content: @@ -7524,6 +7524,12 @@ paths: 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 content: @@ -7537,24 +7543,29 @@ paths: schema: $ref: '#/components/schemas/Error500' get: - summary: List stablecoin provider account links - description: Retrieve stablecoin provider account links for the authenticated platform. - operationId: listStablecoinProviderAccounts + summary: List stablecoins + description: Retrieve stablecoins registered to the authenticated platform. + operationId: listStablecoins tags: - Stablecoins security: - BasicAuth: [] parameters: - - name: provider + - name: issuanceStatus in: query required: false schema: - $ref: '#/components/schemas/StablecoinProvider' - - name: status + $ref: '#/components/schemas/StablecoinIssuanceStatus' + - name: gridOperationsStatus in: query required: false schema: - $ref: '#/components/schemas/StablecoinProviderAccountStatus' + $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) @@ -7566,7 +7577,7 @@ paths: default: 20 - name: cursor in: query - description: Cursor for pagination (returned from previous request) + description: Opaque cursor returned as `nextCursor` from the previous response. required: false schema: type: string @@ -7576,7 +7587,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccountListResponse' + $ref: '#/components/schemas/StablecoinListResponse' '400': description: Bad request - Invalid parameters content: @@ -7595,18 +7606,18 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /stablecoin-provider-accounts/{stablecoinProviderAccountId}: + /stablecoins/{stablecoinId}: parameters: - - name: stablecoinProviderAccountId + - name: stablecoinId in: path - description: System-generated stablecoin provider account link identifier + description: System-generated stablecoin identifier required: true schema: type: string get: - summary: Get a stablecoin provider account link - description: Retrieve a stablecoin provider account link by id for the authenticated platform. - operationId: getStablecoinProviderAccount + summary: Get a stablecoin + description: Retrieve a single registered stablecoin by its Grid identifier. + operationId: getStablecoin tags: - Stablecoins security: @@ -7617,7 +7628,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/StablecoinProviderAccount' + $ref: '#/components/schemas/Stablecoin' '401': description: Unauthorized content: @@ -7625,7 +7636,7 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Stablecoin provider account link not found + description: Stablecoin not found content: application/json: schema: @@ -7636,247 +7647,118 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' -webhooks: - agent-action: + /stablecoins/{stablecoinId}/mints: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string post: - summary: Agent action pending approval webhook + summary: Create a stablecoin mint operation 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 + Create a provider-backed mint operation for a registered stablecoin. Funding and destination accounts are normal Grid `ExternalAccount` objects; any provider-specific Brale address linkage is managed internally by Grid. Wire-funded mints return funding instructions and remain pending until the provider reports funds received. + operationId: createStablecoinMint tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Required idempotency key for retrying this mint request safely. + 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/StablecoinMintRequest' responses: - '200': - description: Webhook received and acknowledged. + '201': + description: Mint operation created + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinOperation' + '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' + '404': + description: Stablecoin or referenced 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' - incoming-payment: + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + '503': + description: Provider temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error503' + /stablecoins/{stablecoinId}/burns: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string post: - summary: Incoming payment webhook and approval mechanism + summary: Create a stablecoin burn operation 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 + Create a provider-backed burn/redemption operation for a registered stablecoin. Burn sources and fiat destinations are normal Grid account objects; provider-specific Brale address ids are resolved and stored internally. External Spark wallet sources return funding instructions and remain pending until the provider reports funds received. + operationId: createStablecoinBurn tags: - - Webhooks + - Stablecoins security: - - WebhookSignature: [] + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Required idempotency key for retrying this burn request safely. + required: true + schema: + type: string + maxLength: 255 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 - direction: CREDIT - 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 - direction: CREDIT - 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 - incomingCompletedCryptoPayment: - summary: Completed payment funded from an external crypto wallet - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000009 - type: INCOMING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000006 - status: COMPLETED - type: INCOMING - direction: CREDIT - source: - sourceType: REALTIME_FUNDING - currency: USDC - onChainTransaction: - transactionHash: 7RJWhvQBQPEjJmki5fhBboGBWRJhmcFkMvrr4Fu3tMSJ5EdynMEiYSyiWAH9GpcbHpeUzeSQF9ZY6q4x8AhBskUf - network: SOLANA - destination: - destinationType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - receivedAmount: - amount: 100000 - currency: - code: USDC - name: USD Coin - symbol: '' - decimals: 6 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: USDC deposit from self-custody wallet + $ref: '#/components/schemas/StablecoinBurnRequest' 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. + '201': + description: Burn operation created 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/StablecoinOperation' '400': description: Bad request content: @@ -7884,332 +7766,170 @@ webhooks: 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. + '404': + description: Stablecoin or referenced account not found content: application/json: schema: - $ref: '#/components/schemas/IncomingPaymentWebhookForbiddenResponse' + $ref: '#/components/schemas/Error404' '409': - description: Conflict - Webhook has already been processed (duplicate id) + description: Conflict content: application/json: schema: $ref: '#/components/schemas/Error409' - '422': - description: | - Unprocessable Entity - Additional counterparty information required. - Only applicable for PENDING transactions. + '500': + description: Internal service error 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 + $ref: '#/components/schemas/Error500' + '503': + description: Provider temporarily unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/Error503' + /stablecoins/{stablecoinId}/operations: + parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string + get: + summary: List stablecoin issuer operations + description: List issuer mint and burn operations for a stablecoin, most recent first, with cursor pagination. + operationId: listStablecoinOperations tags: - - Webhooks + - Stablecoins 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 - direction: DEBIT - 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 - outgoingCompletedCryptoPayment: - summary: Completed crypto payout to an external wallet - value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000008 - type: OUTGOING_PAYMENT.COMPLETED - timestamp: '2025-08-15T14:32:00Z' - data: - id: Transaction:019542f5-b3e7-1d02-0000-000000000009 - status: COMPLETED - type: OUTGOING - direction: DEBIT - source: - sourceType: ACCOUNT - accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 - destination: - destinationType: ACCOUNT - accountId: ExternalAccount:c34dcbd6-dced-4ec4-b756-3c3a9ea3d789 - onChainTransaction: - transactionHash: h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx - network: SOLANA - customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCustomerId: 18d3e5f7b4a9c2 - sentAmount: - amount: 100000 - currency: - code: USDC - name: USD Coin - symbol: '' - decimals: 6 - receivedAmount: - amount: 100000 - currency: - code: USDC - name: USD Coin - symbol: '' - decimals: 6 - quoteId: Quote:019542f5-b3e7-1d02-0000-000000000010 - settledAt: '2025-08-15T14:30:00Z' - createdAt: '2025-08-15T14:25:18Z' - description: USDC withdrawal to self-custody wallet - paymentInstructions: [] - 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 - direction: DEBIT - 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 + - BasicAuth: [] + parameters: + - name: operationType + in: query + description: Filter operations by type. When omitted, both mints and burns are returned. + required: false + schema: + $ref: '#/components/schemas/StablecoinOperationType' + - 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: Opaque cursor returned as `nextCursor` from the previous response. + required: false + schema: + type: string responses: '200': - description: Webhook received successfully - '400': - description: Bad request + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error400' + $ref: '#/components/schemas/StablecoinOperationListResponse' '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' - 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 + $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 issuer operation identifier + required: true + schema: + type: string + get: + summary: Get a stablecoin issuer operation + description: Retrieve a single stablecoin issuer operation by its Grid identifier. + operationId: getStablecoinOperation 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: [] responses: '200': - description: Webhook received successfully. This confirms your webhook endpoint is properly configured. - '400': - description: Bad request + description: Successful operation content: application/json: schema: - $ref: '#/components/schemas/Error400' + $ref: '#/components/schemas/StablecoinOperation' '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 operation not found content: application/json: schema: - $ref: '#/components/schemas/Error409' - bulk-upload: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /stablecoin-provider-accounts: post: - summary: Bulk upload status webhook + summary: Link a stablecoin provider account 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 + Link provider API credentials for the authenticated platform. Provider credentials are account-scoped and can be reused for multiple stablecoins. Currently, 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/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 + $ref: '#/components/schemas/StablecoinProviderAccountLinkRequest' responses: - '200': - description: Webhook received successfully + '201': + description: Stablecoin provider account linked + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinProviderAccount' '400': description: Bad request content: @@ -8217,108 +7937,143 @@ 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' - 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 + '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/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 + - 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 + description: Successful operation + content: + application/json: + schema: + $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' - '409': - description: Conflict - Webhook has already been processed (duplicate id) + '500': + description: Internal service error 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. + $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 + description: Retrieve a stablecoin provider account link by id for the authenticated platform. + operationId: getStablecoinProviderAccount + tags: + - Stablecoins + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/StablecoinProviderAccount' + '401': + description: Unauthorized + content: + application/json: + schema: + $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' +webhooks: + agent-action: + post: + summary: Agent action pending approval webhook + 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 API public key provided to you during integration + 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: customerStatusWebhook + + 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: @@ -8328,127 +8083,52 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/CustomerWebhook' + $ref: '#/components/schemas/AgentActionWebhook' 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 + pendingApproval: + summary: Agent action pending approval value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000010 - type: CUSTOMER.KYB_REJECTED - timestamp: '2025-08-15T14:32:00Z' + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: AGENT_ACTION.PENDING_APPROVAL + timestamp: '2025-10-03T15:00: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 + 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 successfully - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error400' + description: Webhook received and acknowledged. '401': description: Unauthorized - Signature validation failed content: @@ -8461,11 +8141,11 @@ webhooks: application/json: schema: $ref: '#/components/schemas/Error409' - internal-account-status: + incoming-payment: post: - summary: Internal account status webhook + summary: Incoming payment webhook and approval mechanism 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. + 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 @@ -8478,10 +8158,19 @@ webhooks: 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 + ### 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: @@ -8491,68 +8180,121 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/InternalAccountStatusWebhook' + $ref: '#/components/schemas/IncomingPaymentWebhook' examples: - balanceDecrease: - summary: A transaction just cleared a customer account and the balance has decreased + pendingPayment: + summary: Pending payment example requiring approval value: id: Webhook:019542f5-b3e7-1d02-0000-000000000007 - type: INTERNAL_ACCOUNT.BALANCE_UPDATED + type: INCOMING_PAYMENT.PENDING timestamp: '2025-08-15T14:32:00Z' data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: PENDING + type: INCOMING + direction: CREDIT + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain 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 - totalBalance: - amount: 12500 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 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) + 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-000000000008 - type: INTERNAL_ACCOUNT.STATUS_UPDATED + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: INCOMING_PAYMENT.COMPLETED timestamp: '2025-08-15T14:32:00Z' data: - id: InternalAccount:019542f5-b3e7-1d02-0000-000000000005 + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: INCOMING + direction: CREDIT + destination: + destinationType: UMA_ADDRESS + umaAddress: $recipient@uma.domain customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 - type: INTERNAL_FIAT - status: FROZEN - balance: - amount: 10000 + platformCustomerId: 18d3e5f7b4a9c2 + senderUmaAddress: $sender@external.domain + receiverUmaAddress: $recipient@uma.domain + receivedAmount: + amount: 50000 currency: code: USD name: United States Dollar symbol: $ decimals: 2 - totalBalance: - amount: 10000 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: Payment for services + reconciliationInstructions: + reference: REF-123456789 + incomingCompletedCryptoPayment: + summary: Completed payment funded from an external crypto wallet + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000009 + type: INCOMING_PAYMENT.COMPLETED + timestamp: '2025-08-15T14:32:00Z' + data: + id: Transaction:019542f5-b3e7-1d02-0000-000000000006 + status: COMPLETED + type: INCOMING + direction: CREDIT + source: + sourceType: REALTIME_FUNDING + currency: USDC + onChainTransaction: + transactionHash: 7RJWhvQBQPEjJmki5fhBboGBWRJhmcFkMvrr4Fu3tMSJ5EdynMEiYSyiWAH9GpcbHpeUzeSQF9ZY6q4x8AhBskUf + network: SOLANA + destination: + destinationType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000001 + platformCustomerId: 18d3e5f7b4a9c2 + receivedAmount: + amount: 100000 currency: - code: USD - name: United States Dollar - symbol: $ - decimals: 2 - fundingPaymentInstructions: [] - createdAt: '2025-08-01T10:00:00Z' - updatedAt: '2025-08-15T14:32:00Z' + code: USDC + name: USD Coin + symbol: '' + decimals: 6 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: USDC deposit from self-custody wallet responses: '200': description: | - Webhook received successfully + 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: @@ -8565,29 +8307,47 @@ webhooks: 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' - verification-update: + '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: Verification status change + summary: Outgoing payment status webhook description: | - Webhook that is called when a customer's KYC/KYB verification status changes. + 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 API public key provided to you during integration + 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: verificationStatusWebhook + + This webhook is informational only and is sent when an outgoing payment completes successfully, fails, or is refunded. + operationId: outgoingPaymentWebhook tags: - Webhooks security: @@ -8597,78 +8357,168 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/VerificationWebhook' + $ref: '#/components/schemas/OutgoingPaymentWebhook' examples: - approved: - summary: Verification approved + outgoingCompletedPayment: + summary: Completed outgoing payment value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: VERIFICATION.APPROVED + id: Webhook:019542f5-b3e7-1d02-0000-000000000007 + type: OUTGOING_PAYMENT.COMPLETED timestamp: '2025-08-15T14:32:00Z' data: - id: Verification:019542f5-b3e7-1d02-0000-000000000010 + id: Transaction:019542f5-b3e7-1d02-0000-000000000005 + status: COMPLETED + type: OUTGOING + direction: DEBIT + 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 - verificationStatus: APPROVED - errors: [] - createdAt: '2025-08-15T14:00:00Z' - resolveErrors: - summary: Verification requires action + 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 + outgoingCompletedCryptoPayment: + summary: Completed crypto payout to an external wallet value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000031 - type: VERIFICATION.RESOLVE_ERRORS + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: OUTGOING_PAYMENT.COMPLETED timestamp: '2025-08-15T14:32:00Z' data: - id: Verification:019542f5-b3e7-1d02-0000-000000000011 + id: Transaction:019542f5-b3e7-1d02-0000-000000000009 + status: COMPLETED + type: OUTGOING + direction: DEBIT + source: + sourceType: ACCOUNT + accountId: InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:c34dcbd6-dced-4ec4-b756-3c3a9ea3d789 + onChainTransaction: + transactionHash: h82pJGF9p7kpzb6eU326EFZf2cDnimbTFVeJtx1qtBmUNJAEqN76R7PwPfHt3oWb8R6cKvhgyxQdDn53jFrK6wFx + network: SOLANA 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 `PROCESSING → ACTIVE`, on `PROCESSING → 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 + platformCustomerId: 18d3e5f7b4a9c2 + sentAmount: + amount: 100000 + currency: + code: USDC + name: USD Coin + symbol: '' + decimals: 6 + receivedAmount: + amount: 100000 + currency: + code: USDC + name: USD Coin + symbol: '' + decimals: 6 + quoteId: Quote:019542f5-b3e7-1d02-0000-000000000010 + settledAt: '2025-08-15T14:30:00Z' + createdAt: '2025-08-15T14:25:18Z' + description: USDC withdrawal to self-custody wallet + paymentInstructions: [] + 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 + direction: DEBIT + 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. - operationId: cardStateChangeWebhook + + This webhook is purely for testing your endpoint integration and signature verification. + operationId: testWebhook tags: - Webhooks security: @@ -8678,74 +8528,18 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/CardStateChangeWebhook' + $ref: '#/components/schemas/TestWebhookRequest' examples: - activated: - summary: Card transitioned from PROCESSING 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 - fundingSources: - - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 - currency: USD - processorRef: card_b81c2a4f - issuerRef: lead_card_7a1b9c3d - 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 + testWebhook: + summary: Test webhook example 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' + id: Webhook:019542f5-b3e7-1d02-0000-000000000001 + type: TEST + timestamp: '2025-08-15T14:32:00Z' + data: {} responses: '200': - description: | - Webhook received successfully + description: Webhook received successfully. This confirms your webhook endpoint is properly configured. '400': description: Bad request content: @@ -8764,16 +8558,14 @@ webhooks: application/json: schema: $ref: '#/components/schemas/Error409' - card-funding-source-change: + bulk-upload: post: - summary: Card funding source change + summary: Bulk upload status webhook 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. - + 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 @@ -8782,7 +8574,9 @@ webhooks: 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 + + This webhook is sent when a bulk upload job completes or fails, providing detailed information about the results. + operationId: bulkUploadWebhook tags: - Webhooks security: @@ -8792,34 +8586,48 @@ webhooks: content: application/json: schema: - $ref: '#/components/schemas/CardFundingSourceChangeWebhook' + $ref: '#/components/schemas/BulkUploadWebhook' examples: - fundingSourcesReplaced: - summary: Funding sources replaced via PATCH /cards/{id} + completedUpload: + summary: Successful bulk upload completion value: - id: Webhook:019542f5-b3e7-1d02-0000-000000000030 - type: CARD.FUNDING_SOURCE_CHANGE - timestamp: '2026-05-08T14:30:00Z' + id: Webhook:019542f5-b3e7-1d02-0000-000000000008 + type: BULK_UPLOAD.COMPLETED + timestamp: '2025-08-15T14:32: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' + 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 + description: Webhook received successfully '400': description: Bad request content: @@ -8838,28 +8646,638 @@ webhooks: 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 + invitation-claimed: + post: + summary: Invitation claimed webhook 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 - + 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 + totalBalance: + amount: 12500 + 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 + totalBalance: + 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 `PROCESSING → ACTIVE`, on `PROCESSING → 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 PROCESSING 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 + fundingSources: + - InternalAccount:019542f5-b3e7-1d02-0000-000000000002 + currency: USD + processorRef: card_b81c2a4f + issuerRef: lead_card_7a1b9c3d + 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: @@ -19784,43 +20202,296 @@ components: 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: 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 + 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 + format: date-time + description: When the action was submitted by the agent. + example: '2025-10-03T15:00:00Z' + updatedAt: + type: string + format: date-time + description: When the action was last updated. + example: '2025-10-03T15:02:00Z' + AgentActionListResponse: + type: object + required: + - data + - hasMore + properties: + 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: 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: 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: 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: 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: + - agentId + - agentName + - accessToken + - policy + properties: + agentId: + type: string + 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 + - PROCESSING + - 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. | + | `PROCESSING` | 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 `PROCESSING`. | + | `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: + - id + - cardholderId + - state + - form + - fundingSources + - 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: + 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 + 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 + processorRef: 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: + description: Opaque processor-side reference for the card (e.g. the Lithic card token). Useful for cross-referencing in the processor's dashboards; not used for any Grid request routing. + example: card_b81c2a4f + readOnly: true + issuerRef: 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. + description: Opaque identifier for the card on the issuer of record (e.g. the Lead Bank account/card identifier). Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. + example: lead_card_7a1b9c3d + readOnly: true createdAt: type: string format: date-time - description: When the action was submitted by the agent. - example: '2025-10-03T15:00:00Z' + description: Creation timestamp + readOnly: true + example: '2026-05-08T14:10: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 + readOnly: true + example: '2026-05-08T14:11:00Z' + CardListResponse: type: object required: - data @@ -19828,390 +20499,806 @@ components: properties: data: type: array - description: List of agent actions matching the filter criteria. + description: List of cards matching the filter criteria items: - $ref: '#/components/schemas/AgentAction' + $ref: '#/components/schemas/Card' 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 (only present if hasMore is true) totalCount: type: integer - description: Total number of actions matching the criteria (excluding pagination). - AgentUpdateRequest: + description: Total number of cards matching the criteria (excluding pagination) + CardCreateRequest: type: object - description: Partial update to an agent's basic fields. At least one field must be provided. + required: + - cardholderId + - form + - fundingSources properties: - name: + cardholderId: 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: 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: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. + 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: + state: + 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: + 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 + CardRevealResponse: + type: object + required: + - panEmbedUrl + - expiresAt + properties: + panEmbedUrl: + type: string + format: uri + description: 'Signed URL of the card processor''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. The URL is a short-lived bearer secret: render it immediately and never store, cache, or log it.' + example: https://embed.lithic.com/iframe/...?t=... + expiresAt: + type: string + format: date-time + description: When the signed URL stops loading. Request a new reveal rather than re-rendering an expired URL. + example: '2026-05-08T14:16:00Z' + SandboxCardAuthorizationRequest: + type: object + 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: + 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' + SandboxCardClearingRequest: + type: object + required: + - 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: + cardTransactionId: 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. - example: USD - perTransactionLimit: + 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: 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: + 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 + 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). + properties: + cardTransactionId: + 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: 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: + 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 + 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. + StablecoinProvider: + type: string + enum: + - BRALE + description: Stablecoin provider backing the linked account, stablecoin, or operation. + StablecoinNetwork: + type: string + enum: + - SPARK + description: Public network family for the stablecoin token identifier. The concrete Spark network is inferred from the platform mode. + StablecoinProviderEnvironment: + type: string + enum: + - SANDBOX + - PRODUCTION + description: Provider environment derived from the authenticated Grid platform mode. + Stablecoin: + 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: '#/components/schemas/StablecoinNetwork' + decimals: + type: integer + 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: 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 - description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. + required: + - data + - hasMore properties: - permissions: + data: 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: + $ref: '#/components/schemas/Stablecoin' + 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. + StablecoinRegisterRequest: type: object + required: + - providerTokenIdentifier + - networkTokenIdentifier + - network properties: - reason: + providerTokenIdentifier: 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: 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: '#/components/schemas/StablecoinNetwork' + 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 + StablecoinMintFundingSourceBase: type: object required: - - code - - redeemed + - type properties: - code: + type: 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: + enum: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Funding source variant. Grid internal account and provider internal balance funding are reserved for follow-up support. + example: ACH_DEBIT + StablecoinWireFundingSource: + title: Wire + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + properties: + type: + type: string + enum: + - WIRE + description: Wire-funded mint. Funding instructions are returned on the resulting operation. + example: WIRE + description: Wire funding source. The issuer wires fiat to the provider using the returned funding instructions. + StablecoinAchDebitFundingSource: + title: ACH Debit + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - ACH_DEBIT + description: ACH debit funding. + example: ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` debited to fund the mint. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + description: ACH debit funding source. The provider debits the referenced external account. + StablecoinSameDayAchDebitFundingSource: + title: Same-Day ACH Debit + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - SAME_DAY_ACH_DEBIT + description: Same-day ACH debit funding. + example: SAME_DAY_ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` debited to fund the mint. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + description: Same-day ACH debit funding source. The provider debits the referenced external account. + StablecoinGridInternalFundingSource: + title: Grid Internal Account + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + description: Grid internal account funding. Reserved for the follow-up Grid-funded mint flow. + example: GRID_INTERNAL_ACCOUNT + accountId: + type: string + description: Grid internal funding account id. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000102 + description: Grid internal account funding source, reserved for future Grid-funded mint flows. + StablecoinProviderBalanceFundingSource: + title: Provider Internal Balance + allOf: + - $ref: '#/components/schemas/StablecoinMintFundingSourceBase' + - type: object + required: + - type + - sourceTokenIdentifier + - cryptoNetwork + properties: + type: + type: string + enum: + - PROVIDER_INTERNAL_BALANCE + description: Provider internal balance funding. Reserved for the follow-up provider-balance mint flow. + example: PROVIDER_INTERNAL_BALANCE + sourceTokenIdentifier: + type: string + description: Provider token/value type spent from the provider internal balance. + example: USDC + cryptoNetwork: + type: string + description: Source crypto network for the provider internal balance funds. + example: SOLANA + description: Provider internal balance funding source, reserved for future provider-funded mint flows. + StablecoinMintFundingSource: + oneOf: + - $ref: '#/components/schemas/StablecoinWireFundingSource' + - $ref: '#/components/schemas/StablecoinAchDebitFundingSource' + - $ref: '#/components/schemas/StablecoinSameDayAchDebitFundingSource' + - $ref: '#/components/schemas/StablecoinGridInternalFundingSource' + - $ref: '#/components/schemas/StablecoinProviderBalanceFundingSource' + discriminator: + propertyName: type + mapping: + WIRE: '#/components/schemas/StablecoinWireFundingSource' + ACH_DEBIT: '#/components/schemas/StablecoinAchDebitFundingSource' + SAME_DAY_ACH_DEBIT: '#/components/schemas/StablecoinSameDayAchDebitFundingSource' + GRID_INTERNAL_ACCOUNT: '#/components/schemas/StablecoinGridInternalFundingSource' + PROVIDER_INTERNAL_BALANCE: '#/components/schemas/StablecoinProviderBalanceFundingSource' + StablecoinMintDestination: type: object + description: Account that receives the minted stablecoin. External and Grid-managed accounts are represented as a single account reference, matching the `accountId` pattern used elsewhere in the API; the id prefix (`ExternalAccount:` or `InternalAccount:`) determines which. In the initial Brale-backed flow this must reference an active Spark external account. required: - - agentId - - agentName - - accessToken - - policy + - accountId properties: - agentId: + accountId: type: string - description: The agent's system-generated ID. - example: Agent:019542f5-b3e7-1d02-0000-000000000001 - agentName: + description: Grid account receiving the minted stablecoin. Accepts an `ExternalAccount:` id (initial Brale-backed flow) or an `InternalAccount:` id for Grid-managed destinations. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000201 + StablecoinMintRequest: + type: object + required: + - amount + - fundingSource + - destination + properties: + amount: type: string - description: The agent's name. - example: Payroll Automation Agent - accessToken: + pattern: ^[0-9]+$ + description: Amount to mint in the stablecoin's smallest unit. The amount must convert exactly to a whole fiat cent for the token decimals. + example: '1000000' + fundingSource: + $ref: '#/components/schemas/StablecoinMintFundingSource' + destination: + $ref: '#/components/schemas/StablecoinMintDestination' + description: 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 - - PROCESSING - - 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. | - | `PROCESSING` | 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 `PROCESSING`. | - | `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: + maxLength: 1024 + description: Optional platform-provided operation description. + example: Initial program funding mint + StablecoinOperationType: type: string enum: - - VISA - - MASTERCARD - description: | - Card network brand. Read-only — determined by Grid when the card is - provisioned with the issuer. - CardForm: + - MINT + - BURN + description: Stablecoin issuer operation type. + StablecoinOperationStatus: 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: + - CREATED + - PENDING_FUNDING + - PENDING_PROVIDER + - PROCESSING + - COMPLETED + - FAILED + - EXPIRED + description: Stablecoin issuer operation lifecycle status. + StablecoinOperationSource: type: object + description: 'Source of a stablecoin operation, as reported on a `StablecoinOperation`. A single merged shape (superset of the mint funding source and burn source request variants) so the field is unambiguously deserializable regardless of operation type: `externalAccountId` is present for external-account funded mints and external-account burns, `accountId` for Grid internal account sources, and `sourceTokenIdentifier`/`cryptoNetwork` for provider internal balance sources.' required: - - id - - cardholderId - - state - - form - - fundingSources - - createdAt - - updatedAt + - type properties: - id: + type: type: string - description: System-generated unique card identifier - readOnly: true - example: Card:019542f5-b3e7-1d02-0000-000000000010 - cardholderId: + enum: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - EXTERNAL_ACCOUNT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Source variant. Mint funding uses `WIRE`, `ACH_DEBIT`, or `SAME_DAY_ACH_DEBIT`; burns use `EXTERNAL_ACCOUNT`. `GRID_INTERNAL_ACCOUNT` and `PROVIDER_INTERNAL_BALANCE` are shared across mint and burn. + example: ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` funding the operation, present for ACH debit mints and external-account burns. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + accountId: type: string - description: The id of the `Customer` who holds this card. - example: Customer:019542f5-b3e7-1d02-0000-000000000001 - platformCardId: + description: Grid internal account id, present for Grid internal account sources. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000102 + sourceTokenIdentifier: 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: Provider token/value type, present for provider internal balance sources. + example: USDC + cryptoNetwork: 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 - 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 + description: Source crypto network, present for provider internal balance sources. + example: SOLANA + StablecoinFundingInstructions: + type: object + description: Provider funding instructions safe to show publicly. Present for wire-funded mint operations and external-source burn operations when available. The common fields below are always declared; the exact set of remaining fields is rail- and provider-specific (for example, wire instructions carry bank beneficiary/account/routing details while Spark and on-chain instructions carry a deposit address), so `additionalProperties` stays open to pass those through without a spec change per rail. + additionalProperties: true + properties: + rail: + type: string + description: Funding rail these instructions apply to (e.g. `SPARK`, `WIRE`). + example: SPARK + network: + type: string + description: Network the funds should be sent on, when applicable. + example: SPARK + address: + type: string + description: Deposit address the issuer sends funds to, for on-chain or Spark rails. + example: spark1... + valueType: + type: string + description: Provider token/value type the deposit address expects. + example: ACME + example: + rail: SPARK + network: SPARK + address: spark1... + valueType: ACME + StablecoinOperationDestination: + type: object + description: 'Destination of a stablecoin operation, as reported on a `StablecoinOperation`. A single merged (flat) shape so the field is unambiguously deserializable regardless of operation type: `accountId` identifies the receiving account (its `ExternalAccount:` / `InternalAccount:` prefix disambiguates external vs Grid-managed), and `rail` is present for burn (fiat payout) destinations and absent for mint destinations.' + required: + - accountId + properties: + accountId: + type: string + description: Grid account that received the funds. An `ExternalAccount:` id for external destinations or an `InternalAccount:` id for Grid-managed destinations. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000205 + rail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail, present for burn (fiat redemption) destinations. + StablecoinEstimatedDelivery: + type: object + description: Static rail timing estimate for fiat redemption delivery. This is guidance, not a guaranteed arrival time. + additionalProperties: true + properties: + rail: + type: string + description: Fiat payout rail the estimate applies to. + example: ACH_CREDIT + amount: + type: string + pattern: ^[0-9]+$ + description: Estimated delivery amount in the smallest unit of `currency` (e.g. cents for USD). + example: '100' 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. + description: ISO 4217 currency code of the fiat payout. example: USD - readOnly: true - processorRef: + timing: type: string - description: Opaque processor-side reference for the card (e.g. the Lithic card token). Useful for cross-referencing in the processor's dashboards; not used for any Grid request routing. - example: card_b81c2a4f - readOnly: true - issuerRef: + description: Human-readable rail timing estimate. + example: 1-3 business days + example: + rail: ACH_CREDIT + amount: '100' + currency: USD + timing: 1-3 business days + StablecoinOperation: + type: object + required: + - id + - stablecoinId + - operationType + - status + - amount + - provider + - providerEnvironment + - stablecoinProviderAccountId + - createdAt + - updatedAt + properties: + id: type: string - description: Opaque identifier for the card on the issuer of record (e.g. the Lead Bank account/card identifier). Useful for cross-referencing in issuer dashboards; not used for any Grid request routing. - example: lead_card_7a1b9c3d - readOnly: true + description: System-generated stablecoin issuer operation identifier. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000301 + 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: string + description: Operation amount in the stablecoin's smallest unit. + example: '1000000' + provider: + $ref: '#/components/schemas/StablecoinProvider' + providerEnvironment: + $ref: '#/components/schemas/StablecoinProviderEnvironment' + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link used for the operation. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + source: + $ref: '#/components/schemas/StablecoinOperationSource' + fundingInstructions: + $ref: '#/components/schemas/StablecoinFundingInstructions' + destination: + $ref: '#/components/schemas/StablecoinOperationDestination' + estimatedDelivery: + $ref: '#/components/schemas/StablecoinEstimatedDelivery' + expiresAt: + type: string + format: date-time + description: Expiry for operations awaiting external funding. + example: '2026-05-27T16:40:00Z' + providerStatus: + type: string + description: Sanitized provider status when available. + example: pending + failureReason: + type: string + description: Stable internal failure code for terminal failed operations. + example: PROVIDER_TRANSFER_FAILED + description: + type: string + description: Platform-provided operation description. + example: Initial program funding mint createdAt: type: string format: date-time - description: Creation timestamp - readOnly: true - example: '2026-05-08T14:10:00Z' + description: Creation timestamp. + example: '2026-05-20T16:40: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:10:00Z' + Error503: type: object required: - - data - - hasMore + - message + - status + - code properties: - data: - type: array - description: List of cards matching the filter criteria - items: - $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: + status: type: integer - description: Total number of cards matching the criteria (excluding pagination) - CardCreateRequest: - type: object - required: - - cardholderId - - form - - fundingSources - properties: - cardholderId: + enum: + - 503 + description: HTTP status code + code: 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: + description: | + | Error Code | Description | + |------------|-------------| + | SERVICE_UNAVAILABLE | Downstream service is temporarily unavailable | + enum: + - SERVICE_UNAVAILABLE + message: 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: + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true + StablecoinBurnSourceBase: 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: + - type properties: - state: + type: 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: - 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 - CardRevealResponse: + - EXTERNAL_ACCOUNT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Burn source variant. Grid internal account burns are reserved for the Grid-enabled ledger movement flow. + example: EXTERNAL_ACCOUNT + StablecoinExternalAccountBurnSource: + title: External Account + allOf: + - $ref: '#/components/schemas/StablecoinBurnSourceBase' + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - EXTERNAL_ACCOUNT + description: External account burn. References an active Spark external account and returns funding instructions. + example: EXTERNAL_ACCOUNT + externalAccountId: + type: string + description: Grid Spark `ExternalAccount` expected to fund the provider for the burn. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000203 + description: External account burn source. The issuer funds the provider from a Spark external account. + StablecoinGridInternalBurnSource: + title: Grid Internal Account + allOf: + - $ref: '#/components/schemas/StablecoinBurnSourceBase' + - type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + description: Grid internal account burn. Reserved for the Grid-controlled ledger movement flow. + example: GRID_INTERNAL_ACCOUNT + accountId: + type: string + description: Grid internal source account id. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000204 + description: Grid internal account burn source, reserved for future Grid-controlled burn flows. + StablecoinProviderBalanceBurnSource: + title: Provider Internal Balance + allOf: + - $ref: '#/components/schemas/StablecoinBurnSourceBase' + - type: object + required: + - type + properties: + type: + type: string + enum: + - PROVIDER_INTERNAL_BALANCE + description: Provider internal balance burn. Spends stablecoin funds already held at the provider. + example: PROVIDER_INTERNAL_BALANCE + description: Provider internal balance burn source. No external funding is required; the provider spends existing balance. + StablecoinBurnSource: + oneOf: + - $ref: '#/components/schemas/StablecoinExternalAccountBurnSource' + - $ref: '#/components/schemas/StablecoinGridInternalBurnSource' + - $ref: '#/components/schemas/StablecoinProviderBalanceBurnSource' + discriminator: + propertyName: type + mapping: + EXTERNAL_ACCOUNT: '#/components/schemas/StablecoinExternalAccountBurnSource' + GRID_INTERNAL_ACCOUNT: '#/components/schemas/StablecoinGridInternalBurnSource' + PROVIDER_INTERNAL_BALANCE: '#/components/schemas/StablecoinProviderBalanceBurnSource' + StablecoinBurnDestination: type: object required: - - panEmbedUrl - - expiresAt + - type + - externalAccountId + - rail properties: - panEmbedUrl: + type: type: string - format: uri - description: 'Signed URL of the card processor''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. The URL is a short-lived bearer secret: render it immediately and never store, cache, or log it.' - example: https://embed.lithic.com/iframe/...?t=... - expiresAt: + enum: + - EXTERNAL_ACCOUNT + description: Burn destination variant. V1 supports fiat Grid `ExternalAccount` destinations. + externalAccountId: type: string - format: date-time - description: When the signed URL stops loading. Request a new reveal rather than re-rendering an expired URL. - example: '2026-05-08T14:16:00Z' - SandboxCardAuthorizationRequest: + description: Grid bank `ExternalAccount` receiving fiat redemption proceeds. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000205 + rail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail for the burn destination. + StablecoinBurnRequest: type: object 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. + - source + - destination properties: 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' - SandboxCardClearingRequest: - type: object - required: - - 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: - cardTransactionId: 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 - 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: + pattern: ^[0-9]+$ + description: Amount to burn in the stablecoin's smallest unit. The amount must convert exactly to a whole fiat cent for the token decimals. + example: '1000000' + source: + $ref: '#/components/schemas/StablecoinBurnSource' + destination: + $ref: '#/components/schemas/StablecoinBurnDestination' + description: + type: string + maxLength: 1024 + description: Optional platform-provided operation description. + example: Redeem ACME + 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 - StablecoinProvider: - type: string - enum: - - BRALE - description: Stablecoin provider backing the linked account, stablecoin, or operation. + description: Total number of stablecoin operations matching the query. StablecoinProviderAccountStatus: type: string enum: @@ -20219,12 +21306,6 @@ components: - 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 required: diff --git a/openapi/components/schemas/errors/Error503.yaml b/openapi/components/schemas/errors/Error503.yaml new file mode 100644 index 000000000..dd695d51b --- /dev/null +++ b/openapi/components/schemas/errors/Error503.yaml @@ -0,0 +1,26 @@ +type: object +required: + - message + - status + - code +properties: + status: + type: integer + enum: + - 503 + description: HTTP status code + code: + type: string + description: | + | Error Code | Description | + |------------|-------------| + | SERVICE_UNAVAILABLE | Downstream service is temporarily unavailable | + enum: + - SERVICE_UNAVAILABLE + message: + type: string + description: Error message + details: + type: object + description: Additional error details + additionalProperties: true diff --git a/openapi/components/schemas/stablecoins/Stablecoin.yaml b/openapi/components/schemas/stablecoins/Stablecoin.yaml new file mode 100644 index 000000000..c8584d881 --- /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/StablecoinAchDebitFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinAchDebitFundingSource.yaml new file mode 100644 index 000000000..41f143b65 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinAchDebitFundingSource.yaml @@ -0,0 +1,19 @@ +title: ACH Debit +allOf: + - $ref: ./StablecoinMintFundingSourceBase.yaml + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - ACH_DEBIT + description: ACH debit funding. + example: ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` debited to fund the mint. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + description: ACH debit funding source. The provider debits the referenced external account. diff --git a/openapi/components/schemas/stablecoins/StablecoinBurnDestination.yaml b/openapi/components/schemas/stablecoins/StablecoinBurnDestination.yaml new file mode 100644 index 000000000..9fe648759 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinBurnDestination.yaml @@ -0,0 +1,23 @@ +type: object +required: + - type + - externalAccountId + - rail +properties: + type: + type: string + enum: + - EXTERNAL_ACCOUNT + description: Burn destination variant. V1 supports fiat Grid `ExternalAccount` destinations. + externalAccountId: + type: string + description: Grid bank `ExternalAccount` receiving fiat redemption proceeds. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000205 + rail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail for the burn destination. diff --git a/openapi/components/schemas/stablecoins/StablecoinBurnRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinBurnRequest.yaml new file mode 100644 index 000000000..1071ad735 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinBurnRequest.yaml @@ -0,0 +1,20 @@ +type: object +required: + - amount + - source + - destination +properties: + amount: + type: string + pattern: '^[0-9]+$' + description: Amount to burn in the stablecoin's smallest unit. The amount must convert exactly to a whole fiat cent for the token decimals. + example: '1000000' + source: + $ref: StablecoinBurnSource.yaml + destination: + $ref: StablecoinBurnDestination.yaml + description: + type: string + maxLength: 1024 + description: Optional platform-provided operation description. + example: Redeem ACME diff --git a/openapi/components/schemas/stablecoins/StablecoinBurnSource.yaml b/openapi/components/schemas/stablecoins/StablecoinBurnSource.yaml new file mode 100644 index 000000000..be9721452 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinBurnSource.yaml @@ -0,0 +1,10 @@ +oneOf: + - $ref: ./StablecoinExternalAccountBurnSource.yaml + - $ref: ./StablecoinGridInternalBurnSource.yaml + - $ref: ./StablecoinProviderBalanceBurnSource.yaml +discriminator: + propertyName: type + mapping: + EXTERNAL_ACCOUNT: ./StablecoinExternalAccountBurnSource.yaml + GRID_INTERNAL_ACCOUNT: ./StablecoinGridInternalBurnSource.yaml + PROVIDER_INTERNAL_BALANCE: ./StablecoinProviderBalanceBurnSource.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinBurnSourceBase.yaml b/openapi/components/schemas/stablecoins/StablecoinBurnSourceBase.yaml new file mode 100644 index 000000000..cf2123ce1 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinBurnSourceBase.yaml @@ -0,0 +1,12 @@ +type: object +required: + - type +properties: + type: + type: string + enum: + - EXTERNAL_ACCOUNT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Burn source variant. Grid internal account burns are reserved for the Grid-enabled ledger movement flow. + example: EXTERNAL_ACCOUNT diff --git a/openapi/components/schemas/stablecoins/StablecoinEstimatedDelivery.yaml b/openapi/components/schemas/stablecoins/StablecoinEstimatedDelivery.yaml new file mode 100644 index 000000000..774cc0e9c --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinEstimatedDelivery.yaml @@ -0,0 +1,26 @@ +type: object +description: Static rail timing estimate for fiat redemption delivery. This is guidance, not a guaranteed arrival time. +additionalProperties: true +properties: + rail: + type: string + description: Fiat payout rail the estimate applies to. + example: ACH_CREDIT + amount: + type: string + pattern: '^[0-9]+$' + description: Estimated delivery amount in the smallest unit of `currency` (e.g. cents for USD). + example: '100' + currency: + type: string + description: ISO 4217 currency code of the fiat payout. + example: USD + timing: + type: string + description: Human-readable rail timing estimate. + example: 1-3 business days +example: + rail: ACH_CREDIT + amount: '100' + currency: USD + timing: 1-3 business days diff --git a/openapi/components/schemas/stablecoins/StablecoinExternalAccountBurnSource.yaml b/openapi/components/schemas/stablecoins/StablecoinExternalAccountBurnSource.yaml new file mode 100644 index 000000000..96fff4de3 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinExternalAccountBurnSource.yaml @@ -0,0 +1,19 @@ +title: External Account +allOf: + - $ref: ./StablecoinBurnSourceBase.yaml + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - EXTERNAL_ACCOUNT + description: External account burn. References an active Spark external account and returns funding instructions. + example: EXTERNAL_ACCOUNT + externalAccountId: + type: string + description: Grid Spark `ExternalAccount` expected to fund the provider for the burn. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000203 + description: External account burn source. The issuer funds the provider from a Spark external account. diff --git a/openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml b/openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml new file mode 100644 index 000000000..98cf74260 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinFundingInstructions.yaml @@ -0,0 +1,32 @@ +type: object +description: >- + Provider funding instructions safe to show publicly. Present for wire-funded + mint operations and external-source burn operations when available. The common + fields below are always declared; the exact set of remaining fields is + rail- and provider-specific (for example, wire instructions carry bank + beneficiary/account/routing details while Spark and on-chain instructions + carry a deposit address), so `additionalProperties` stays open to pass those + through without a spec change per rail. +additionalProperties: true +properties: + rail: + type: string + description: Funding rail these instructions apply to (e.g. `SPARK`, `WIRE`). + example: SPARK + network: + type: string + description: Network the funds should be sent on, when applicable. + example: SPARK + address: + type: string + description: Deposit address the issuer sends funds to, for on-chain or Spark rails. + example: spark1... + valueType: + type: string + description: Provider token/value type the deposit address expects. + example: ACME +example: + rail: SPARK + network: SPARK + address: spark1... + valueType: ACME diff --git a/openapi/components/schemas/stablecoins/StablecoinGridInternalBurnSource.yaml b/openapi/components/schemas/stablecoins/StablecoinGridInternalBurnSource.yaml new file mode 100644 index 000000000..e98be75c1 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinGridInternalBurnSource.yaml @@ -0,0 +1,19 @@ +title: Grid Internal Account +allOf: + - $ref: ./StablecoinBurnSourceBase.yaml + - type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + description: Grid internal account burn. Reserved for the Grid-controlled ledger movement flow. + example: GRID_INTERNAL_ACCOUNT + accountId: + type: string + description: Grid internal source account id. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000204 + description: Grid internal account burn source, reserved for future Grid-controlled burn flows. diff --git a/openapi/components/schemas/stablecoins/StablecoinGridInternalFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinGridInternalFundingSource.yaml new file mode 100644 index 000000000..aa3d50dbd --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinGridInternalFundingSource.yaml @@ -0,0 +1,19 @@ +title: Grid Internal Account +allOf: + - $ref: ./StablecoinMintFundingSourceBase.yaml + - type: object + required: + - type + - accountId + properties: + type: + type: string + enum: + - GRID_INTERNAL_ACCOUNT + description: Grid internal account funding. Reserved for the follow-up Grid-funded mint flow. + example: GRID_INTERNAL_ACCOUNT + accountId: + type: string + description: Grid internal funding account id. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000102 + description: Grid internal account funding source, reserved for future Grid-funded mint flows. diff --git a/openapi/components/schemas/stablecoins/StablecoinGridOperationsStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinGridOperationsStatus.yaml new file mode 100644 index 000000000..3c8ac4989 --- /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 000000000..fa65ab5b2 --- /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 000000000..c1ebd7b2e --- /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 000000000..970a69891 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinMintDestination.yaml @@ -0,0 +1,18 @@ +type: object +description: >- + Account that receives the minted stablecoin. External and Grid-managed + accounts are represented as a single account reference, matching the + `accountId` pattern used elsewhere in the API; the id prefix + (`ExternalAccount:` or `InternalAccount:`) determines which. In the + initial Brale-backed flow this must reference an active Spark external + account. +required: + - accountId +properties: + accountId: + type: string + description: >- + Grid account receiving the minted stablecoin. Accepts an + `ExternalAccount:` id (initial Brale-backed flow) or an + `InternalAccount:` id for Grid-managed destinations. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000201 diff --git a/openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml new file mode 100644 index 000000000..0b6dc1ec6 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinMintFundingSource.yaml @@ -0,0 +1,14 @@ +oneOf: + - $ref: ./StablecoinWireFundingSource.yaml + - $ref: ./StablecoinAchDebitFundingSource.yaml + - $ref: ./StablecoinSameDayAchDebitFundingSource.yaml + - $ref: ./StablecoinGridInternalFundingSource.yaml + - $ref: ./StablecoinProviderBalanceFundingSource.yaml +discriminator: + propertyName: type + mapping: + WIRE: ./StablecoinWireFundingSource.yaml + ACH_DEBIT: ./StablecoinAchDebitFundingSource.yaml + SAME_DAY_ACH_DEBIT: ./StablecoinSameDayAchDebitFundingSource.yaml + GRID_INTERNAL_ACCOUNT: ./StablecoinGridInternalFundingSource.yaml + PROVIDER_INTERNAL_BALANCE: ./StablecoinProviderBalanceFundingSource.yaml diff --git a/openapi/components/schemas/stablecoins/StablecoinMintFundingSourceBase.yaml b/openapi/components/schemas/stablecoins/StablecoinMintFundingSourceBase.yaml new file mode 100644 index 000000000..09c2ca0e4 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinMintFundingSourceBase.yaml @@ -0,0 +1,14 @@ +type: object +required: + - type +properties: + type: + type: string + enum: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Funding source variant. Grid internal account and provider internal balance funding are reserved for follow-up support. + example: ACH_DEBIT diff --git a/openapi/components/schemas/stablecoins/StablecoinMintRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinMintRequest.yaml new file mode 100644 index 000000000..7979864f0 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinMintRequest.yaml @@ -0,0 +1,20 @@ +type: object +required: + - amount + - fundingSource + - destination +properties: + amount: + type: string + pattern: '^[0-9]+$' + description: Amount to mint in the stablecoin's smallest unit. The amount must convert exactly to a whole fiat cent for the token decimals. + example: '1000000' + fundingSource: + $ref: StablecoinMintFundingSource.yaml + destination: + $ref: StablecoinMintDestination.yaml + description: + type: string + maxLength: 1024 + description: Optional platform-provided operation description. + example: Initial program funding mint diff --git a/openapi/components/schemas/stablecoins/StablecoinNetwork.yaml b/openapi/components/schemas/stablecoins/StablecoinNetwork.yaml new file mode 100644 index 000000000..1f1e01760 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinNetwork.yaml @@ -0,0 +1,4 @@ +type: string +enum: + - SPARK +description: Public network family for the stablecoin token identifier. The concrete Spark network is inferred from the platform mode. diff --git a/openapi/components/schemas/stablecoins/StablecoinOperation.yaml b/openapi/components/schemas/stablecoins/StablecoinOperation.yaml new file mode 100644 index 000000000..068ed5594 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperation.yaml @@ -0,0 +1,72 @@ +type: object +required: + - id + - stablecoinId + - operationType + - status + - amount + - provider + - providerEnvironment + - stablecoinProviderAccountId + - createdAt + - updatedAt +properties: + id: + type: string + description: System-generated stablecoin issuer operation identifier. + example: StablecoinOperation:019542f5-b3e7-1d02-0000-000000000301 + 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: + type: string + description: Operation amount in the stablecoin's smallest unit. + example: '1000000' + provider: + $ref: StablecoinProvider.yaml + providerEnvironment: + $ref: StablecoinProviderEnvironment.yaml + stablecoinProviderAccountId: + type: string + description: Stablecoin provider account link used for the operation. + example: StablecoinProviderAccount:019542f5-b3e7-1d02-0000-000000000001 + source: + $ref: StablecoinOperationSource.yaml + fundingInstructions: + $ref: StablecoinFundingInstructions.yaml + destination: + $ref: StablecoinOperationDestination.yaml + estimatedDelivery: + $ref: StablecoinEstimatedDelivery.yaml + expiresAt: + type: string + format: date-time + description: Expiry for operations awaiting external funding. + example: '2026-05-27T16:40:00Z' + providerStatus: + type: string + description: Sanitized provider status when available. + example: pending + failureReason: + type: string + description: Stable internal failure code for terminal failed operations. + example: PROVIDER_TRANSFER_FAILED + description: + type: string + description: Platform-provided operation description. + example: Initial program funding mint + 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/StablecoinOperationDestination.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationDestination.yaml new file mode 100644 index 000000000..c6fe86c64 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperationDestination.yaml @@ -0,0 +1,27 @@ +type: object +description: >- + Destination of a stablecoin operation, as reported on a + `StablecoinOperation`. A single merged (flat) shape so the field is + unambiguously deserializable regardless of operation type: `accountId` + identifies the receiving account (its `ExternalAccount:` / + `InternalAccount:` prefix disambiguates external vs Grid-managed), and + `rail` is present for burn (fiat payout) destinations and absent for + mint destinations. +required: + - accountId +properties: + accountId: + type: string + description: >- + Grid account that received the funds. An `ExternalAccount:` id for + external destinations or an `InternalAccount:` id for Grid-managed + destinations. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000205 + rail: + type: string + enum: + - WIRE + - ACH_CREDIT + - SAME_DAY_ACH_CREDIT + - RTP_CREDIT + description: Fiat payout rail, present for burn (fiat redemption) destinations. diff --git a/openapi/components/schemas/stablecoins/StablecoinOperationListResponse.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationListResponse.yaml new file mode 100644 index 000000000..5a8277bdd --- /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 query. diff --git a/openapi/components/schemas/stablecoins/StablecoinOperationSource.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationSource.yaml new file mode 100644 index 000000000..3d2edb9a9 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperationSource.yaml @@ -0,0 +1,40 @@ +type: object +description: >- + Source of a stablecoin operation, as reported on a + `StablecoinOperation`. A single merged shape (superset of the + mint funding source and burn source request variants) so the field + is unambiguously deserializable regardless of operation type: + `externalAccountId` is present for external-account funded mints and + external-account burns, `accountId` for Grid internal account + sources, and `sourceTokenIdentifier`/`cryptoNetwork` for provider + internal balance sources. +required: + - type +properties: + type: + type: string + enum: + - WIRE + - ACH_DEBIT + - SAME_DAY_ACH_DEBIT + - EXTERNAL_ACCOUNT + - GRID_INTERNAL_ACCOUNT + - PROVIDER_INTERNAL_BALANCE + description: Source variant. Mint funding uses `WIRE`, `ACH_DEBIT`, or `SAME_DAY_ACH_DEBIT`; burns use `EXTERNAL_ACCOUNT`. `GRID_INTERNAL_ACCOUNT` and `PROVIDER_INTERNAL_BALANCE` are shared across mint and burn. + example: ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` funding the operation, present for ACH debit mints and external-account burns. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + accountId: + type: string + description: Grid internal account id, present for Grid internal account sources. + example: InternalAccount:019542f5-b3e7-1d02-0000-000000000102 + sourceTokenIdentifier: + type: string + description: Provider token/value type, present for provider internal balance sources. + example: USDC + cryptoNetwork: + type: string + description: Source crypto network, present for provider internal balance sources. + example: SOLANA diff --git a/openapi/components/schemas/stablecoins/StablecoinOperationStatus.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationStatus.yaml new file mode 100644 index 000000000..e4b2e803a --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinOperationStatus.yaml @@ -0,0 +1,10 @@ +type: string +enum: + - CREATED + - PENDING_FUNDING + - PENDING_PROVIDER + - PROCESSING + - COMPLETED + - FAILED + - EXPIRED +description: Stablecoin issuer operation lifecycle status. diff --git a/openapi/components/schemas/stablecoins/StablecoinOperationType.yaml b/openapi/components/schemas/stablecoins/StablecoinOperationType.yaml new file mode 100644 index 000000000..e8f0072ee --- /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/StablecoinProviderBalanceBurnSource.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderBalanceBurnSource.yaml new file mode 100644 index 000000000..f3e7cd1a3 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderBalanceBurnSource.yaml @@ -0,0 +1,14 @@ +title: Provider Internal Balance +allOf: + - $ref: ./StablecoinBurnSourceBase.yaml + - type: object + required: + - type + properties: + type: + type: string + enum: + - PROVIDER_INTERNAL_BALANCE + description: Provider internal balance burn. Spends stablecoin funds already held at the provider. + example: PROVIDER_INTERNAL_BALANCE + description: Provider internal balance burn source. No external funding is required; the provider spends existing balance. diff --git a/openapi/components/schemas/stablecoins/StablecoinProviderBalanceFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinProviderBalanceFundingSource.yaml new file mode 100644 index 000000000..458608c27 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinProviderBalanceFundingSource.yaml @@ -0,0 +1,24 @@ +title: Provider Internal Balance +allOf: + - $ref: ./StablecoinMintFundingSourceBase.yaml + - type: object + required: + - type + - sourceTokenIdentifier + - cryptoNetwork + properties: + type: + type: string + enum: + - PROVIDER_INTERNAL_BALANCE + description: Provider internal balance funding. Reserved for the follow-up provider-balance mint flow. + example: PROVIDER_INTERNAL_BALANCE + sourceTokenIdentifier: + type: string + description: Provider token/value type spent from the provider internal balance. + example: USDC + cryptoNetwork: + type: string + description: Source crypto network for the provider internal balance funds. + example: SOLANA + description: Provider internal balance funding source, reserved for future provider-funded mint flows. diff --git a/openapi/components/schemas/stablecoins/StablecoinRegisterRequest.yaml b/openapi/components/schemas/stablecoins/StablecoinRegisterRequest.yaml new file mode 100644 index 000000000..fc2b4e62b --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinRegisterRequest.yaml @@ -0,0 +1,20 @@ +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/StablecoinSameDayAchDebitFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinSameDayAchDebitFundingSource.yaml new file mode 100644 index 000000000..2a3e1c470 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinSameDayAchDebitFundingSource.yaml @@ -0,0 +1,19 @@ +title: Same-Day ACH Debit +allOf: + - $ref: ./StablecoinMintFundingSourceBase.yaml + - type: object + required: + - type + - externalAccountId + properties: + type: + type: string + enum: + - SAME_DAY_ACH_DEBIT + description: Same-day ACH debit funding. + example: SAME_DAY_ACH_DEBIT + externalAccountId: + type: string + description: Grid `ExternalAccount` debited to fund the mint. + example: ExternalAccount:019542f5-b3e7-1d02-0000-000000000101 + description: Same-day ACH debit funding source. The provider debits the referenced external account. diff --git a/openapi/components/schemas/stablecoins/StablecoinWireFundingSource.yaml b/openapi/components/schemas/stablecoins/StablecoinWireFundingSource.yaml new file mode 100644 index 000000000..752f33788 --- /dev/null +++ b/openapi/components/schemas/stablecoins/StablecoinWireFundingSource.yaml @@ -0,0 +1,14 @@ +title: Wire +allOf: + - $ref: ./StablecoinMintFundingSourceBase.yaml + - type: object + required: + - type + properties: + type: + type: string + enum: + - WIRE + description: Wire-funded mint. Funding instructions are returned on the resulting operation. + example: WIRE + description: Wire funding source. The issuer wires fiat to the provider using the returned funding instructions. diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 39ada2584..a56ed33d4 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -85,8 +85,8 @@ tags: - name: Stablecoins description: >- Stablecoin issuance endpoints. Link provider accounts, register - provider-created stablecoins, create mint/burn quotes, execute them, and - track the resulting operations. + provider-created stablecoins, create direct mint/burn issuer operations, + and track operation status. servers: - url: https://api.lightspark.com/grid/2025-10-13 description: Production server @@ -304,6 +304,18 @@ 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 + /stablecoins: + $ref: paths/stablecoins/stablecoins.yaml + /stablecoins/{stablecoinId}: + $ref: paths/stablecoins/stablecoins_{stablecoinId}.yaml + /stablecoins/{stablecoinId}/mints: + $ref: paths/stablecoins/stablecoins_{stablecoinId}_mints.yaml + /stablecoins/{stablecoinId}/burns: + $ref: paths/stablecoins/stablecoins_{stablecoinId}_burns.yaml + /stablecoins/{stablecoinId}/operations: + $ref: paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml + /stablecoin-operations/{stablecoinOperationId}: + $ref: paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml /stablecoin-provider-accounts: $ref: paths/stablecoins/stablecoin-provider-accounts.yaml /stablecoin-provider-accounts/{stablecoinProviderAccountId}: diff --git a/openapi/paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml b/openapi/paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml new file mode 100644 index 000000000..61ca1eaac --- /dev/null +++ b/openapi/paths/stablecoins/stablecoin-operations_{stablecoinOperationId}.yaml @@ -0,0 +1,40 @@ +parameters: + - name: stablecoinOperationId + in: path + description: System-generated stablecoin issuer operation identifier + required: true + schema: + type: string +get: + summary: Get a stablecoin issuer operation + description: Retrieve a single stablecoin issuer operation by its Grid identifier. + 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/stablecoins.yaml b/openapi/paths/stablecoins/stablecoins.yaml new file mode 100644 index 000000000..d0b393760 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins.yaml @@ -0,0 +1,124 @@ +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: Required idempotency key for retrying this request safely. + 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: Opaque cursor returned as `nextCursor` from the previous response. + 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 000000000..ad950e02c --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}.yaml @@ -0,0 +1,40 @@ +parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +get: + summary: Get a stablecoin + description: Retrieve a single registered stablecoin by its Grid identifier. + 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}_burns.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_burns.yaml new file mode 100644 index 000000000..a42795717 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_burns.yaml @@ -0,0 +1,73 @@ +parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +post: + summary: Create a stablecoin burn operation + description: | + Create a provider-backed burn/redemption operation for a registered stablecoin. Burn sources and fiat destinations are normal Grid account objects; provider-specific Brale address ids are resolved and stored internally. External Spark wallet sources return funding instructions and remain pending until the provider reports funds received. + operationId: createStablecoinBurn + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Required idempotency key for retrying this burn request safely. + required: true + schema: + type: string + maxLength: 255 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinBurnRequest.yaml + responses: + '201': + description: Burn 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 referenced 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 + '503': + description: Provider temporarily unavailable + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error503.yaml diff --git a/openapi/paths/stablecoins/stablecoins_{stablecoinId}_mints.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_mints.yaml new file mode 100644 index 000000000..cd6dc20eb --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_mints.yaml @@ -0,0 +1,73 @@ +parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +post: + summary: Create a stablecoin mint operation + description: | + Create a provider-backed mint operation for a registered stablecoin. Funding and destination accounts are normal Grid `ExternalAccount` objects; any provider-specific Brale address linkage is managed internally by Grid. Wire-funded mints return funding instructions and remain pending until the provider reports funds received. + operationId: createStablecoinMint + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: Idempotency-Key + in: header + description: Required idempotency key for retrying this mint request safely. + required: true + schema: + type: string + maxLength: 255 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinMintRequest.yaml + responses: + '201': + description: Mint 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 referenced 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 + '503': + description: Provider temporarily unavailable + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error503.yaml diff --git a/openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml new file mode 100644 index 000000000..18dd93307 --- /dev/null +++ b/openapi/paths/stablecoins/stablecoins_{stablecoinId}_operations.yaml @@ -0,0 +1,62 @@ +parameters: + - name: stablecoinId + in: path + description: System-generated stablecoin identifier + required: true + schema: + type: string +get: + summary: List stablecoin issuer operations + description: List issuer mint and burn operations for a stablecoin, most recent first, with cursor pagination. + operationId: listStablecoinOperations + tags: + - Stablecoins + security: + - BasicAuth: [] + parameters: + - name: operationType + in: query + description: Filter operations by type. When omitted, both mints and burns are returned. + required: false + schema: + $ref: ../../components/schemas/stablecoins/StablecoinOperationType.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: Opaque cursor returned as `nextCursor` from the previous response. + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/stablecoins/StablecoinOperationListResponse.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