From 692891a29325befd0ee88da0373d091f9fdc0615 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 30 Apr 2026 22:03:28 -0700 Subject: [PATCH 01/12] feat(agents): add Agents (experimental) to Grid API spec Introduces two new tag groups: - Agent Management: platform-scoped CRUD, policy, device codes, approvals (BasicAuth) - Agent Operations: agent-scoped payments, quotes, transfers, external accounts (AgentAuth) New schemas (18): Agent, AgentCreateRequest/Response, AgentUpdateRequest, AgentListResponse, AgentPolicy, AgentPolicyUpdateRequest, AgentPermission, AgentExecutionMode, AgentSpendingLimits/Update, AgentApprovalThresholds, AgentAccountRestrictions/Rule, AgentUsage, AgentDeviceCode, AgentDeviceCodeStatusResponse, AgentDeviceCodeRedeemResponse New endpoints (19): - POST/GET /agents, GET /agents/approvals - GET/PATCH/DELETE /agents/{agentId}, PATCH /agents/{agentId}/policy - POST /agents/{agentId}/device-codes (regenerate) - GET /agents/device-codes/{code}/status, POST .../redeem - POST /agents/{agentId}/transactions/{transactionId}/approve|reject - GET /agents/me, GET/POST /agents/me/transactions, /quotes, /external-accounts - POST /agents/me/transfer-in|out, /quotes/{quoteId}/execute Also: adds agentId to Transaction schema; updates approvals-and-audit.mdx and policies-and-permissions.mdx to match spec field names and shapes; adds sidebar icons for both groups in style.css --- .../agents/approvals-and-audit.mdx | 51 +- .../agents/policies-and-permissions.mdx | 46 +- mintlify/openapi.yaml | 1748 +++++++++++++++++ mintlify/style.css | 12 + openapi.yaml | 1748 +++++++++++++++++ openapi/components/schemas/agents/Agent.yaml | 47 + .../agents/AgentAccountRestrictions.yaml | 18 + .../schemas/agents/AgentAccountRule.yaml | 17 + .../agents/AgentApprovalThresholds.yaml | 12 + .../schemas/agents/AgentCreateRequest.yaml | 16 + .../schemas/agents/AgentCreateResponse.yaml | 10 + .../schemas/agents/AgentDeviceCode.yaml | 24 + .../agents/AgentDeviceCodeRedeemResponse.yaml | 30 + .../agents/AgentDeviceCodeStatusResponse.yaml | 13 + .../schemas/agents/AgentExecutionMode.yaml | 8 + .../schemas/agents/AgentListResponse.yaml | 19 + .../schemas/agents/AgentPermission.yaml | 14 + .../schemas/agents/AgentPolicy.yaml | 20 + .../agents/AgentPolicyUpdateRequest.yaml | 18 + .../schemas/agents/AgentSpendingLimits.yaml | 25 + .../agents/AgentSpendingLimitsUpdate.yaml | 23 + .../schemas/agents/AgentUpdateRequest.yaml | 11 + .../components/schemas/agents/AgentUsage.yaml | 28 + .../schemas/transactions/Transaction.yaml | 6 + openapi/openapi.yaml | 62 + openapi/paths/agents/agents.yaml | 136 ++ openapi/paths/agents/agents_approvals.yaml | 90 + .../agents_device-codes_{code}_redeem.yaml | 46 + .../agents_device-codes_{code}_status.yaml | 42 + openapi/paths/agents/agents_me.yaml | 30 + .../agents/agents_me_external-accounts.yaml | 136 ++ ...external-accounts_{externalAccountId}.yaml | 74 + openapi/paths/agents/agents_me_quotes.yaml | 74 + .../agents/agents_me_quotes_{quoteId}.yaml | 42 + .../agents_me_quotes_{quoteId}_execute.yaml | 94 + .../paths/agents/agents_me_transactions.yaml | 112 ++ ...gents_me_transactions_{transactionId}.yaml | 42 + .../paths/agents/agents_me_transfer-in.yaml | 81 + .../paths/agents/agents_me_transfer-out.yaml | 77 + openapi/paths/agents/agents_{agentId}.yaml | 114 ++ .../agents/agents_{agentId}_device-codes.yaml | 56 + .../paths/agents/agents_{agentId}_policy.yaml | 54 + ..._transactions_{transactionId}_approve.yaml | 71 + ...}_transactions_{transactionId}_reject.yaml | 71 + 44 files changed, 5410 insertions(+), 58 deletions(-) create mode 100644 openapi/components/schemas/agents/Agent.yaml create mode 100644 openapi/components/schemas/agents/AgentAccountRestrictions.yaml create mode 100644 openapi/components/schemas/agents/AgentAccountRule.yaml create mode 100644 openapi/components/schemas/agents/AgentApprovalThresholds.yaml create mode 100644 openapi/components/schemas/agents/AgentCreateRequest.yaml create mode 100644 openapi/components/schemas/agents/AgentCreateResponse.yaml create mode 100644 openapi/components/schemas/agents/AgentDeviceCode.yaml create mode 100644 openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml create mode 100644 openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml create mode 100644 openapi/components/schemas/agents/AgentExecutionMode.yaml create mode 100644 openapi/components/schemas/agents/AgentListResponse.yaml create mode 100644 openapi/components/schemas/agents/AgentPermission.yaml create mode 100644 openapi/components/schemas/agents/AgentPolicy.yaml create mode 100644 openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml create mode 100644 openapi/components/schemas/agents/AgentSpendingLimits.yaml create mode 100644 openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml create mode 100644 openapi/components/schemas/agents/AgentUpdateRequest.yaml create mode 100644 openapi/components/schemas/agents/AgentUsage.yaml create mode 100644 openapi/paths/agents/agents.yaml create mode 100644 openapi/paths/agents/agents_approvals.yaml create mode 100644 openapi/paths/agents/agents_device-codes_{code}_redeem.yaml create mode 100644 openapi/paths/agents/agents_device-codes_{code}_status.yaml create mode 100644 openapi/paths/agents/agents_me.yaml create mode 100644 openapi/paths/agents/agents_me_external-accounts.yaml create mode 100644 openapi/paths/agents/agents_me_external-accounts_{externalAccountId}.yaml create mode 100644 openapi/paths/agents/agents_me_quotes.yaml create mode 100644 openapi/paths/agents/agents_me_quotes_{quoteId}.yaml create mode 100644 openapi/paths/agents/agents_me_quotes_{quoteId}_execute.yaml create mode 100644 openapi/paths/agents/agents_me_transactions.yaml create mode 100644 openapi/paths/agents/agents_me_transactions_{transactionId}.yaml create mode 100644 openapi/paths/agents/agents_me_transfer-in.yaml create mode 100644 openapi/paths/agents/agents_me_transfer-out.yaml create mode 100644 openapi/paths/agents/agents_{agentId}.yaml create mode 100644 openapi/paths/agents/agents_{agentId}_device-codes.yaml create mode 100644 openapi/paths/agents/agents_{agentId}_policy.yaml create mode 100644 openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml create mode 100644 openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml diff --git a/mintlify/global-accounts/agents/approvals-and-audit.mdx b/mintlify/global-accounts/agents/approvals-and-audit.mdx index d3765d9d..a9d520d3 100644 --- a/mintlify/global-accounts/agents/approvals-and-audit.mdx +++ b/mintlify/global-accounts/agents/approvals-and-audit.mdx @@ -43,47 +43,34 @@ An approval in your UI is not always a guarantee that the original request will ## Activity and audit records -The activity and audit data returned by Grid makes it easy for customers and operators to understand both intent and outcome. +Pending approval requests are transactions with a `PENDING` status, returned by `GET /agents/approvals`. Each record includes: -Each activity record captures: +- `id` — transaction identifier +- `agentId` — the agent that initiated the action +- `customerId` / `platformCustomerId` — the customer on whose behalf the agent acted +- `status` — `PENDING` while awaiting approval; updated to `COMPLETED`, `REJECTED`, or `FAILED` after the decision is processed +- `type` — transaction type (e.g. outgoing payment, cross-currency transfer) +- `destination` — destination account or UMA address +- `description` — optional memo set by the agent +- `createdAt` / `updatedAt` — timestamps for the request lifecycle -- Agent ID and display name -- Action type -- Requested amount and asset -- Source and destination context -- Reason or natural-language detail -- Policy decision -- Approval status -- Linked Grid quote ID or transaction ID, when available -- Created, approved, rejected, and completed timestamps - -For example, a permission request surfaced in your product might look like: +For example, a pending approval request surfaced in your product might look like: ```json { - "id": "Approval:019542f5-b3e7-1d02-0000-000000000099", - "agentId": "Agent:019542f5-b3e7-1d02-0000-000000000042", + "id": "Transaction:019542f5-b3e7-1d02-0000-000000000099", "status": "PENDING", - "actionType": "EXECUTE_QUOTE", - "quoteId": "Quote:019542f5-b3e7-1d02-0000-000000000025", - "source": { - "accountId": "InternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965", - "currency": "USD" - }, + "type": "OUTGOING_PAYMENT", + "agentId": "Agent:019542f5-b3e7-1d02-0000-000000000042", + "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000010", + "platformCustomerId": "user-a1b2c3", "destination": { - "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123", - "currency": "EUR" - }, - "sendingAmount": { - "amount": 50000, - "currency": { - "code": "USD", - "decimals": 2 - } + "type": "EXTERNAL_ACCOUNT", + "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" }, "description": "Send supplier payout", - "policyDecision": "APPROVAL_REQUIRED", - "createdAt": "2025-10-03T15:00:00Z" + "createdAt": "2025-10-03T15:00:00Z", + "updatedAt": "2025-10-03T15:00:00Z" } ``` diff --git a/mintlify/global-accounts/agents/policies-and-permissions.mdx b/mintlify/global-accounts/agents/policies-and-permissions.mdx index ff9d643a..6d57ec09 100644 --- a/mintlify/global-accounts/agents/policies-and-permissions.mdx +++ b/mintlify/global-accounts/agents/policies-and-permissions.mdx @@ -32,14 +32,15 @@ An agent policy should answer four questions: ## Permissions -Grid exposes explicit allowlists instead of broad agent access. Common permissions include: +Grid exposes explicit allowlists instead of broad agent access. Available permissions are: -- View balances and account details -- View transaction history -- Create external accounts -- Create quotes -- Execute withdrawals or quote-backed transfers -- Fund or move value between allowed accounts +| Permission | What it allows | +|---|---| +| `VIEW_TRANSACTIONS` | List and retrieve transactions and account balances | +| `CREATE_TRANSFERS` | Initiate same-currency transfers | +| `CREATE_QUOTES` | Create cross-currency quotes | +| `EXECUTE_QUOTES` | Execute cross-currency quotes | +| `MANAGE_EXTERNAL_ACCOUNTS` | Create and manage external accounts | These permissions are intentionally narrow and map to concrete Grid-backed actions rather than broad scopes such as "manage wallet." @@ -72,8 +73,8 @@ Keep limits in the smallest currency unit used by Grid so comparisons are exact Each action should resolve to one of two execution modes: -- `auto`: Grid may execute the action immediately after policy validation. -- `approval_required`: Grid creates a pending approval and dispatches it to your product for customer confirmation. +- `AUTO`: Grid may execute the action immediately after policy validation. +- `APPROVAL_REQUIRED`: Grid creates a pending approval and dispatches it to your product for customer confirmation. You can apply execution mode globally or per account. A practical pattern is to allow automatic execution for low-risk actions and require approvals for higher-value withdrawals or new destination setup. @@ -106,22 +107,16 @@ For example, Grid stores and enforces a policy object shaped like: ```json { "permissions": [ - "view_balances", - "view_transactions", - "create_external_accounts", - "execute_withdrawals" + "VIEW_TRANSACTIONS", + "CREATE_QUOTES", + "EXECUTE_QUOTES", + "MANAGE_EXTERNAL_ACCOUNTS" ], - "defaultExecutionMode": "approval_required", + "defaultExecutionMode": "APPROVAL_REQUIRED", "spendingLimits": { - "perTransaction": { - "amount": 50000, - "currency": "USD" - }, - "daily": { - "amount": 200000, - "currency": "USD" - }, - "dailyTransactionCount": 5 + "perTransactionLimit": 50000, + "dailyLimit": 200000, + "dailyTransactionLimit": 5 }, "accountRestrictions": { "allowedAccountIds": [ @@ -129,14 +124,13 @@ For example, Grid stores and enforces a policy object shaped like: ] }, "approvalThresholds": { - "amount": 25000, - "currency": "USD" + "amount": 25000 } } ``` -Policy amounts use the smallest unit of the specified currency. For example, `50000` with `"currency": "USD"` means $500.00. If Grid compares across currencies or assets, it uses the current exchange rate at evaluation time. +Policy amounts are integers in the smallest unit of the relevant currency. Grid infers the currency from the account or transaction context — no currency field is needed in the policy itself. For example, `50000` in a USD context means $500.00. ## Practical guidance diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index eca20ec0..1bc14f05 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -48,6 +48,10 @@ tags: description: Endpoints for discovering available payment rails, banks, and providers for a given country and currency corridor. - name: Embedded Wallet Auth description: Endpoints for registering and verifying end-user authentication credentials (email OTP, OAuth, passkey) used to sign Embedded Wallet actions. + - name: Agent Management + description: 'Endpoints for creating and managing agents (experimental), called by the partner''s backend using platform credentials. Covers the full agent lifecycle: creation, policy configuration, pausing, deletion, the device code installation flow, and approving or rejecting transactions initiated by agents.' + - name: Agent Operations + description: Endpoints called by the agent itself using its own credentials (obtained via device code redemption). Scoped to the agent's associated customer — all requests automatically operate on behalf of that customer and are subject to the agent's policy. When an action requires approval, the resulting transaction enters a pending state and must be approved by the platform via `POST /transactions/{transactionId}/approve`. paths: /config: get: @@ -4319,6 +4323,1391 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /agents: + post: + summary: Create an agent + description: | + Create a new agent with a specified policy. Returns the created agent and a device code that must be redeemed by the agent software to complete installation. + operationId: createAgent + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentCreateRequest' + responses: + '201': + description: Agent created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AgentCreateResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List agents + description: Retrieve a paginated list of agents for the authenticated platform. + operationId: listAgents + tags: + - Agent Management + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: Filter by customer ID + required: false + schema: + type: string + - name: isPaused + in: query + description: Filter by paused status + required: false + schema: + type: boolean + - name: isConnected + in: query + description: Filter by connection status (whether the device code has been redeemed) + required: false + schema: + type: boolean + - name: createdAfter + in: query + description: Filter agents created after this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: createdBefore + in: query + description: Filter agents created before this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: updatedAfter + in: query + description: Filter agents updated after this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: updatedBefore + in: query + description: Filter agents updated before this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/approvals: + get: + summary: List agent transaction approval requests + description: | + Retrieve a paginated list of transactions initiated by agents that require platform approval. Filter by `agentId` or `customerId` to scope results to a specific agent or customer. Approve or reject individual transactions via `POST /agents/{agentId}/transactions/{transactionId}/approve` or `POST /agents/{agentId}/transactions/{transactionId}/reject`. + operationId: listAgentApprovals + tags: + - Agent Management + security: + - BasicAuth: [] + parameters: + - name: agentId + in: query + description: Filter by agent ID + required: false + schema: + type: string + - name: customerId + in: query + description: Filter by customer ID + required: false + schema: + type: string + - name: startDate + in: query + description: Filter by start date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - name: endDate + in: query + description: Filter by end date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - 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 + - name: sortOrder + in: query + description: Order to sort results in + required: false + schema: + type: string + enum: + - asc + - desc + default: desc + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me: + get: + summary: Get current agent + description: | + Retrieve the authenticated agent's own profile, policy, and current usage. This endpoint is called by the agent software itself using its own credentials (obtained via device code redemption) rather than platform credentials. + operationId: getAgentMe + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + get: + summary: Get agent by ID + description: Retrieve an agent by its system-generated ID. + operationId: getAgentById + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + patch: + summary: Update agent + description: Update an agent's name or paused state. + operationId: updateAgent + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentUpdateRequest' + responses: + '200': + description: Agent updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + delete: + summary: Delete agent + description: Permanently delete an agent. Connected agent software will lose access immediately. + operationId: deleteAgent + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '204': + description: Agent deleted successfully + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/policy: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + patch: + summary: Update agent policy + description: | + Partially update an agent's policy. Only provided fields will be updated; omitted fields retain their current values. Policy changes take effect immediately. + operationId: updateAgentPolicy + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPolicyUpdateRequest' + responses: + '200': + description: Agent policy updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/device-codes: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + post: + summary: Regenerate a device code + description: | + Generate a new device code for an existing agent. Use this when the original device code has expired before being redeemed, or when the agent software needs to be reinstalled. Any previously issued unredeemed device codes for this agent are invalidated. + operationId: regenerateAgentDeviceCode + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '201': + description: New device code generated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AgentDeviceCode' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Agent already has an active connection and cannot regenerate a device code + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/transactions/{transactionId}/approve: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + - name: transactionId + in: path + description: Unique identifier of the transaction to approve + required: true + schema: + type: string + post: + summary: Approve an agent-initiated transaction + description: | + Approve a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + This endpoint is called by the platform's backend using platform credentials, not by the agent itself. + operationId: approveAgentTransaction + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/ApprovePaymentRequest' + responses: + '200': + description: Transaction approved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Transaction cannot be approved + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent or transaction not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Transaction is not pending approval or has already been processed + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/transactions/{transactionId}/reject: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + - name: transactionId + in: path + description: Unique identifier of the transaction to reject + required: true + schema: + type: string + post: + summary: Reject an agent-initiated transaction + description: | + Reject a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + This endpoint is called by the platform's backend using platform credentials, not by the agent itself. + operationId: rejectAgentTransaction + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/RejectPaymentRequest' + responses: + '200': + description: Transaction rejected successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Transaction cannot be rejected + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent or transaction not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Transaction is not pending approval or has already been processed + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/device-codes/{code}/status: + parameters: + - name: code + in: path + description: The device code to check + required: true + schema: + type: string + get: + summary: Get device code status + description: | + Check whether a device code has been redeemed. Use this to poll for agent installation completion after creating an agent. + operationId: getAgentDeviceCodeStatus + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentDeviceCodeStatusResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Device code not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/device-codes/{code}/redeem: + parameters: + - name: code + in: path + description: The device code to redeem + required: true + schema: + type: string + post: + summary: Redeem device code + description: | + Redeem a device code to obtain agent credentials. This endpoint is called by the agent software during installation. On success, returns a clientId and clientSecret that the agent uses for all subsequent API calls. The secret is returned only once and must be stored securely. + This endpoint does not require platform authentication — the device code itself serves as proof of authorization. + operationId: redeemAgentDeviceCode + tags: + - Agent Management + security: [] + responses: + '200': + description: Device code redeemed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AgentDeviceCodeRedeemResponse' + '400': + description: Bad request (e.g., code already redeemed or expired) + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '404': + description: Device code not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transactions: + get: + summary: List agent transactions + description: | + Retrieve a paginated list of transactions for the authenticated agent's customer. Results are automatically scoped to the agent's associated customer — no customer filter is needed or accepted. + operationId: agentListTransactions + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: accountIdentifier + in: query + description: Filter by account identifier (matches either sender or receiver) + required: false + schema: + type: string + - name: senderAccountIdentifier + in: query + description: Filter by sender account identifier + required: false + schema: + type: string + - name: receiverAccountIdentifier + in: query + description: Filter by receiver account identifier + required: false + schema: + type: string + - name: status + in: query + description: Filter by transaction status + required: false + schema: + $ref: '#/components/schemas/TransactionStatus' + - name: type + in: query + description: Filter by transaction type + required: false + schema: + $ref: '#/components/schemas/TransactionType' + - name: reference + in: query + description: Filter by reference + required: false + schema: + type: string + - name: startDate + in: query + description: Filter by start date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - name: endDate + in: query + description: Filter by end date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - 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 + - name: sortOrder + in: query + description: Order to sort results in + required: false + schema: + type: string + enum: + - asc + - desc + default: desc + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transactions/{transactionId}: + parameters: + - name: transactionId + in: path + description: Unique identifier of the transaction + required: true + schema: + type: string + get: + summary: Get agent transaction by ID + description: | + Retrieve a specific transaction belonging to the authenticated agent's customer. Returns 404 if the transaction exists but belongs to a different customer. + operationId: agentGetTransaction + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Transaction not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/quotes: + post: + summary: Create a transfer quote + description: | + Generate a quote for a cross-currency transfer on behalf of the authenticated agent's customer. Accounts referenced in the request must belong to the agent's customer. Requires the CREATE_QUOTES permission in the agent's policy. + If the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the quote amount exceeds the agent's approvalThresholds, the resulting transaction will require explicit approval before funds move. + operationId: agentCreateQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/QuoteRequest' + responses: + '201': + description: Transfer quote created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Quote' + '400': + description: Bad request - Missing or invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '412': + description: Counterparty doesn't support UMA version + content: + application/json: + schema: + $ref: '#/components/schemas/Error412' + '424': + description: Counterparty issue + content: + application/json: + schema: + $ref: '#/components/schemas/Error424' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/quotes/{quoteId}: + parameters: + - name: quoteId + in: path + description: ID of the quote to retrieve + required: true + schema: + type: string + get: + summary: Get agent quote by ID + description: | + Retrieve a quote created by the authenticated agent. Returns 404 if the quote exists but was not created by this agent. + operationId: agentGetQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Quote retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Quote' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/quotes/{quoteId}/execute: + parameters: + - name: quoteId + in: path + required: true + description: The unique identifier of the quote to execute + schema: + type: string + example: Quote:019542f5-b3e7-1d02-0000-000000000001 + post: + summary: Execute a quote + description: | + Execute a quote created by the authenticated agent. Requires the EXECUTE_QUOTES permission in the agent's policy. + If the agent's policy requires approval for this amount (based on execution mode or approval thresholds), the transaction will be created in a pending state and must be approved by the platform via `POST /agents/{agentId}/transactions/{transactionId}/approve`. + Once executed, the quote cannot be cancelled. + operationId: agentExecuteQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: + - name: Grid-Wallet-Signature + in: header + required: false + description: Signature over the `payloadToSign` returned in the quote's `paymentInstructions[].accountOrWalletInfo` entry, produced with the session private key of a verified authentication credential on the source Embedded Wallet and base64-encoded. Required when the quote's source is an internal account of type `EMBEDDED_WALLET`; ignored for other source types. + schema: + type: string + example: MEUCIQDx7k2N0aK4p8f3vR9J6yT5wL1mB0sXnG2hQ4vJ8zYkCgIgZ4rP9dT7eWfU3oM6KjR1qSpNvBwL0tXyA2iG8fH5dE= + responses: + '200': + description: Quote executed successfully. Transfer has been initiated. + content: + application/json: + schema: + $ref: '#/components/schemas/Quote' + '400': + description: Bad request - Quote cannot be executed + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized. Also returned when the quote's source is an internal account of type `EMBEDDED_WALLET` and the provided `Grid-Wallet-Signature` header is missing, malformed, or does not match the quote's `payloadToSign`. + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '404': + description: Quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Quote already executed, expired, or in invalid state + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transfer-in: + post: + summary: Create a transfer-in + description: | + Transfer funds from an external account to an internal account for the authenticated agent's customer. Accounts must belong to the agent's customer. Requires the CREATE_TRANSFERS permission in the agent's policy. + If the agent's policy requires approval for this amount, the transaction will be created in a pending state and must be approved by the platform via `POST /agents/{agentId}/transactions/{transactionId}/approve`. + This endpoint should only be used for external account sources with pull functionality (e.g. ACH Pull). Otherwise, use the payment instructions on the internal account to deposit funds. + operationId: agentCreateTransferIn + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: 550e8400-e29b-41d4-a716-446655440000 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TransferInRequest' + examples: + transferIn: + summary: Transfer from external to internal account + value: + source: + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + amount: 12550 + responses: + '201': + description: Transfer-in created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '404': + description: Account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transfer-out: + post: + summary: Create a transfer-out + description: | + Transfer funds from an internal account to an external account for the authenticated agent's customer. Accounts must belong to the agent's customer. Requires the CREATE_TRANSFERS permission in the agent's policy. + If the agent's policy requires approval for this amount, the transaction will be created in a pending state and must be approved by the platform via `POST /agents/{agentId}/transactions/{transactionId}/approve`. + operationId: agentCreateTransferOut + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: 550e8400-e29b-41d4-a716-446655440000 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TransferOutRequest' + examples: + transferOut: + summary: Transfer from internal to external account + value: + source: + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + amount: 12550 + responses: + '201': + description: Transfer-out created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '404': + description: Account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/external-accounts: + get: + summary: List agent external accounts + description: | + Retrieve a paginated list of external accounts belonging to the authenticated agent's customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentListExternalAccounts + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: currency + in: query + description: Filter by currency code + required: false + schema: + type: string + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccountListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + post: + summary: Add an external account + description: | + Register a new external bank account or wallet for the authenticated agent's customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. The `customerId` field is optional and will be inferred from the agent's associated customer if omitted. + operationId: agentCreateExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccountCreateRequest' + examples: + usBankAccount: + summary: Create external US bank account + value: + currency: USD + accountInfo: + accountType: USD_ACCOUNT + accountNumber: '12345678901' + routingNumber: '123456789' + bankAccountType: CHECKING + bankName: Chase Bank + beneficiary: + beneficiaryType: INDIVIDUAL + fullName: John Doe + birthDate: '1990-01-15' + nationality: US + address: + line1: 123 Main Street + city: San Francisco + state: CA + postalCode: '94105' + country: US + sparkWallet: + summary: Create external Spark wallet + value: + currency: BTC + accountInfo: + accountType: SPARK_WALLET + address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu + responses: + '201': + description: External account created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccount' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - External account already exists + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/external-accounts/{externalAccountId}: + parameters: + - name: externalAccountId + in: path + description: System-generated unique external account identifier + required: true + schema: + type: string + get: + summary: Get agent external account by ID + description: | + Retrieve an external account belonging to the authenticated agent's customer. Returns 404 if the account exists but belongs to a different customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentGetExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccount' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: External account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + delete: + summary: Delete agent external account + description: | + Delete an external account belonging to the authenticated agent's customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentDeleteExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '204': + description: External account deleted successfully + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: External account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' webhooks: incoming-payment: post: @@ -5136,6 +6525,10 @@ components: type: http scheme: basic description: API token authentication using format `:` + AgentAuth: + type: http + scheme: basic + description: 'Agent authentication using format `:`, where the credentials are obtained by 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 @@ -12373,6 +13766,10 @@ components: format: date-time description: When the transaction was last updated example: '2025-08-15T14:30:00Z' + agentId: + type: string + description: If this transaction was initiated by an agent, the system-generated ID of that agent. Absent for platform-initiated transactions. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 description: type: string description: Optional memo or description for the payment @@ -14199,6 +15596,357 @@ components: description: List of active authentication sessions for the internal account. items: $ref: '#/components/schemas/AuthSession' + AgentPermission: + type: string + enum: + - VIEW_TRANSACTIONS + - CREATE_TRANSFERS + - CREATE_QUOTES + - EXECUTE_QUOTES + - MANAGE_EXTERNAL_ACCOUNTS + description: 'Permission granted to an agent that determines what actions it can perform. VIEW_TRANSACTIONS: Can list and retrieve transactions and account balances. CREATE_TRANSFERS: Can initiate same-currency transfers. CREATE_QUOTES: Can create cross-currency quotes. EXECUTE_QUOTES: Can execute cross-currency quotes. MANAGE_EXTERNAL_ACCOUNTS: Can create and manage external accounts.' + AgentExecutionMode: + type: string + enum: + - AUTO + - APPROVAL_REQUIRED + description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' + AgentSpendingLimits: + type: object + description: Spending limits that cap the agent's transaction amounts and frequency. + required: + - perTransactionLimit + properties: + perTransactionLimit: + type: integer + description: Maximum amount the agent can transfer in a single transaction, in the smallest unit of the relevant currency. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per day, in the smallest unit of the relevant currency. Null means no daily limit. + example: 500000 + dailyTransactionLimit: + type: integer + description: Maximum number of transactions the agent can initiate per day. + example: 10 + monthlyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per month, in the smallest unit of the relevant currency. Null means no monthly limit. + example: 5000000 + AgentAccountRule: + type: object + description: Per-account policy override that takes precedence over the agent's default policy for a specific account. + required: + - accountId + properties: + accountId: + type: string + description: The internal account ID this rule applies to. + example: Account:019542f5-b3e7-1d02-0000-000000000001 + executionMode: + $ref: '#/components/schemas/AgentExecutionMode' + perTransactionLimit: + type: + - integer + - 'null' + description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. + example: 10000 + AgentAccountRestrictions: + type: object + description: Optional restrictions that limit the agent to specific accounts or override policy per account. + properties: + allowedAccountIds: + type: + - array + - 'null' + description: If set, restricts the agent to operate only on the specified internal account IDs. Null means the agent can access all accounts. + items: + type: string + example: Account:019542f5-b3e7-1d02-0000-000000000001 + accountRules: + type: array + description: Per-account rules that override the agent's default policy for specific accounts. + items: + $ref: '#/components/schemas/AgentAccountRule' + AgentApprovalThresholds: + type: object + description: Thresholds that force approval for high-value transactions, overriding the default execution mode. + properties: + amount: + type: + - integer + - 'null' + description: If set, any transaction above this amount (in the smallest unit of the relevant currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. + example: 100000 + AgentPolicy: + type: object + description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. + required: + - permissions + - defaultExecutionMode + - spendingLimits + properties: + permissions: + type: array + description: List of permissions granted to the agent. + items: + $ref: '#/components/schemas/AgentPermission' + defaultExecutionMode: + $ref: '#/components/schemas/AgentExecutionMode' + spendingLimits: + $ref: '#/components/schemas/AgentSpendingLimits' + accountRestrictions: + $ref: '#/components/schemas/AgentAccountRestrictions' + approvalThresholds: + $ref: '#/components/schemas/AgentApprovalThresholds' + AgentUsage: + type: object + description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. + required: + - dailyTransactionCount + - dailySpend + - monthlySpend + properties: + dailyTransactionCount: + type: integer + description: Number of transactions initiated by the agent today. + example: 3 + dailySpend: + type: integer + description: Total amount spent by the agent today, in the smallest unit of the relevant currency. + example: 150000 + dailyResetDate: + type: string + format: date + description: The date when daily usage counters will reset. + example: '2025-07-22' + monthlySpend: + type: integer + description: Total amount spent by the agent this month, in the smallest unit of the relevant currency. + example: 750000 + monthlyResetMonth: + type: string + description: The year-month (YYYY-MM) when monthly usage counters will reset. + example: 2025-08 + Agent: + type: object + description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. + required: + - id + - name + - customerId + - isPaused + - isConnected + - policy + - usage + - createdAt + - updatedAt + properties: + id: + type: string + description: System-generated unique identifier for the agent. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + name: + type: string + description: Human-readable name for the agent. + example: Payroll Automation Agent + customerId: + type: string + description: The ID of the customer this agent operates on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + isPaused: + type: boolean + description: Whether the agent is currently paused. Paused agents cannot initiate any actions. + example: false + isConnected: + type: boolean + description: Whether the agent has been installed and connected (i.e., its device code has been redeemed). + example: true + policy: + $ref: '#/components/schemas/AgentPolicy' + usage: + $ref: '#/components/schemas/AgentUsage' + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2025-07-21T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2025-07-21T17:32:28Z' + AgentListResponse: + type: object + required: + - data + - hasMore + properties: + data: + type: array + description: List of agents matching the filter criteria. + items: + $ref: '#/components/schemas/Agent' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true). + totalCount: + type: integer + description: Total number of agents matching the criteria (excluding pagination). + AgentCreateRequest: + type: object + required: + - name + - customerId + - policy + properties: + name: + type: string + description: Human-readable name to identify the agent. + example: Payroll Automation Agent + customerId: + type: string + description: The ID of the customer this agent will operate on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + policy: + $ref: '#/components/schemas/AgentPolicy' + AgentDeviceCode: + type: object + required: + - code + - agentId + - expiresAt + - redeemed + properties: + code: + type: string + description: Human-readable device code used to install and connect the agent software. + example: GRID-AGENT-X7K9-M2P4 + agentId: + type: string + description: The agent this device code belongs to. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + expiresAt: + type: string + format: date-time + description: Timestamp when this device code expires. + example: '2025-07-22T17:32:28Z' + redeemed: + type: boolean + description: Whether this device code has already been redeemed by the agent. + example: false + AgentCreateResponse: + type: object + description: Response returned when an agent is created, including the agent and a device code for installation. + required: + - agent + - deviceCode + properties: + agent: + $ref: '#/components/schemas/Agent' + deviceCode: + $ref: '#/components/schemas/AgentDeviceCode' + 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: + perTransactionLimit: + type: integer + description: Maximum amount per transaction, in the smallest unit of the relevant currency. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum daily spend, in the smallest unit of the relevant currency. 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, in the smallest unit of the relevant currency. 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' + 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 + - clientId + - clientSecret + - 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 + clientId: + type: string + description: The client ID to use as the username in HTTP Basic Authentication when calling Grid API endpoints as this agent. + example: 01947d2284054f890000e63bca4810df + clientSecret: + type: string + description: The client secret to use as the password in HTTP Basic Authentication. This secret is returned only once and must be stored securely — it cannot be retrieved again. + example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + policy: + $ref: '#/components/schemas/AgentPolicy' WebhookType: type: string enum: diff --git a/mintlify/style.css b/mintlify/style.css index 14bc413f..69d88540 100644 --- a/mintlify/style.css +++ b/mintlify/style.css @@ -1382,6 +1382,18 @@ ul#sidebar-group > li[data-title="Embedded Wallet Auth"] > button::before { background-image: url('/images/icons/lock.svg') !important; } +/* Agent Management */ +#sidebar-group > li[data-title="Agent Management"] > button::before, +ul#sidebar-group > li[data-title="Agent Management"] > button::before { + background-image: url('/images/icons/agent.svg') !important; +} + +/* Agent Operations */ +#sidebar-group > li[data-title="Agent Operations"] > button::before, +ul#sidebar-group > li[data-title="Agent Operations"] > button::before { + background-image: url('/images/icons/prompt.svg') !important; +} + /* =========================================== Main Content Area diff --git a/openapi.yaml b/openapi.yaml index eca20ec0..1bc14f05 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -48,6 +48,10 @@ tags: description: Endpoints for discovering available payment rails, banks, and providers for a given country and currency corridor. - name: Embedded Wallet Auth description: Endpoints for registering and verifying end-user authentication credentials (email OTP, OAuth, passkey) used to sign Embedded Wallet actions. + - name: Agent Management + description: 'Endpoints for creating and managing agents (experimental), called by the partner''s backend using platform credentials. Covers the full agent lifecycle: creation, policy configuration, pausing, deletion, the device code installation flow, and approving or rejecting transactions initiated by agents.' + - name: Agent Operations + description: Endpoints called by the agent itself using its own credentials (obtained via device code redemption). Scoped to the agent's associated customer — all requests automatically operate on behalf of that customer and are subject to the agent's policy. When an action requires approval, the resulting transaction enters a pending state and must be approved by the platform via `POST /transactions/{transactionId}/approve`. paths: /config: get: @@ -4319,6 +4323,1391 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /agents: + post: + summary: Create an agent + description: | + Create a new agent with a specified policy. Returns the created agent and a device code that must be redeemed by the agent software to complete installation. + operationId: createAgent + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentCreateRequest' + responses: + '201': + description: Agent created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AgentCreateResponse' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + get: + summary: List agents + description: Retrieve a paginated list of agents for the authenticated platform. + operationId: listAgents + tags: + - Agent Management + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: Filter by customer ID + required: false + schema: + type: string + - name: isPaused + in: query + description: Filter by paused status + required: false + schema: + type: boolean + - name: isConnected + in: query + description: Filter by connection status (whether the device code has been redeemed) + required: false + schema: + type: boolean + - name: createdAfter + in: query + description: Filter agents created after this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: createdBefore + in: query + description: Filter agents created before this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: updatedAfter + in: query + description: Filter agents updated after this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: updatedBefore + in: query + description: Filter agents updated before this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/approvals: + get: + summary: List agent transaction approval requests + description: | + Retrieve a paginated list of transactions initiated by agents that require platform approval. Filter by `agentId` or `customerId` to scope results to a specific agent or customer. Approve or reject individual transactions via `POST /agents/{agentId}/transactions/{transactionId}/approve` or `POST /agents/{agentId}/transactions/{transactionId}/reject`. + operationId: listAgentApprovals + tags: + - Agent Management + security: + - BasicAuth: [] + parameters: + - name: agentId + in: query + description: Filter by agent ID + required: false + schema: + type: string + - name: customerId + in: query + description: Filter by customer ID + required: false + schema: + type: string + - name: startDate + in: query + description: Filter by start date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - name: endDate + in: query + description: Filter by end date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - 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 + - name: sortOrder + in: query + description: Order to sort results in + required: false + schema: + type: string + enum: + - asc + - desc + default: desc + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me: + get: + summary: Get current agent + description: | + Retrieve the authenticated agent's own profile, policy, and current usage. This endpoint is called by the agent software itself using its own credentials (obtained via device code redemption) rather than platform credentials. + operationId: getAgentMe + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + get: + summary: Get agent by ID + description: Retrieve an agent by its system-generated ID. + operationId: getAgentById + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + patch: + summary: Update agent + description: Update an agent's name or paused state. + operationId: updateAgent + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentUpdateRequest' + responses: + '200': + description: Agent updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + delete: + summary: Delete agent + description: Permanently delete an agent. Connected agent software will lose access immediately. + operationId: deleteAgent + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '204': + description: Agent deleted successfully + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/policy: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + patch: + summary: Update agent policy + description: | + Partially update an agent's policy. Only provided fields will be updated; omitted fields retain their current values. Policy changes take effect immediately. + operationId: updateAgentPolicy + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentPolicyUpdateRequest' + responses: + '200': + description: Agent policy updated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Agent' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/device-codes: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + post: + summary: Regenerate a device code + description: | + Generate a new device code for an existing agent. Use this when the original device code has expired before being redeemed, or when the agent software needs to be reinstalled. Any previously issued unredeemed device codes for this agent are invalidated. + operationId: regenerateAgentDeviceCode + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '201': + description: New device code generated successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AgentDeviceCode' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Agent already has an active connection and cannot regenerate a device code + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/transactions/{transactionId}/approve: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + - name: transactionId + in: path + description: Unique identifier of the transaction to approve + required: true + schema: + type: string + post: + summary: Approve an agent-initiated transaction + description: | + Approve a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + This endpoint is called by the platform's backend using platform credentials, not by the agent itself. + operationId: approveAgentTransaction + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/ApprovePaymentRequest' + responses: + '200': + description: Transaction approved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Transaction cannot be approved + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent or transaction not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Transaction is not pending approval or has already been processed + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/{agentId}/transactions/{transactionId}/reject: + parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + - name: transactionId + in: path + description: Unique identifier of the transaction to reject + required: true + schema: + type: string + post: + summary: Reject an agent-initiated transaction + description: | + Reject a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + This endpoint is called by the platform's backend using platform credentials, not by the agent itself. + operationId: rejectAgentTransaction + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: false + content: + application/json: + schema: + $ref: '#/components/schemas/RejectPaymentRequest' + responses: + '200': + description: Transaction rejected successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Transaction cannot be rejected + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Agent or transaction not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Transaction is not pending approval or has already been processed + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/device-codes/{code}/status: + parameters: + - name: code + in: path + description: The device code to check + required: true + schema: + type: string + get: + summary: Get device code status + description: | + Check whether a device code has been redeemed. Use this to poll for agent installation completion after creating an agent. + operationId: getAgentDeviceCodeStatus + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentDeviceCodeStatusResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Device code not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/device-codes/{code}/redeem: + parameters: + - name: code + in: path + description: The device code to redeem + required: true + schema: + type: string + post: + summary: Redeem device code + description: | + Redeem a device code to obtain agent credentials. This endpoint is called by the agent software during installation. On success, returns a clientId and clientSecret that the agent uses for all subsequent API calls. The secret is returned only once and must be stored securely. + This endpoint does not require platform authentication — the device code itself serves as proof of authorization. + operationId: redeemAgentDeviceCode + tags: + - Agent Management + security: [] + responses: + '200': + description: Device code redeemed successfully + content: + application/json: + schema: + $ref: '#/components/schemas/AgentDeviceCodeRedeemResponse' + '400': + description: Bad request (e.g., code already redeemed or expired) + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '404': + description: Device code not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transactions: + get: + summary: List agent transactions + description: | + Retrieve a paginated list of transactions for the authenticated agent's customer. Results are automatically scoped to the agent's associated customer — no customer filter is needed or accepted. + operationId: agentListTransactions + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: accountIdentifier + in: query + description: Filter by account identifier (matches either sender or receiver) + required: false + schema: + type: string + - name: senderAccountIdentifier + in: query + description: Filter by sender account identifier + required: false + schema: + type: string + - name: receiverAccountIdentifier + in: query + description: Filter by receiver account identifier + required: false + schema: + type: string + - name: status + in: query + description: Filter by transaction status + required: false + schema: + $ref: '#/components/schemas/TransactionStatus' + - name: type + in: query + description: Filter by transaction type + required: false + schema: + $ref: '#/components/schemas/TransactionType' + - name: reference + in: query + description: Filter by reference + required: false + schema: + type: string + - name: startDate + in: query + description: Filter by start date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - name: endDate + in: query + description: Filter by end date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - 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 + - name: sortOrder + in: query + description: Order to sort results in + required: false + schema: + type: string + enum: + - asc + - desc + default: desc + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transactions/{transactionId}: + parameters: + - name: transactionId + in: path + description: Unique identifier of the transaction + required: true + schema: + type: string + get: + summary: Get agent transaction by ID + description: | + Retrieve a specific transaction belonging to the authenticated agent's customer. Returns 404 if the transaction exists but belongs to a different customer. + operationId: agentGetTransaction + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Transaction not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/quotes: + post: + summary: Create a transfer quote + description: | + Generate a quote for a cross-currency transfer on behalf of the authenticated agent's customer. Accounts referenced in the request must belong to the agent's customer. Requires the CREATE_QUOTES permission in the agent's policy. + If the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the quote amount exceeds the agent's approvalThresholds, the resulting transaction will require explicit approval before funds move. + operationId: agentCreateQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/QuoteRequest' + responses: + '201': + description: Transfer quote created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Quote' + '400': + description: Bad request - Missing or invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '412': + description: Counterparty doesn't support UMA version + content: + application/json: + schema: + $ref: '#/components/schemas/Error412' + '424': + description: Counterparty issue + content: + application/json: + schema: + $ref: '#/components/schemas/Error424' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/quotes/{quoteId}: + parameters: + - name: quoteId + in: path + description: ID of the quote to retrieve + required: true + schema: + type: string + get: + summary: Get agent quote by ID + description: | + Retrieve a quote created by the authenticated agent. Returns 404 if the quote exists but was not created by this agent. + operationId: agentGetQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Quote retrieved successfully + content: + application/json: + schema: + $ref: '#/components/schemas/Quote' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/quotes/{quoteId}/execute: + parameters: + - name: quoteId + in: path + required: true + description: The unique identifier of the quote to execute + schema: + type: string + example: Quote:019542f5-b3e7-1d02-0000-000000000001 + post: + summary: Execute a quote + description: | + Execute a quote created by the authenticated agent. Requires the EXECUTE_QUOTES permission in the agent's policy. + If the agent's policy requires approval for this amount (based on execution mode or approval thresholds), the transaction will be created in a pending state and must be approved by the platform via `POST /agents/{agentId}/transactions/{transactionId}/approve`. + Once executed, the quote cannot be cancelled. + operationId: agentExecuteQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: + - name: Grid-Wallet-Signature + in: header + required: false + description: Signature over the `payloadToSign` returned in the quote's `paymentInstructions[].accountOrWalletInfo` entry, produced with the session private key of a verified authentication credential on the source Embedded Wallet and base64-encoded. Required when the quote's source is an internal account of type `EMBEDDED_WALLET`; ignored for other source types. + schema: + type: string + example: MEUCIQDx7k2N0aK4p8f3vR9J6yT5wL1mB0sXnG2hQ4vJ8zYkCgIgZ4rP9dT7eWfU3oM6KjR1qSpNvBwL0tXyA2iG8fH5dE= + responses: + '200': + description: Quote executed successfully. Transfer has been initiated. + content: + application/json: + schema: + $ref: '#/components/schemas/Quote' + '400': + description: Bad request - Quote cannot be executed + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized. Also returned when the quote's source is an internal account of type `EMBEDDED_WALLET` and the provided `Grid-Wallet-Signature` header is missing, malformed, or does not match the quote's `payloadToSign`. + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '404': + description: Quote not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '409': + description: Conflict - Quote already executed, expired, or in invalid state + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transfer-in: + post: + summary: Create a transfer-in + description: | + Transfer funds from an external account to an internal account for the authenticated agent's customer. Accounts must belong to the agent's customer. Requires the CREATE_TRANSFERS permission in the agent's policy. + If the agent's policy requires approval for this amount, the transaction will be created in a pending state and must be approved by the platform via `POST /agents/{agentId}/transactions/{transactionId}/approve`. + This endpoint should only be used for external account sources with pull functionality (e.g. ACH Pull). Otherwise, use the payment instructions on the internal account to deposit funds. + operationId: agentCreateTransferIn + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: 550e8400-e29b-41d4-a716-446655440000 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TransferInRequest' + examples: + transferIn: + summary: Transfer from external to internal account + value: + source: + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + amount: 12550 + responses: + '201': + description: Transfer-in created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '404': + description: Account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/transfer-out: + post: + summary: Create a transfer-out + description: | + Transfer funds from an internal account to an external account for the authenticated agent's customer. Accounts must belong to the agent's customer. Requires the CREATE_TRANSFERS permission in the agent's policy. + If the agent's policy requires approval for this amount, the transaction will be created in a pending state and must be approved by the platform via `POST /agents/{agentId}/transactions/{transactionId}/approve`. + operationId: agentCreateTransferOut + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: | + A unique identifier for the request. If the same key is sent multiple times, the server will return the same response as the first request. + schema: + type: string + example: 550e8400-e29b-41d4-a716-446655440000 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TransferOutRequest' + examples: + transferOut: + summary: Transfer from internal to external account + value: + source: + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + amount: 12550 + responses: + '201': + description: Transfer-out created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/TransactionOneOf' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: '#/components/schemas/Error403' + '404': + description: Account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/external-accounts: + get: + summary: List agent external accounts + description: | + Retrieve a paginated list of external accounts belonging to the authenticated agent's customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentListExternalAccounts + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: currency + in: query + description: Filter by currency code + required: false + schema: + type: string + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccountListResponse' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + post: + summary: Add an external account + description: | + Register a new external bank account or wallet for the authenticated agent's customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. The `customerId` field is optional and will be inferred from the agent's associated customer if omitted. + operationId: agentCreateExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccountCreateRequest' + examples: + usBankAccount: + summary: Create external US bank account + value: + currency: USD + accountInfo: + accountType: USD_ACCOUNT + accountNumber: '12345678901' + routingNumber: '123456789' + bankAccountType: CHECKING + bankName: Chase Bank + beneficiary: + beneficiaryType: INDIVIDUAL + fullName: John Doe + birthDate: '1990-01-15' + nationality: US + address: + line1: 123 Main Street + city: San Francisco + state: CA + postalCode: '94105' + country: US + sparkWallet: + summary: Create external Spark wallet + value: + currency: BTC + accountInfo: + accountType: SPARK_WALLET + address: spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu + responses: + '201': + description: External account created successfully + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccount' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error400' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - External account already exists + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/external-accounts/{externalAccountId}: + parameters: + - name: externalAccountId + in: path + description: System-generated unique external account identifier + required: true + schema: + type: string + get: + summary: Get agent external account by ID + description: | + Retrieve an external account belonging to the authenticated agent's customer. Returns 404 if the account exists but belongs to a different customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentGetExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ExternalAccount' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: External account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + delete: + summary: Delete agent external account + description: | + Delete an external account belonging to the authenticated agent's customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentDeleteExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '204': + description: External account deleted successfully + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: External account not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' webhooks: incoming-payment: post: @@ -5136,6 +6525,10 @@ components: type: http scheme: basic description: API token authentication using format `:` + AgentAuth: + type: http + scheme: basic + description: 'Agent authentication using format `:`, where the credentials are obtained by 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 @@ -12373,6 +13766,10 @@ components: format: date-time description: When the transaction was last updated example: '2025-08-15T14:30:00Z' + agentId: + type: string + description: If this transaction was initiated by an agent, the system-generated ID of that agent. Absent for platform-initiated transactions. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 description: type: string description: Optional memo or description for the payment @@ -14199,6 +15596,357 @@ components: description: List of active authentication sessions for the internal account. items: $ref: '#/components/schemas/AuthSession' + AgentPermission: + type: string + enum: + - VIEW_TRANSACTIONS + - CREATE_TRANSFERS + - CREATE_QUOTES + - EXECUTE_QUOTES + - MANAGE_EXTERNAL_ACCOUNTS + description: 'Permission granted to an agent that determines what actions it can perform. VIEW_TRANSACTIONS: Can list and retrieve transactions and account balances. CREATE_TRANSFERS: Can initiate same-currency transfers. CREATE_QUOTES: Can create cross-currency quotes. EXECUTE_QUOTES: Can execute cross-currency quotes. MANAGE_EXTERNAL_ACCOUNTS: Can create and manage external accounts.' + AgentExecutionMode: + type: string + enum: + - AUTO + - APPROVAL_REQUIRED + description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' + AgentSpendingLimits: + type: object + description: Spending limits that cap the agent's transaction amounts and frequency. + required: + - perTransactionLimit + properties: + perTransactionLimit: + type: integer + description: Maximum amount the agent can transfer in a single transaction, in the smallest unit of the relevant currency. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per day, in the smallest unit of the relevant currency. Null means no daily limit. + example: 500000 + dailyTransactionLimit: + type: integer + description: Maximum number of transactions the agent can initiate per day. + example: 10 + monthlyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per month, in the smallest unit of the relevant currency. Null means no monthly limit. + example: 5000000 + AgentAccountRule: + type: object + description: Per-account policy override that takes precedence over the agent's default policy for a specific account. + required: + - accountId + properties: + accountId: + type: string + description: The internal account ID this rule applies to. + example: Account:019542f5-b3e7-1d02-0000-000000000001 + executionMode: + $ref: '#/components/schemas/AgentExecutionMode' + perTransactionLimit: + type: + - integer + - 'null' + description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. + example: 10000 + AgentAccountRestrictions: + type: object + description: Optional restrictions that limit the agent to specific accounts or override policy per account. + properties: + allowedAccountIds: + type: + - array + - 'null' + description: If set, restricts the agent to operate only on the specified internal account IDs. Null means the agent can access all accounts. + items: + type: string + example: Account:019542f5-b3e7-1d02-0000-000000000001 + accountRules: + type: array + description: Per-account rules that override the agent's default policy for specific accounts. + items: + $ref: '#/components/schemas/AgentAccountRule' + AgentApprovalThresholds: + type: object + description: Thresholds that force approval for high-value transactions, overriding the default execution mode. + properties: + amount: + type: + - integer + - 'null' + description: If set, any transaction above this amount (in the smallest unit of the relevant currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. + example: 100000 + AgentPolicy: + type: object + description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. + required: + - permissions + - defaultExecutionMode + - spendingLimits + properties: + permissions: + type: array + description: List of permissions granted to the agent. + items: + $ref: '#/components/schemas/AgentPermission' + defaultExecutionMode: + $ref: '#/components/schemas/AgentExecutionMode' + spendingLimits: + $ref: '#/components/schemas/AgentSpendingLimits' + accountRestrictions: + $ref: '#/components/schemas/AgentAccountRestrictions' + approvalThresholds: + $ref: '#/components/schemas/AgentApprovalThresholds' + AgentUsage: + type: object + description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. + required: + - dailyTransactionCount + - dailySpend + - monthlySpend + properties: + dailyTransactionCount: + type: integer + description: Number of transactions initiated by the agent today. + example: 3 + dailySpend: + type: integer + description: Total amount spent by the agent today, in the smallest unit of the relevant currency. + example: 150000 + dailyResetDate: + type: string + format: date + description: The date when daily usage counters will reset. + example: '2025-07-22' + monthlySpend: + type: integer + description: Total amount spent by the agent this month, in the smallest unit of the relevant currency. + example: 750000 + monthlyResetMonth: + type: string + description: The year-month (YYYY-MM) when monthly usage counters will reset. + example: 2025-08 + Agent: + type: object + description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. + required: + - id + - name + - customerId + - isPaused + - isConnected + - policy + - usage + - createdAt + - updatedAt + properties: + id: + type: string + description: System-generated unique identifier for the agent. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + name: + type: string + description: Human-readable name for the agent. + example: Payroll Automation Agent + customerId: + type: string + description: The ID of the customer this agent operates on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + isPaused: + type: boolean + description: Whether the agent is currently paused. Paused agents cannot initiate any actions. + example: false + isConnected: + type: boolean + description: Whether the agent has been installed and connected (i.e., its device code has been redeemed). + example: true + policy: + $ref: '#/components/schemas/AgentPolicy' + usage: + $ref: '#/components/schemas/AgentUsage' + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2025-07-21T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2025-07-21T17:32:28Z' + AgentListResponse: + type: object + required: + - data + - hasMore + properties: + data: + type: array + description: List of agents matching the filter criteria. + items: + $ref: '#/components/schemas/Agent' + hasMore: + type: boolean + description: Indicates if more results are available beyond this page. + nextCursor: + type: string + description: Cursor to retrieve the next page of results (only present if hasMore is true). + totalCount: + type: integer + description: Total number of agents matching the criteria (excluding pagination). + AgentCreateRequest: + type: object + required: + - name + - customerId + - policy + properties: + name: + type: string + description: Human-readable name to identify the agent. + example: Payroll Automation Agent + customerId: + type: string + description: The ID of the customer this agent will operate on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + policy: + $ref: '#/components/schemas/AgentPolicy' + AgentDeviceCode: + type: object + required: + - code + - agentId + - expiresAt + - redeemed + properties: + code: + type: string + description: Human-readable device code used to install and connect the agent software. + example: GRID-AGENT-X7K9-M2P4 + agentId: + type: string + description: The agent this device code belongs to. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + expiresAt: + type: string + format: date-time + description: Timestamp when this device code expires. + example: '2025-07-22T17:32:28Z' + redeemed: + type: boolean + description: Whether this device code has already been redeemed by the agent. + example: false + AgentCreateResponse: + type: object + description: Response returned when an agent is created, including the agent and a device code for installation. + required: + - agent + - deviceCode + properties: + agent: + $ref: '#/components/schemas/Agent' + deviceCode: + $ref: '#/components/schemas/AgentDeviceCode' + 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: + perTransactionLimit: + type: integer + description: Maximum amount per transaction, in the smallest unit of the relevant currency. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum daily spend, in the smallest unit of the relevant currency. 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, in the smallest unit of the relevant currency. 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' + 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 + - clientId + - clientSecret + - 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 + clientId: + type: string + description: The client ID to use as the username in HTTP Basic Authentication when calling Grid API endpoints as this agent. + example: 01947d2284054f890000e63bca4810df + clientSecret: + type: string + description: The client secret to use as the password in HTTP Basic Authentication. This secret is returned only once and must be stored securely — it cannot be retrieved again. + example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + policy: + $ref: '#/components/schemas/AgentPolicy' WebhookType: type: string enum: diff --git a/openapi/components/schemas/agents/Agent.yaml b/openapi/components/schemas/agents/Agent.yaml new file mode 100644 index 00000000..65166160 --- /dev/null +++ b/openapi/components/schemas/agents/Agent.yaml @@ -0,0 +1,47 @@ +type: object +description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. +required: + - id + - name + - customerId + - isPaused + - isConnected + - policy + - usage + - createdAt + - updatedAt +properties: + id: + type: string + description: System-generated unique identifier for the agent. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + name: + type: string + description: Human-readable name for the agent. + example: Payroll Automation Agent + customerId: + type: string + description: The ID of the customer this agent operates on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + isPaused: + type: boolean + description: Whether the agent is currently paused. Paused agents cannot initiate any actions. + example: false + isConnected: + type: boolean + description: Whether the agent has been installed and connected (i.e., its device code has been redeemed). + example: true + policy: + $ref: ./AgentPolicy.yaml + usage: + $ref: ./AgentUsage.yaml + createdAt: + type: string + format: date-time + description: Creation timestamp. + example: '2025-07-21T17:32:28Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp. + example: '2025-07-21T17:32:28Z' diff --git a/openapi/components/schemas/agents/AgentAccountRestrictions.yaml b/openapi/components/schemas/agents/AgentAccountRestrictions.yaml new file mode 100644 index 00000000..c1b742ac --- /dev/null +++ b/openapi/components/schemas/agents/AgentAccountRestrictions.yaml @@ -0,0 +1,18 @@ +type: object +description: Optional restrictions that limit the agent to specific accounts or override policy per account. +properties: + allowedAccountIds: + type: + - array + - 'null' + description: >- + If set, restricts the agent to operate only on the specified internal account IDs. + Null means the agent can access all accounts. + items: + type: string + example: Account:019542f5-b3e7-1d02-0000-000000000001 + accountRules: + type: array + description: Per-account rules that override the agent's default policy for specific accounts. + items: + $ref: ./AgentAccountRule.yaml diff --git a/openapi/components/schemas/agents/AgentAccountRule.yaml b/openapi/components/schemas/agents/AgentAccountRule.yaml new file mode 100644 index 00000000..b8738f8a --- /dev/null +++ b/openapi/components/schemas/agents/AgentAccountRule.yaml @@ -0,0 +1,17 @@ +type: object +description: Per-account policy override that takes precedence over the agent's default policy for a specific account. +required: + - accountId +properties: + accountId: + type: string + description: The internal account ID this rule applies to. + example: Account:019542f5-b3e7-1d02-0000-000000000001 + executionMode: + $ref: ./AgentExecutionMode.yaml + perTransactionLimit: + type: + - integer + - 'null' + description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. + example: 10000 diff --git a/openapi/components/schemas/agents/AgentApprovalThresholds.yaml b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml new file mode 100644 index 00000000..066eef34 --- /dev/null +++ b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml @@ -0,0 +1,12 @@ +type: object +description: Thresholds that force approval for high-value transactions, overriding the default execution mode. +properties: + amount: + type: + - integer + - 'null' + description: >- + If set, any transaction above this amount (in the smallest unit of the relevant currency) + will require explicit approval even when the agent's defaultExecutionMode is AUTO. + Null means no threshold override. + example: 100000 diff --git a/openapi/components/schemas/agents/AgentCreateRequest.yaml b/openapi/components/schemas/agents/AgentCreateRequest.yaml new file mode 100644 index 00000000..d11e9881 --- /dev/null +++ b/openapi/components/schemas/agents/AgentCreateRequest.yaml @@ -0,0 +1,16 @@ +type: object +required: + - name + - customerId + - policy +properties: + name: + type: string + description: Human-readable name to identify the agent. + example: Payroll Automation Agent + customerId: + type: string + description: The ID of the customer this agent will operate on behalf of. + example: Customer:019542f5-b3e7-1d02-0000-000000000001 + policy: + $ref: ./AgentPolicy.yaml diff --git a/openapi/components/schemas/agents/AgentCreateResponse.yaml b/openapi/components/schemas/agents/AgentCreateResponse.yaml new file mode 100644 index 00000000..a90a6cb2 --- /dev/null +++ b/openapi/components/schemas/agents/AgentCreateResponse.yaml @@ -0,0 +1,10 @@ +type: object +description: Response returned when an agent is created, including the agent and a device code for installation. +required: + - agent + - deviceCode +properties: + agent: + $ref: ./Agent.yaml + deviceCode: + $ref: ./AgentDeviceCode.yaml diff --git a/openapi/components/schemas/agents/AgentDeviceCode.yaml b/openapi/components/schemas/agents/AgentDeviceCode.yaml new file mode 100644 index 00000000..707d45d7 --- /dev/null +++ b/openapi/components/schemas/agents/AgentDeviceCode.yaml @@ -0,0 +1,24 @@ +type: object +required: + - code + - agentId + - expiresAt + - redeemed +properties: + code: + type: string + description: Human-readable device code used to install and connect the agent software. + example: GRID-AGENT-X7K9-M2P4 + agentId: + type: string + description: The agent this device code belongs to. + example: Agent:019542f5-b3e7-1d02-0000-000000000001 + expiresAt: + type: string + format: date-time + description: Timestamp when this device code expires. + example: '2025-07-22T17:32:28Z' + redeemed: + type: boolean + description: Whether this device code has already been redeemed by the agent. + example: false diff --git a/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml new file mode 100644 index 00000000..d43ec606 --- /dev/null +++ b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml @@ -0,0 +1,30 @@ +type: object +required: + - agentId + - agentName + - clientId + - clientSecret + - 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 + clientId: + type: string + description: >- + The client ID to use as the username in HTTP Basic Authentication when calling + Grid API endpoints as this agent. + example: 01947d2284054f890000e63bca4810df + clientSecret: + type: string + description: >- + The client secret to use as the password in HTTP Basic Authentication. This secret + is returned only once and must be stored securely — it cannot be retrieved again. + example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + policy: + $ref: ./AgentPolicy.yaml diff --git a/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml b/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml new file mode 100644 index 00000000..926a9c44 --- /dev/null +++ b/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml @@ -0,0 +1,13 @@ +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 diff --git a/openapi/components/schemas/agents/AgentExecutionMode.yaml b/openapi/components/schemas/agents/AgentExecutionMode.yaml new file mode 100644 index 00000000..6711c7b5 --- /dev/null +++ b/openapi/components/schemas/agents/AgentExecutionMode.yaml @@ -0,0 +1,8 @@ +type: string +enum: + - AUTO + - APPROVAL_REQUIRED +description: >- + Execution mode controlling whether agent actions require human approval. + AUTO: The agent can execute actions autonomously without explicit approval. + APPROVAL_REQUIRED: All agent actions require explicit human approval before execution. diff --git a/openapi/components/schemas/agents/AgentListResponse.yaml b/openapi/components/schemas/agents/AgentListResponse.yaml new file mode 100644 index 00000000..04a87763 --- /dev/null +++ b/openapi/components/schemas/agents/AgentListResponse.yaml @@ -0,0 +1,19 @@ +type: object +required: + - data + - hasMore +properties: + data: + type: array + description: List of agents matching the filter criteria. + items: + $ref: ./Agent.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 (only present if hasMore is true). + totalCount: + type: integer + description: Total number of agents matching the criteria (excluding pagination). diff --git a/openapi/components/schemas/agents/AgentPermission.yaml b/openapi/components/schemas/agents/AgentPermission.yaml new file mode 100644 index 00000000..4cef5cb0 --- /dev/null +++ b/openapi/components/schemas/agents/AgentPermission.yaml @@ -0,0 +1,14 @@ +type: string +enum: + - VIEW_TRANSACTIONS + - CREATE_TRANSFERS + - CREATE_QUOTES + - EXECUTE_QUOTES + - MANAGE_EXTERNAL_ACCOUNTS +description: >- + Permission granted to an agent that determines what actions it can perform. + VIEW_TRANSACTIONS: Can list and retrieve transactions and account balances. + CREATE_TRANSFERS: Can initiate same-currency transfers. + CREATE_QUOTES: Can create cross-currency quotes. + EXECUTE_QUOTES: Can execute cross-currency quotes. + MANAGE_EXTERNAL_ACCOUNTS: Can create and manage external accounts. diff --git a/openapi/components/schemas/agents/AgentPolicy.yaml b/openapi/components/schemas/agents/AgentPolicy.yaml new file mode 100644 index 00000000..ac251e1d --- /dev/null +++ b/openapi/components/schemas/agents/AgentPolicy.yaml @@ -0,0 +1,20 @@ +type: object +description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. +required: + - permissions + - defaultExecutionMode + - spendingLimits +properties: + permissions: + type: array + description: List of permissions granted to the agent. + items: + $ref: ./AgentPermission.yaml + defaultExecutionMode: + $ref: ./AgentExecutionMode.yaml + spendingLimits: + $ref: ./AgentSpendingLimits.yaml + accountRestrictions: + $ref: ./AgentAccountRestrictions.yaml + approvalThresholds: + $ref: ./AgentApprovalThresholds.yaml diff --git a/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml b/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml new file mode 100644 index 00000000..8cd1f7fa --- /dev/null +++ b/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml @@ -0,0 +1,18 @@ +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: ./AgentPermission.yaml + defaultExecutionMode: + $ref: ./AgentExecutionMode.yaml + spendingLimits: + $ref: ./AgentSpendingLimitsUpdate.yaml + accountRestrictions: + $ref: ./AgentAccountRestrictions.yaml + approvalThresholds: + $ref: ./AgentApprovalThresholds.yaml diff --git a/openapi/components/schemas/agents/AgentSpendingLimits.yaml b/openapi/components/schemas/agents/AgentSpendingLimits.yaml new file mode 100644 index 00000000..df06f7ee --- /dev/null +++ b/openapi/components/schemas/agents/AgentSpendingLimits.yaml @@ -0,0 +1,25 @@ +type: object +description: Spending limits that cap the agent's transaction amounts and frequency. +required: + - perTransactionLimit +properties: + perTransactionLimit: + type: integer + description: Maximum amount the agent can transfer in a single transaction, in the smallest unit of the relevant currency. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per day, in the smallest unit of the relevant currency. Null means no daily limit. + example: 500000 + dailyTransactionLimit: + type: integer + description: Maximum number of transactions the agent can initiate per day. + example: 10 + monthlyLimit: + type: + - integer + - 'null' + description: Maximum total amount the agent can transfer per month, in the smallest unit of the relevant currency. Null means no monthly limit. + example: 5000000 diff --git a/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml new file mode 100644 index 00000000..39f3adcb --- /dev/null +++ b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml @@ -0,0 +1,23 @@ +type: object +description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. +properties: + perTransactionLimit: + type: integer + description: Maximum amount per transaction, in the smallest unit of the relevant currency. + example: 50000 + dailyLimit: + type: + - integer + - 'null' + description: Maximum daily spend, in the smallest unit of the relevant currency. 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, in the smallest unit of the relevant currency. Set to null to remove the monthly limit. + example: 5000000 diff --git a/openapi/components/schemas/agents/AgentUpdateRequest.yaml b/openapi/components/schemas/agents/AgentUpdateRequest.yaml new file mode 100644 index 00000000..1154a360 --- /dev/null +++ b/openapi/components/schemas/agents/AgentUpdateRequest.yaml @@ -0,0 +1,11 @@ +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 diff --git a/openapi/components/schemas/agents/AgentUsage.yaml b/openapi/components/schemas/agents/AgentUsage.yaml new file mode 100644 index 00000000..8de13d24 --- /dev/null +++ b/openapi/components/schemas/agents/AgentUsage.yaml @@ -0,0 +1,28 @@ +type: object +description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. +required: + - dailyTransactionCount + - dailySpend + - monthlySpend +properties: + dailyTransactionCount: + type: integer + description: Number of transactions initiated by the agent today. + example: 3 + dailySpend: + type: integer + description: Total amount spent by the agent today, in the smallest unit of the relevant currency. + example: 150000 + dailyResetDate: + type: string + format: date + description: The date when daily usage counters will reset. + example: '2025-07-22' + monthlySpend: + type: integer + description: Total amount spent by the agent this month, in the smallest unit of the relevant currency. + example: 750000 + monthlyResetMonth: + type: string + description: The year-month (YYYY-MM) when monthly usage counters will reset. + example: '2025-08' diff --git a/openapi/components/schemas/transactions/Transaction.yaml b/openapi/components/schemas/transactions/Transaction.yaml index 2b72ccad..04b2bac1 100644 --- a/openapi/components/schemas/transactions/Transaction.yaml +++ b/openapi/components/schemas/transactions/Transaction.yaml @@ -42,6 +42,12 @@ properties: format: date-time description: When the transaction was last updated example: '2025-08-15T14:30:00Z' + agentId: + type: string + description: >- + If this transaction was initiated by an agent, the system-generated ID of that agent. + Absent for platform-initiated transactions. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 description: type: string description: Optional memo or description for the payment diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 58e3b03b..2c96719e 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -57,6 +57,20 @@ tags: Endpoints for registering and verifying end-user authentication credentials (email OTP, OAuth, passkey) used to sign Embedded Wallet actions. + - name: Agent Management + description: >- + Endpoints for creating and managing agents (experimental), called by the partner's + backend using platform credentials. Covers the full agent lifecycle: creation, + policy configuration, pausing, deletion, the device code installation flow, and + approving or rejecting transactions initiated by agents. + - name: Agent Operations + description: >- + Endpoints called by the agent itself using its own credentials (obtained via device + code redemption). Scoped to the agent's associated customer — all requests + automatically operate on behalf of that customer and are subject to the agent's + policy. When an action requires approval, the resulting transaction enters a pending + state and must be approved by the platform via + `POST /transactions/{transactionId}/approve`. servers: - url: https://api.lightspark.com/grid/2025-10-13 description: Production server @@ -68,6 +82,15 @@ components: description: >- API token authentication using format `:` + AgentAuth: + type: http + scheme: basic + description: >- + Agent authentication using format `:`, where the + credentials are obtained by 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 @@ -190,6 +213,45 @@ paths: $ref: paths/auth/auth_sessions.yaml /auth/sessions/{id}: $ref: paths/auth/auth_sessions_{id}.yaml + /agents: + $ref: paths/agents/agents.yaml + /agents/approvals: + $ref: paths/agents/agents_approvals.yaml + /agents/me: + $ref: paths/agents/agents_me.yaml + /agents/{agentId}: + $ref: paths/agents/agents_{agentId}.yaml + /agents/{agentId}/policy: + $ref: paths/agents/agents_{agentId}_policy.yaml + /agents/{agentId}/device-codes: + $ref: paths/agents/agents_{agentId}_device-codes.yaml + /agents/{agentId}/transactions/{transactionId}/approve: + $ref: paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml + /agents/{agentId}/transactions/{transactionId}/reject: + $ref: paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml + /agents/device-codes/{code}/status: + $ref: paths/agents/agents_device-codes_{code}_status.yaml + /agents/device-codes/{code}/redeem: + $ref: paths/agents/agents_device-codes_{code}_redeem.yaml + /agents/me/transactions: + $ref: paths/agents/agents_me_transactions.yaml + /agents/me/transactions/{transactionId}: + $ref: paths/agents/agents_me_transactions_{transactionId}.yaml + + /agents/me/quotes: + $ref: paths/agents/agents_me_quotes.yaml + /agents/me/quotes/{quoteId}: + $ref: paths/agents/agents_me_quotes_{quoteId}.yaml + /agents/me/quotes/{quoteId}/execute: + $ref: paths/agents/agents_me_quotes_{quoteId}_execute.yaml + /agents/me/transfer-in: + $ref: paths/agents/agents_me_transfer-in.yaml + /agents/me/transfer-out: + $ref: paths/agents/agents_me_transfer-out.yaml + /agents/me/external-accounts: + $ref: paths/agents/agents_me_external-accounts.yaml + /agents/me/external-accounts/{externalAccountId}: + $ref: paths/agents/agents_me_external-accounts_{externalAccountId}.yaml webhooks: incoming-payment: $ref: webhooks/incoming-payment.yaml diff --git a/openapi/paths/agents/agents.yaml b/openapi/paths/agents/agents.yaml new file mode 100644 index 00000000..add083cd --- /dev/null +++ b/openapi/paths/agents/agents.yaml @@ -0,0 +1,136 @@ +post: + summary: Create an agent + description: > + Create a new agent with a specified policy. Returns the created agent and a device code + that must be redeemed by the agent software to complete installation. + operationId: createAgent + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentCreateRequest.yaml + responses: + '201': + description: Agent created successfully + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentCreateResponse.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 + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml +get: + summary: List agents + description: Retrieve a paginated list of agents for the authenticated platform. + operationId: listAgents + tags: + - Agent Management + security: + - BasicAuth: [] + parameters: + - name: customerId + in: query + description: Filter by customer ID + required: false + schema: + type: string + - name: isPaused + in: query + description: Filter by paused status + required: false + schema: + type: boolean + - name: isConnected + in: query + description: Filter by connection status (whether the device code has been redeemed) + required: false + schema: + type: boolean + - name: createdAfter + in: query + description: Filter agents created after this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: createdBefore + in: query + description: Filter agents created before this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: updatedAfter + in: query + description: Filter agents updated after this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: updatedBefore + in: query + description: Filter agents updated before this timestamp (inclusive) + required: false + schema: + type: string + format: date-time + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentListResponse.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/agents/agents_approvals.yaml b/openapi/paths/agents/agents_approvals.yaml new file mode 100644 index 00000000..f79cb704 --- /dev/null +++ b/openapi/paths/agents/agents_approvals.yaml @@ -0,0 +1,90 @@ +get: + summary: List agent transaction approval requests + description: > + Retrieve a paginated list of transactions initiated by agents that require + platform approval. Filter by `agentId` or `customerId` to scope results to a + specific agent or customer. Approve or reject individual transactions via + `POST /agents/{agentId}/transactions/{transactionId}/approve` or + `POST /agents/{agentId}/transactions/{transactionId}/reject`. + operationId: listAgentApprovals + tags: + - Agent Management + security: + - BasicAuth: [] + parameters: + - name: agentId + in: query + description: Filter by agent ID + required: false + schema: + type: string + - name: customerId + in: query + description: Filter by customer ID + required: false + schema: + type: string + - name: startDate + in: query + description: Filter by start date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - name: endDate + in: query + description: Filter by end date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - 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 + - name: sortOrder + in: query + description: Order to sort results in + required: false + schema: + type: string + enum: + - asc + - desc + default: desc + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/TransactionListResponse.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/agents/agents_device-codes_{code}_redeem.yaml b/openapi/paths/agents/agents_device-codes_{code}_redeem.yaml new file mode 100644 index 00000000..c156369f --- /dev/null +++ b/openapi/paths/agents/agents_device-codes_{code}_redeem.yaml @@ -0,0 +1,46 @@ +parameters: + - name: code + in: path + description: The device code to redeem + required: true + schema: + type: string +post: + summary: Redeem device code + description: > + Redeem a device code to obtain agent credentials. This endpoint is called by the + agent software during installation. On success, returns a clientId and clientSecret + that the agent uses for all subsequent API calls. The secret is returned only once + and must be stored securely. + + This endpoint does not require platform authentication — the device code itself + serves as proof of authorization. + operationId: redeemAgentDeviceCode + tags: + - Agent Management + security: [] + responses: + '200': + description: Device code redeemed successfully + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml + '400': + description: Bad request (e.g., code already redeemed or expired) + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '404': + description: Device code 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/agents/agents_device-codes_{code}_status.yaml b/openapi/paths/agents/agents_device-codes_{code}_status.yaml new file mode 100644 index 00000000..d23780f5 --- /dev/null +++ b/openapi/paths/agents/agents_device-codes_{code}_status.yaml @@ -0,0 +1,42 @@ +parameters: + - name: code + in: path + description: The device code to check + required: true + schema: + type: string +get: + summary: Get device code status + description: > + Check whether a device code has been redeemed. Use this to poll for agent + installation completion after creating an agent. + operationId: getAgentDeviceCodeStatus + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentDeviceCodeStatusResponse.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Device code 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/agents/agents_me.yaml b/openapi/paths/agents/agents_me.yaml new file mode 100644 index 00000000..b5acac06 --- /dev/null +++ b/openapi/paths/agents/agents_me.yaml @@ -0,0 +1,30 @@ +get: + summary: Get current agent + description: > + Retrieve the authenticated agent's own profile, policy, and current usage. + This endpoint is called by the agent software itself using its own credentials + (obtained via device code redemption) rather than platform credentials. + operationId: getAgentMe + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/agents/Agent.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/agents/agents_me_external-accounts.yaml b/openapi/paths/agents/agents_me_external-accounts.yaml new file mode 100644 index 00000000..369227fd --- /dev/null +++ b/openapi/paths/agents/agents_me_external-accounts.yaml @@ -0,0 +1,136 @@ +get: + summary: List agent external accounts + description: > + Retrieve a paginated list of external accounts belonging to the authenticated + agent's customer. Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the + agent's policy. + operationId: agentListExternalAccounts + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: currency + in: query + description: Filter by currency code + required: false + schema: + type: string + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/external_accounts/ExternalAccountListResponse.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 +post: + summary: Add an external account + description: > + Register a new external bank account or wallet for the authenticated agent's customer. + Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + The `customerId` field is optional and will be inferred from the agent's associated + customer if omitted. + operationId: agentCreateExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/external_accounts/ExternalAccountCreateRequest.yaml + examples: + usBankAccount: + summary: Create external US bank account + value: + currency: USD + accountInfo: + accountType: USD_ACCOUNT + accountNumber: "12345678901" + routingNumber: "123456789" + bankAccountType: CHECKING + bankName: Chase Bank + beneficiary: + beneficiaryType: INDIVIDUAL + fullName: John Doe + birthDate: "1990-01-15" + nationality: US + address: + line1: 123 Main Street + city: San Francisco + state: CA + postalCode: "94105" + country: US + sparkWallet: + summary: Create external Spark wallet + value: + currency: BTC + accountInfo: + accountType: SPARK_WALLET + address: "spark1pgssyuuuhnrrdjswal5c3s3rafw9w3y5dd4cjy3duxlf7hjzkp0rqx6dj6mrhu" + responses: + '201': + description: External account created successfully + content: + application/json: + schema: + $ref: ../../components/schemas/external_accounts/ExternalAccount.yaml + '400': + description: Bad request + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '409': + description: Conflict - External account already exists + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_me_external-accounts_{externalAccountId}.yaml b/openapi/paths/agents/agents_me_external-accounts_{externalAccountId}.yaml new file mode 100644 index 00000000..4bdd2cc7 --- /dev/null +++ b/openapi/paths/agents/agents_me_external-accounts_{externalAccountId}.yaml @@ -0,0 +1,74 @@ +parameters: + - name: externalAccountId + in: path + description: System-generated unique external account identifier + required: true + schema: + type: string +get: + summary: Get agent external account by ID + description: > + Retrieve an external account belonging to the authenticated agent's customer. + Returns 404 if the account exists but belongs to a different customer. + Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentGetExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/external_accounts/ExternalAccount.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: External account not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml +delete: + summary: Delete agent external account + description: > + Delete an external account belonging to the authenticated agent's customer. + Requires the MANAGE_EXTERNAL_ACCOUNTS permission in the agent's policy. + operationId: agentDeleteExternalAccount + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '204': + description: External account deleted successfully + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: External account not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_me_quotes.yaml b/openapi/paths/agents/agents_me_quotes.yaml new file mode 100644 index 00000000..2e4a664f --- /dev/null +++ b/openapi/paths/agents/agents_me_quotes.yaml @@ -0,0 +1,74 @@ +post: + summary: Create a transfer quote + description: > + Generate a quote for a cross-currency transfer on behalf of the authenticated + agent's customer. Accounts referenced in the request must belong to the agent's + customer. Requires the CREATE_QUOTES permission in the agent's policy. + + If the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the quote amount + exceeds the agent's approvalThresholds, the resulting transaction will require + explicit approval before funds move. + operationId: agentCreateQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: > + A unique identifier for the request. If the same key is sent multiple times, + the server will return the same response as the first request. + schema: + type: string + example: + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/quotes/QuoteRequest.yaml + responses: + '201': + description: Transfer quote created successfully + content: + application/json: + schema: + $ref: ../../components/schemas/quotes/Quote.yaml + '400': + description: Bad request - Missing or 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 + '403': + description: Forbidden - Agent policy does not permit this operation + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error403.yaml + '412': + description: Counterparty doesn't support UMA version + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error412.yaml + '424': + description: Counterparty issue + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error424.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_me_quotes_{quoteId}.yaml b/openapi/paths/agents/agents_me_quotes_{quoteId}.yaml new file mode 100644 index 00000000..8c41497c --- /dev/null +++ b/openapi/paths/agents/agents_me_quotes_{quoteId}.yaml @@ -0,0 +1,42 @@ +parameters: + - name: quoteId + in: path + description: ID of the quote to retrieve + required: true + schema: + type: string +get: + summary: Get agent quote by ID + description: > + Retrieve a quote created by the authenticated agent. Returns 404 if the + quote exists but was not created by this agent. + operationId: agentGetQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Quote retrieved successfully + content: + application/json: + schema: + $ref: ../../components/schemas/quotes/Quote.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Quote not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_me_quotes_{quoteId}_execute.yaml b/openapi/paths/agents/agents_me_quotes_{quoteId}_execute.yaml new file mode 100644 index 00000000..216e8eb4 --- /dev/null +++ b/openapi/paths/agents/agents_me_quotes_{quoteId}_execute.yaml @@ -0,0 +1,94 @@ +parameters: + - name: quoteId + in: path + required: true + description: The unique identifier of the quote to execute + schema: + type: string + example: Quote:019542f5-b3e7-1d02-0000-000000000001 +post: + summary: Execute a quote + description: > + Execute a quote created by the authenticated agent. Requires the EXECUTE_QUOTES + permission in the agent's policy. + + If the agent's policy requires approval for this amount (based on execution mode + or approval thresholds), the transaction will be created in a pending state and + must be approved by the platform via `POST /agents/{agentId}/transactions/{transactionId}/approve`. + + Once executed, the quote cannot be cancelled. + operationId: agentExecuteQuote + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: > + A unique identifier for the request. If the same key is sent multiple times, + the server will return the same response as the first request. + schema: + type: string + example: + - name: Grid-Wallet-Signature + in: header + required: false + description: >- + Signature over the `payloadToSign` returned in the quote's + `paymentInstructions[].accountOrWalletInfo` entry, produced with the + session private key of a verified authentication credential on the + source Embedded Wallet and base64-encoded. Required when the quote's + source is an internal account of type `EMBEDDED_WALLET`; ignored for + other source types. + schema: + type: string + example: MEUCIQDx7k2N0aK4p8f3vR9J6yT5wL1mB0sXnG2hQ4vJ8zYkCgIgZ4rP9dT7eWfU3oM6KjR1qSpNvBwL0tXyA2iG8fH5dE= + responses: + '200': + description: Quote executed successfully. Transfer has been initiated. + content: + application/json: + schema: + $ref: ../../components/schemas/quotes/Quote.yaml + '400': + description: Bad request - Quote cannot be executed + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error400.yaml + '401': + description: >- + Unauthorized. Also returned when the quote's source is an internal + account of type `EMBEDDED_WALLET` and the provided + `Grid-Wallet-Signature` header is missing, malformed, or does not + match the quote's `payloadToSign`. + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error403.yaml + '404': + description: Quote not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict - Quote already executed, expired, or in invalid state + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_me_transactions.yaml b/openapi/paths/agents/agents_me_transactions.yaml new file mode 100644 index 00000000..34791ade --- /dev/null +++ b/openapi/paths/agents/agents_me_transactions.yaml @@ -0,0 +1,112 @@ +get: + summary: List agent transactions + description: > + Retrieve a paginated list of transactions for the authenticated agent's customer. + Results are automatically scoped to the agent's associated customer — no customer + filter is needed or accepted. + operationId: agentListTransactions + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: accountIdentifier + in: query + description: Filter by account identifier (matches either sender or receiver) + required: false + schema: + type: string + - name: senderAccountIdentifier + in: query + description: Filter by sender account identifier + required: false + schema: + type: string + - name: receiverAccountIdentifier + in: query + description: Filter by receiver account identifier + required: false + schema: + type: string + - name: status + in: query + description: Filter by transaction status + required: false + schema: + $ref: ../../components/schemas/transactions/TransactionStatus.yaml + - name: type + in: query + description: Filter by transaction type + required: false + schema: + $ref: ../../components/schemas/transactions/TransactionType.yaml + - name: reference + in: query + description: Filter by reference + required: false + schema: + type: string + - name: startDate + in: query + description: Filter by start date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - name: endDate + in: query + description: Filter by end date (inclusive) in ISO 8601 format + required: false + schema: + type: string + format: date-time + - 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 + - name: sortOrder + in: query + description: Order to sort results in + required: false + schema: + type: string + enum: + - asc + - desc + default: desc + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/TransactionListResponse.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/agents/agents_me_transactions_{transactionId}.yaml b/openapi/paths/agents/agents_me_transactions_{transactionId}.yaml new file mode 100644 index 00000000..f21db22e --- /dev/null +++ b/openapi/paths/agents/agents_me_transactions_{transactionId}.yaml @@ -0,0 +1,42 @@ +parameters: + - name: transactionId + in: path + description: Unique identifier of the transaction + required: true + schema: + type: string +get: + summary: Get agent transaction by ID + description: > + Retrieve a specific transaction belonging to the authenticated agent's customer. + Returns 404 if the transaction exists but belongs to a different customer. + operationId: agentGetTransaction + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/TransactionOneOf.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Transaction 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/agents/agents_me_transfer-in.yaml b/openapi/paths/agents/agents_me_transfer-in.yaml new file mode 100644 index 00000000..cd8bef31 --- /dev/null +++ b/openapi/paths/agents/agents_me_transfer-in.yaml @@ -0,0 +1,81 @@ +post: + summary: Create a transfer-in + description: > + Transfer funds from an external account to an internal account for the authenticated + agent's customer. Accounts must belong to the agent's customer. Requires the + CREATE_TRANSFERS permission in the agent's policy. + + If the agent's policy requires approval for this amount, the transaction will be + created in a pending state and must be approved by the platform via + `POST /agents/{agentId}/transactions/{transactionId}/approve`. + + This endpoint should only be used for external account sources with pull functionality + (e.g. ACH Pull). Otherwise, use the payment instructions on the internal account to + deposit funds. + operationId: agentCreateTransferIn + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: > + A unique identifier for the request. If the same key is sent multiple times, + the server will return the same response as the first request. + schema: + type: string + example: 550e8400-e29b-41d4-a716-446655440000 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/transfers/TransferInRequest.yaml + examples: + transferIn: + summary: Transfer from external to internal account + value: + source: + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + destination: + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + amount: 12550 + responses: + '201': + description: Transfer-in created successfully + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/TransactionOneOf.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 + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error403.yaml + '404': + description: Account not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_me_transfer-out.yaml b/openapi/paths/agents/agents_me_transfer-out.yaml new file mode 100644 index 00000000..05aa4203 --- /dev/null +++ b/openapi/paths/agents/agents_me_transfer-out.yaml @@ -0,0 +1,77 @@ +post: + summary: Create a transfer-out + description: > + Transfer funds from an internal account to an external account for the authenticated + agent's customer. Accounts must belong to the agent's customer. Requires the + CREATE_TRANSFERS permission in the agent's policy. + + If the agent's policy requires approval for this amount, the transaction will be + created in a pending state and must be approved by the platform via + `POST /agents/{agentId}/transactions/{transactionId}/approve`. + operationId: agentCreateTransferOut + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: Idempotency-Key + in: header + required: false + description: > + A unique identifier for the request. If the same key is sent multiple times, + the server will return the same response as the first request. + schema: + type: string + example: 550e8400-e29b-41d4-a716-446655440000 + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/transfers/TransferOutRequest.yaml + examples: + transferOut: + summary: Transfer from internal to external account + value: + source: + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + amount: 12550 + responses: + '201': + description: Transfer-out created successfully + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/TransactionOneOf.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 + '403': + description: Forbidden - Agent policy does not permit this operation or spending limit exceeded + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error403.yaml + '404': + description: Account not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_{agentId}.yaml b/openapi/paths/agents/agents_{agentId}.yaml new file mode 100644 index 00000000..8aa80e12 --- /dev/null +++ b/openapi/paths/agents/agents_{agentId}.yaml @@ -0,0 +1,114 @@ +parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string +get: + summary: Get agent by ID + description: Retrieve an agent by its system-generated ID. + operationId: getAgentById + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/agents/Agent.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Agent 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 +patch: + summary: Update agent + description: Update an agent's name or paused state. + operationId: updateAgent + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentUpdateRequest.yaml + responses: + '200': + description: Agent updated successfully + content: + application/json: + schema: + $ref: ../../components/schemas/agents/Agent.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: Agent 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 +delete: + summary: Delete agent + description: Permanently delete an agent. Connected agent software will lose access immediately. + operationId: deleteAgent + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '204': + description: Agent deleted successfully + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Agent 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/agents/agents_{agentId}_device-codes.yaml b/openapi/paths/agents/agents_{agentId}_device-codes.yaml new file mode 100644 index 00000000..9f1badca --- /dev/null +++ b/openapi/paths/agents/agents_{agentId}_device-codes.yaml @@ -0,0 +1,56 @@ +parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string +post: + summary: Regenerate a device code + description: > + Generate a new device code for an existing agent. Use this when the original + device code has expired before being redeemed, or when the agent software needs + to be reinstalled. Any previously issued unredeemed device codes for this agent + are invalidated. + operationId: regenerateAgentDeviceCode + tags: + - Agent Management + security: + - BasicAuth: [] + responses: + '201': + description: New device code generated successfully + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentDeviceCode.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: Agent not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict - Agent already has an active connection and cannot regenerate a device code + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_{agentId}_policy.yaml b/openapi/paths/agents/agents_{agentId}_policy.yaml new file mode 100644 index 00000000..e352abe3 --- /dev/null +++ b/openapi/paths/agents/agents_{agentId}_policy.yaml @@ -0,0 +1,54 @@ +parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string +patch: + summary: Update agent policy + description: > + Partially update an agent's policy. Only provided fields will be updated; + omitted fields retain their current values. Policy changes take effect immediately. + operationId: updateAgentPolicy + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentPolicyUpdateRequest.yaml + responses: + '200': + description: Agent policy updated successfully + content: + application/json: + schema: + $ref: ../../components/schemas/agents/Agent.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: Agent 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/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml b/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml new file mode 100644 index 00000000..5b7f9e50 --- /dev/null +++ b/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml @@ -0,0 +1,71 @@ +parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + - name: transactionId + in: path + description: Unique identifier of the transaction to approve + required: true + schema: + type: string +post: + summary: Approve an agent-initiated transaction + description: > + Approve a pending transaction that was initiated by an agent and is awaiting + platform approval. A transaction enters a pending state when the agent's policy + requires approval — either because the agent's defaultExecutionMode is + APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + + This endpoint is called by the platform's backend using platform credentials, + not by the agent itself. + operationId: approveAgentTransaction + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: false + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/ApprovePaymentRequest.yaml + responses: + '200': + description: Transaction approved successfully + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/TransactionOneOf.yaml + '400': + description: Bad request - Transaction cannot be approved + 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: Agent or transaction not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict - Transaction is not pending approval or has already been processed + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error409.yaml + '500': + description: Internal service error + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error500.yaml diff --git a/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml b/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml new file mode 100644 index 00000000..cd08130f --- /dev/null +++ b/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml @@ -0,0 +1,71 @@ +parameters: + - name: agentId + in: path + description: System-generated unique agent identifier + required: true + schema: + type: string + - name: transactionId + in: path + description: Unique identifier of the transaction to reject + required: true + schema: + type: string +post: + summary: Reject an agent-initiated transaction + description: > + Reject a pending transaction that was initiated by an agent and is awaiting + platform approval. A transaction enters a pending state when the agent's policy + requires approval — either because the agent's defaultExecutionMode is + APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + + This endpoint is called by the platform's backend using platform credentials, + not by the agent itself. + operationId: rejectAgentTransaction + tags: + - Agent Management + security: + - BasicAuth: [] + requestBody: + required: false + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/RejectPaymentRequest.yaml + responses: + '200': + description: Transaction rejected successfully + content: + application/json: + schema: + $ref: ../../components/schemas/transactions/TransactionOneOf.yaml + '400': + description: Bad request - Transaction cannot be rejected + 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: Agent or transaction not found + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error404.yaml + '409': + description: Conflict - Transaction is not pending approval or has already been processed + 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 From a8f0e32c3dd5eebc2961aa107ebaf8d7956434a1 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 30 Apr 2026 22:19:39 -0700 Subject: [PATCH 02/12] fix(agents): restore currency field on spending limits and approval thresholds --- .../agents/policies-and-permissions.mdx | 4 ++- mintlify/openapi.yaml | 31 +++++++++++++------ openapi.yaml | 31 +++++++++++++------ .../agents/AgentApprovalThresholds.yaml | 11 +++++-- .../schemas/agents/AgentSpendingLimits.yaml | 17 +++++++--- .../agents/AgentSpendingLimitsUpdate.yaml | 10 ++++-- 6 files changed, 76 insertions(+), 28 deletions(-) diff --git a/mintlify/global-accounts/agents/policies-and-permissions.mdx b/mintlify/global-accounts/agents/policies-and-permissions.mdx index 6d57ec09..2d5e5889 100644 --- a/mintlify/global-accounts/agents/policies-and-permissions.mdx +++ b/mintlify/global-accounts/agents/policies-and-permissions.mdx @@ -114,6 +114,7 @@ For example, Grid stores and enforces a policy object shaped like: ], "defaultExecutionMode": "APPROVAL_REQUIRED", "spendingLimits": { + "currency": "USD", "perTransactionLimit": 50000, "dailyLimit": 200000, "dailyTransactionLimit": 5 @@ -124,13 +125,14 @@ For example, Grid stores and enforces a policy object shaped like: ] }, "approvalThresholds": { + "currency": "USD", "amount": 25000 } } ``` -Policy amounts are integers in the smallest unit of the relevant currency. Grid infers the currency from the account or transaction context — no currency field is needed in the policy itself. For example, `50000` in a USD context means $500.00. +Policy amounts are integers in the smallest unit of the specified currency. For example, `50000` with `"currency": "USD"` means $500.00. When a transaction is denominated in a different currency, Grid converts using the current exchange rate at evaluation time. ## Practical guidance diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 1bc14f05..c55b65ea 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -15613,19 +15613,24 @@ components: description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' AgentSpendingLimits: type: object - description: Spending limits that cap the agent's transaction amounts and frequency. + description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: + - currency - perTransactionLimit properties: + currency: + type: string + description: ISO 4217 currency code that all amount limits are denominated in. + example: USD perTransactionLimit: type: integer - description: Maximum amount the agent can transfer in a single transaction, in the smallest unit of the relevant currency. + description: Maximum amount the agent can transfer in a single transaction. example: 50000 dailyLimit: type: - integer - 'null' - description: Maximum total amount the agent can transfer per day, in the smallest unit of the relevant currency. Null means no daily limit. + description: Maximum total amount the agent can transfer per day. Null means no daily limit. example: 500000 dailyTransactionLimit: type: integer @@ -15635,7 +15640,7 @@ components: type: - integer - 'null' - description: Maximum total amount the agent can transfer per month, in the smallest unit of the relevant currency. Null means no monthly limit. + description: Maximum total amount the agent can transfer per month. Null means no monthly limit. example: 5000000 AgentAccountRule: type: object @@ -15674,13 +15679,17 @@ components: $ref: '#/components/schemas/AgentAccountRule' AgentApprovalThresholds: type: object - description: Thresholds that force approval for high-value transactions, overriding the default execution mode. + description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: + currency: + type: string + description: ISO 4217 currency code that the amount threshold is denominated in. Required when amount is set. + example: USD amount: type: - integer - 'null' - description: If set, any transaction above this amount (in the smallest unit of the relevant currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. + description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. example: 100000 AgentPolicy: type: object @@ -15869,15 +15878,19 @@ components: 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, in the smallest unit of the relevant currency. + description: Maximum amount per transaction. example: 50000 dailyLimit: type: - integer - 'null' - description: Maximum daily spend, in the smallest unit of the relevant currency. Set to null to remove the daily limit. + description: Maximum daily spend. Set to null to remove the daily limit. example: 500000 dailyTransactionLimit: type: integer @@ -15887,7 +15900,7 @@ components: type: - integer - 'null' - description: Maximum monthly spend, in the smallest unit of the relevant currency. Set to null to remove the monthly limit. + description: Maximum monthly spend. Set to null to remove the monthly limit. example: 5000000 AgentPolicyUpdateRequest: type: object diff --git a/openapi.yaml b/openapi.yaml index 1bc14f05..c55b65ea 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -15613,19 +15613,24 @@ components: description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' AgentSpendingLimits: type: object - description: Spending limits that cap the agent's transaction amounts and frequency. + description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: + - currency - perTransactionLimit properties: + currency: + type: string + description: ISO 4217 currency code that all amount limits are denominated in. + example: USD perTransactionLimit: type: integer - description: Maximum amount the agent can transfer in a single transaction, in the smallest unit of the relevant currency. + description: Maximum amount the agent can transfer in a single transaction. example: 50000 dailyLimit: type: - integer - 'null' - description: Maximum total amount the agent can transfer per day, in the smallest unit of the relevant currency. Null means no daily limit. + description: Maximum total amount the agent can transfer per day. Null means no daily limit. example: 500000 dailyTransactionLimit: type: integer @@ -15635,7 +15640,7 @@ components: type: - integer - 'null' - description: Maximum total amount the agent can transfer per month, in the smallest unit of the relevant currency. Null means no monthly limit. + description: Maximum total amount the agent can transfer per month. Null means no monthly limit. example: 5000000 AgentAccountRule: type: object @@ -15674,13 +15679,17 @@ components: $ref: '#/components/schemas/AgentAccountRule' AgentApprovalThresholds: type: object - description: Thresholds that force approval for high-value transactions, overriding the default execution mode. + description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: + currency: + type: string + description: ISO 4217 currency code that the amount threshold is denominated in. Required when amount is set. + example: USD amount: type: - integer - 'null' - description: If set, any transaction above this amount (in the smallest unit of the relevant currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. + description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. example: 100000 AgentPolicy: type: object @@ -15869,15 +15878,19 @@ components: 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, in the smallest unit of the relevant currency. + description: Maximum amount per transaction. example: 50000 dailyLimit: type: - integer - 'null' - description: Maximum daily spend, in the smallest unit of the relevant currency. Set to null to remove the daily limit. + description: Maximum daily spend. Set to null to remove the daily limit. example: 500000 dailyTransactionLimit: type: integer @@ -15887,7 +15900,7 @@ components: type: - integer - 'null' - description: Maximum monthly spend, in the smallest unit of the relevant currency. Set to null to remove the monthly limit. + description: Maximum monthly spend. Set to null to remove the monthly limit. example: 5000000 AgentPolicyUpdateRequest: type: object diff --git a/openapi/components/schemas/agents/AgentApprovalThresholds.yaml b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml index 066eef34..dcd14c38 100644 --- a/openapi/components/schemas/agents/AgentApprovalThresholds.yaml +++ b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml @@ -1,12 +1,19 @@ type: object -description: Thresholds that force approval for high-value transactions, overriding the default execution mode. +description: >- + Thresholds that force approval for high-value transactions, overriding the default execution mode. + When a transaction is denominated in a different currency than the threshold, Grid converts using + the exchange rate at evaluation time. properties: + currency: + type: string + description: ISO 4217 currency code that the amount threshold is denominated in. Required when amount is set. + example: USD amount: type: - integer - 'null' description: >- - If set, any transaction above this amount (in the smallest unit of the relevant currency) + If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. example: 100000 diff --git a/openapi/components/schemas/agents/AgentSpendingLimits.yaml b/openapi/components/schemas/agents/AgentSpendingLimits.yaml index df06f7ee..b089c9da 100644 --- a/openapi/components/schemas/agents/AgentSpendingLimits.yaml +++ b/openapi/components/schemas/agents/AgentSpendingLimits.yaml @@ -1,17 +1,26 @@ type: object -description: Spending limits that cap the agent's transaction amounts and frequency. +description: >- + Spending limits that cap the agent's transaction amounts and frequency. All amount + fields are integers in the smallest unit of the specified currency. When a transaction + is denominated in a different currency, Grid converts using the exchange rate at + evaluation time. required: + - currency - perTransactionLimit properties: + currency: + type: string + description: ISO 4217 currency code that all amount limits are denominated in. + example: USD perTransactionLimit: type: integer - description: Maximum amount the agent can transfer in a single transaction, in the smallest unit of the relevant currency. + description: Maximum amount the agent can transfer in a single transaction. example: 50000 dailyLimit: type: - integer - 'null' - description: Maximum total amount the agent can transfer per day, in the smallest unit of the relevant currency. Null means no daily limit. + description: Maximum total amount the agent can transfer per day. Null means no daily limit. example: 500000 dailyTransactionLimit: type: integer @@ -21,5 +30,5 @@ properties: type: - integer - 'null' - description: Maximum total amount the agent can transfer per month, in the smallest unit of the relevant currency. Null means no monthly limit. + description: Maximum total amount the agent can transfer per month. Null means no monthly limit. example: 5000000 diff --git a/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml index 39f3adcb..80c7b865 100644 --- a/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml +++ b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml @@ -1,15 +1,19 @@ 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, in the smallest unit of the relevant currency. + description: Maximum amount per transaction. example: 50000 dailyLimit: type: - integer - 'null' - description: Maximum daily spend, in the smallest unit of the relevant currency. Set to null to remove the daily limit. + description: Maximum daily spend. Set to null to remove the daily limit. example: 500000 dailyTransactionLimit: type: integer @@ -19,5 +23,5 @@ properties: type: - integer - 'null' - description: Maximum monthly spend, in the smallest unit of the relevant currency. Set to null to remove the monthly limit. + description: Maximum monthly spend. Set to null to remove the monthly limit. example: 5000000 From 3941f1c123476d887a299dfcac96b7f691fc271e Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 30 Apr 2026 22:38:23 -0700 Subject: [PATCH 03/12] fix(agents): add title fields to all agent schemas for correct Mintlify type rendering --- mintlify/openapi.yaml | 16 ++++++++++++++++ openapi.yaml | 16 ++++++++++++++++ openapi/components/schemas/agents/Agent.yaml | 1 + .../schemas/agents/AgentAccountRestrictions.yaml | 1 + .../schemas/agents/AgentAccountRule.yaml | 1 + .../schemas/agents/AgentApprovalThresholds.yaml | 1 + .../schemas/agents/AgentCreateRequest.yaml | 1 + .../schemas/agents/AgentCreateResponse.yaml | 1 + .../schemas/agents/AgentDeviceCode.yaml | 1 + .../agents/AgentDeviceCodeRedeemResponse.yaml | 1 + .../agents/AgentDeviceCodeStatusResponse.yaml | 1 + .../schemas/agents/AgentListResponse.yaml | 1 + .../components/schemas/agents/AgentPolicy.yaml | 1 + .../schemas/agents/AgentPolicyUpdateRequest.yaml | 1 + .../schemas/agents/AgentSpendingLimits.yaml | 1 + .../agents/AgentSpendingLimitsUpdate.yaml | 1 + .../schemas/agents/AgentUpdateRequest.yaml | 1 + .../components/schemas/agents/AgentUsage.yaml | 1 + 18 files changed, 48 insertions(+) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index c55b65ea..d9b47359 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -15612,6 +15612,7 @@ components: - APPROVAL_REQUIRED description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' AgentSpendingLimits: + title: Agent Spending Limits type: object description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: @@ -15643,6 +15644,7 @@ components: description: Maximum total amount the agent can transfer per month. Null means no monthly limit. example: 5000000 AgentAccountRule: + title: Agent Account Rule type: object description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: @@ -15661,6 +15663,7 @@ components: description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. example: 10000 AgentAccountRestrictions: + title: Agent Account Restrictions type: object description: Optional restrictions that limit the agent to specific accounts or override policy per account. properties: @@ -15678,6 +15681,7 @@ components: items: $ref: '#/components/schemas/AgentAccountRule' AgentApprovalThresholds: + title: Agent Approval Thresholds type: object description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: @@ -15692,6 +15696,7 @@ components: description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. example: 100000 AgentPolicy: + title: Agent Policy type: object description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: @@ -15713,6 +15718,7 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentUsage: + title: Agent Usage type: object description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: @@ -15742,6 +15748,7 @@ components: description: The year-month (YYYY-MM) when monthly usage counters will reset. example: 2025-08 Agent: + title: Agent type: object description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: @@ -15790,6 +15797,7 @@ components: description: Last update timestamp. example: '2025-07-21T17:32:28Z' AgentListResponse: + title: Agent List Response type: object required: - data @@ -15810,6 +15818,7 @@ components: type: integer description: Total number of agents matching the criteria (excluding pagination). AgentCreateRequest: + title: Agent Create Request type: object required: - name @@ -15827,6 +15836,7 @@ components: policy: $ref: '#/components/schemas/AgentPolicy' AgentDeviceCode: + title: Agent Device Code type: object required: - code @@ -15852,6 +15862,7 @@ components: description: Whether this device code has already been redeemed by the agent. example: false AgentCreateResponse: + title: Agent Create Response type: object description: Response returned when an agent is created, including the agent and a device code for installation. required: @@ -15863,6 +15874,7 @@ components: deviceCode: $ref: '#/components/schemas/AgentDeviceCode' AgentUpdateRequest: + title: Agent Update Request type: object description: Partial update to an agent's basic fields. At least one field must be provided. properties: @@ -15875,6 +15887,7 @@ components: description: Set to true to pause the agent or false to resume it. example: true AgentSpendingLimitsUpdate: + title: Agent Spending Limits Update type: object description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15903,6 +15916,7 @@ components: description: Maximum monthly spend. Set to null to remove the monthly limit. example: 5000000 AgentPolicyUpdateRequest: + title: Agent Policy Update Request type: object description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15920,6 +15934,7 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentDeviceCodeStatusResponse: + title: Agent Device Code Status type: object required: - code @@ -15934,6 +15949,7 @@ components: description: Whether this device code has been redeemed. example: false AgentDeviceCodeRedeemResponse: + title: Agent Device Code Redeem Response type: object required: - agentId diff --git a/openapi.yaml b/openapi.yaml index c55b65ea..d9b47359 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -15612,6 +15612,7 @@ components: - APPROVAL_REQUIRED description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' AgentSpendingLimits: + title: Agent Spending Limits type: object description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: @@ -15643,6 +15644,7 @@ components: description: Maximum total amount the agent can transfer per month. Null means no monthly limit. example: 5000000 AgentAccountRule: + title: Agent Account Rule type: object description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: @@ -15661,6 +15663,7 @@ components: description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. example: 10000 AgentAccountRestrictions: + title: Agent Account Restrictions type: object description: Optional restrictions that limit the agent to specific accounts or override policy per account. properties: @@ -15678,6 +15681,7 @@ components: items: $ref: '#/components/schemas/AgentAccountRule' AgentApprovalThresholds: + title: Agent Approval Thresholds type: object description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: @@ -15692,6 +15696,7 @@ components: description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. example: 100000 AgentPolicy: + title: Agent Policy type: object description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: @@ -15713,6 +15718,7 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentUsage: + title: Agent Usage type: object description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: @@ -15742,6 +15748,7 @@ components: description: The year-month (YYYY-MM) when monthly usage counters will reset. example: 2025-08 Agent: + title: Agent type: object description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: @@ -15790,6 +15797,7 @@ components: description: Last update timestamp. example: '2025-07-21T17:32:28Z' AgentListResponse: + title: Agent List Response type: object required: - data @@ -15810,6 +15818,7 @@ components: type: integer description: Total number of agents matching the criteria (excluding pagination). AgentCreateRequest: + title: Agent Create Request type: object required: - name @@ -15827,6 +15836,7 @@ components: policy: $ref: '#/components/schemas/AgentPolicy' AgentDeviceCode: + title: Agent Device Code type: object required: - code @@ -15852,6 +15862,7 @@ components: description: Whether this device code has already been redeemed by the agent. example: false AgentCreateResponse: + title: Agent Create Response type: object description: Response returned when an agent is created, including the agent and a device code for installation. required: @@ -15863,6 +15874,7 @@ components: deviceCode: $ref: '#/components/schemas/AgentDeviceCode' AgentUpdateRequest: + title: Agent Update Request type: object description: Partial update to an agent's basic fields. At least one field must be provided. properties: @@ -15875,6 +15887,7 @@ components: description: Set to true to pause the agent or false to resume it. example: true AgentSpendingLimitsUpdate: + title: Agent Spending Limits Update type: object description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15903,6 +15916,7 @@ components: description: Maximum monthly spend. Set to null to remove the monthly limit. example: 5000000 AgentPolicyUpdateRequest: + title: Agent Policy Update Request type: object description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15920,6 +15934,7 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentDeviceCodeStatusResponse: + title: Agent Device Code Status type: object required: - code @@ -15934,6 +15949,7 @@ components: description: Whether this device code has been redeemed. example: false AgentDeviceCodeRedeemResponse: + title: Agent Device Code Redeem Response type: object required: - agentId diff --git a/openapi/components/schemas/agents/Agent.yaml b/openapi/components/schemas/agents/Agent.yaml index 65166160..fc5fcebd 100644 --- a/openapi/components/schemas/agents/Agent.yaml +++ b/openapi/components/schemas/agents/Agent.yaml @@ -1,3 +1,4 @@ +title: Agent type: object description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: diff --git a/openapi/components/schemas/agents/AgentAccountRestrictions.yaml b/openapi/components/schemas/agents/AgentAccountRestrictions.yaml index c1b742ac..caeffac5 100644 --- a/openapi/components/schemas/agents/AgentAccountRestrictions.yaml +++ b/openapi/components/schemas/agents/AgentAccountRestrictions.yaml @@ -1,3 +1,4 @@ +title: Agent Account Restrictions type: object description: Optional restrictions that limit the agent to specific accounts or override policy per account. properties: diff --git a/openapi/components/schemas/agents/AgentAccountRule.yaml b/openapi/components/schemas/agents/AgentAccountRule.yaml index b8738f8a..2f97926a 100644 --- a/openapi/components/schemas/agents/AgentAccountRule.yaml +++ b/openapi/components/schemas/agents/AgentAccountRule.yaml @@ -1,3 +1,4 @@ +title: Agent Account Rule type: object description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: diff --git a/openapi/components/schemas/agents/AgentApprovalThresholds.yaml b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml index dcd14c38..08d4a991 100644 --- a/openapi/components/schemas/agents/AgentApprovalThresholds.yaml +++ b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml @@ -1,3 +1,4 @@ +title: Agent Approval Thresholds type: object description: >- Thresholds that force approval for high-value transactions, overriding the default execution mode. diff --git a/openapi/components/schemas/agents/AgentCreateRequest.yaml b/openapi/components/schemas/agents/AgentCreateRequest.yaml index d11e9881..f7d68950 100644 --- a/openapi/components/schemas/agents/AgentCreateRequest.yaml +++ b/openapi/components/schemas/agents/AgentCreateRequest.yaml @@ -1,3 +1,4 @@ +title: Agent Create Request type: object required: - name diff --git a/openapi/components/schemas/agents/AgentCreateResponse.yaml b/openapi/components/schemas/agents/AgentCreateResponse.yaml index a90a6cb2..fedfcd45 100644 --- a/openapi/components/schemas/agents/AgentCreateResponse.yaml +++ b/openapi/components/schemas/agents/AgentCreateResponse.yaml @@ -1,3 +1,4 @@ +title: Agent Create Response type: object description: Response returned when an agent is created, including the agent and a device code for installation. required: diff --git a/openapi/components/schemas/agents/AgentDeviceCode.yaml b/openapi/components/schemas/agents/AgentDeviceCode.yaml index 707d45d7..94dcc3d4 100644 --- a/openapi/components/schemas/agents/AgentDeviceCode.yaml +++ b/openapi/components/schemas/agents/AgentDeviceCode.yaml @@ -1,3 +1,4 @@ +title: Agent Device Code type: object required: - code diff --git a/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml index d43ec606..21715cf9 100644 --- a/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml +++ b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml @@ -1,3 +1,4 @@ +title: Agent Device Code Redeem Response type: object required: - agentId diff --git a/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml b/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml index 926a9c44..993c3416 100644 --- a/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml +++ b/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml @@ -1,3 +1,4 @@ +title: Agent Device Code Status type: object required: - code diff --git a/openapi/components/schemas/agents/AgentListResponse.yaml b/openapi/components/schemas/agents/AgentListResponse.yaml index 04a87763..8fd07c16 100644 --- a/openapi/components/schemas/agents/AgentListResponse.yaml +++ b/openapi/components/schemas/agents/AgentListResponse.yaml @@ -1,3 +1,4 @@ +title: Agent List Response type: object required: - data diff --git a/openapi/components/schemas/agents/AgentPolicy.yaml b/openapi/components/schemas/agents/AgentPolicy.yaml index ac251e1d..a866fa19 100644 --- a/openapi/components/schemas/agents/AgentPolicy.yaml +++ b/openapi/components/schemas/agents/AgentPolicy.yaml @@ -1,3 +1,4 @@ +title: Agent Policy type: object description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: diff --git a/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml b/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml index 8cd1f7fa..39914805 100644 --- a/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml +++ b/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml @@ -1,3 +1,4 @@ +title: Agent Policy Update Request type: object description: >- Partial update to an agent's policy. Only provided fields will be updated; diff --git a/openapi/components/schemas/agents/AgentSpendingLimits.yaml b/openapi/components/schemas/agents/AgentSpendingLimits.yaml index b089c9da..e198b319 100644 --- a/openapi/components/schemas/agents/AgentSpendingLimits.yaml +++ b/openapi/components/schemas/agents/AgentSpendingLimits.yaml @@ -1,3 +1,4 @@ +title: Agent Spending Limits type: object description: >- Spending limits that cap the agent's transaction amounts and frequency. All amount diff --git a/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml index 80c7b865..41360898 100644 --- a/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml +++ b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml @@ -1,3 +1,4 @@ +title: Agent Spending Limits Update type: object description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. properties: diff --git a/openapi/components/schemas/agents/AgentUpdateRequest.yaml b/openapi/components/schemas/agents/AgentUpdateRequest.yaml index 1154a360..c890b543 100644 --- a/openapi/components/schemas/agents/AgentUpdateRequest.yaml +++ b/openapi/components/schemas/agents/AgentUpdateRequest.yaml @@ -1,3 +1,4 @@ +title: Agent Update Request type: object description: Partial update to an agent's basic fields. At least one field must be provided. properties: diff --git a/openapi/components/schemas/agents/AgentUsage.yaml b/openapi/components/schemas/agents/AgentUsage.yaml index 8de13d24..97b79cac 100644 --- a/openapi/components/schemas/agents/AgentUsage.yaml +++ b/openapi/components/schemas/agents/AgentUsage.yaml @@ -1,3 +1,4 @@ +title: Agent Usage type: object description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: From 4b3e77550c3a302110c1b793f30740033d40f1ee Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 30 Apr 2026 22:43:11 -0700 Subject: [PATCH 04/12] Revert "fix(agents): add title fields to all agent schemas for correct Mintlify type rendering" This reverts commit e768ff36f040de508d93a284a8344f76258b7427. --- mintlify/openapi.yaml | 16 ---------------- openapi.yaml | 16 ---------------- openapi/components/schemas/agents/Agent.yaml | 1 - .../schemas/agents/AgentAccountRestrictions.yaml | 1 - .../schemas/agents/AgentAccountRule.yaml | 1 - .../schemas/agents/AgentApprovalThresholds.yaml | 1 - .../schemas/agents/AgentCreateRequest.yaml | 1 - .../schemas/agents/AgentCreateResponse.yaml | 1 - .../schemas/agents/AgentDeviceCode.yaml | 1 - .../agents/AgentDeviceCodeRedeemResponse.yaml | 1 - .../agents/AgentDeviceCodeStatusResponse.yaml | 1 - .../schemas/agents/AgentListResponse.yaml | 1 - .../components/schemas/agents/AgentPolicy.yaml | 1 - .../schemas/agents/AgentPolicyUpdateRequest.yaml | 1 - .../schemas/agents/AgentSpendingLimits.yaml | 1 - .../agents/AgentSpendingLimitsUpdate.yaml | 1 - .../schemas/agents/AgentUpdateRequest.yaml | 1 - .../components/schemas/agents/AgentUsage.yaml | 1 - 18 files changed, 48 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index d9b47359..c55b65ea 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -15612,7 +15612,6 @@ components: - APPROVAL_REQUIRED description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' AgentSpendingLimits: - title: Agent Spending Limits type: object description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: @@ -15644,7 +15643,6 @@ components: description: Maximum total amount the agent can transfer per month. Null means no monthly limit. example: 5000000 AgentAccountRule: - title: Agent Account Rule type: object description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: @@ -15663,7 +15661,6 @@ components: description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. example: 10000 AgentAccountRestrictions: - title: Agent Account Restrictions type: object description: Optional restrictions that limit the agent to specific accounts or override policy per account. properties: @@ -15681,7 +15678,6 @@ components: items: $ref: '#/components/schemas/AgentAccountRule' AgentApprovalThresholds: - title: Agent Approval Thresholds type: object description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: @@ -15696,7 +15692,6 @@ components: description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. example: 100000 AgentPolicy: - title: Agent Policy type: object description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: @@ -15718,7 +15713,6 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentUsage: - title: Agent Usage type: object description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: @@ -15748,7 +15742,6 @@ components: description: The year-month (YYYY-MM) when monthly usage counters will reset. example: 2025-08 Agent: - title: Agent type: object description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: @@ -15797,7 +15790,6 @@ components: description: Last update timestamp. example: '2025-07-21T17:32:28Z' AgentListResponse: - title: Agent List Response type: object required: - data @@ -15818,7 +15810,6 @@ components: type: integer description: Total number of agents matching the criteria (excluding pagination). AgentCreateRequest: - title: Agent Create Request type: object required: - name @@ -15836,7 +15827,6 @@ components: policy: $ref: '#/components/schemas/AgentPolicy' AgentDeviceCode: - title: Agent Device Code type: object required: - code @@ -15862,7 +15852,6 @@ components: description: Whether this device code has already been redeemed by the agent. example: false AgentCreateResponse: - title: Agent Create Response type: object description: Response returned when an agent is created, including the agent and a device code for installation. required: @@ -15874,7 +15863,6 @@ components: deviceCode: $ref: '#/components/schemas/AgentDeviceCode' AgentUpdateRequest: - title: Agent Update Request type: object description: Partial update to an agent's basic fields. At least one field must be provided. properties: @@ -15887,7 +15875,6 @@ components: description: Set to true to pause the agent or false to resume it. example: true AgentSpendingLimitsUpdate: - title: Agent Spending Limits Update type: object description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15916,7 +15903,6 @@ components: description: Maximum monthly spend. Set to null to remove the monthly limit. example: 5000000 AgentPolicyUpdateRequest: - title: Agent Policy Update Request type: object description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15934,7 +15920,6 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentDeviceCodeStatusResponse: - title: Agent Device Code Status type: object required: - code @@ -15949,7 +15934,6 @@ components: description: Whether this device code has been redeemed. example: false AgentDeviceCodeRedeemResponse: - title: Agent Device Code Redeem Response type: object required: - agentId diff --git a/openapi.yaml b/openapi.yaml index d9b47359..c55b65ea 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -15612,7 +15612,6 @@ components: - APPROVAL_REQUIRED description: 'Execution mode controlling whether agent actions require human approval. AUTO: The agent can execute actions autonomously without explicit approval. APPROVAL_REQUIRED: All agent actions require explicit human approval before execution.' AgentSpendingLimits: - title: Agent Spending Limits type: object description: Spending limits that cap the agent's transaction amounts and frequency. All amount fields are integers in the smallest unit of the specified currency. When a transaction is denominated in a different currency, Grid converts using the exchange rate at evaluation time. required: @@ -15644,7 +15643,6 @@ components: description: Maximum total amount the agent can transfer per month. Null means no monthly limit. example: 5000000 AgentAccountRule: - title: Agent Account Rule type: object description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: @@ -15663,7 +15661,6 @@ components: description: Per-transaction limit override, in the smallest unit of the relevant currency. Null inherits from the agent's spending limits. example: 10000 AgentAccountRestrictions: - title: Agent Account Restrictions type: object description: Optional restrictions that limit the agent to specific accounts or override policy per account. properties: @@ -15681,7 +15678,6 @@ components: items: $ref: '#/components/schemas/AgentAccountRule' AgentApprovalThresholds: - title: Agent Approval Thresholds type: object description: Thresholds that force approval for high-value transactions, overriding the default execution mode. When a transaction is denominated in a different currency than the threshold, Grid converts using the exchange rate at evaluation time. properties: @@ -15696,7 +15692,6 @@ components: description: If set, any transaction above this amount (in the smallest unit of the specified currency) will require explicit approval even when the agent's defaultExecutionMode is AUTO. Null means no threshold override. example: 100000 AgentPolicy: - title: Agent Policy type: object description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: @@ -15718,7 +15713,6 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentUsage: - title: Agent Usage type: object description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: @@ -15748,7 +15742,6 @@ components: description: The year-month (YYYY-MM) when monthly usage counters will reset. example: 2025-08 Agent: - title: Agent type: object description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: @@ -15797,7 +15790,6 @@ components: description: Last update timestamp. example: '2025-07-21T17:32:28Z' AgentListResponse: - title: Agent List Response type: object required: - data @@ -15818,7 +15810,6 @@ components: type: integer description: Total number of agents matching the criteria (excluding pagination). AgentCreateRequest: - title: Agent Create Request type: object required: - name @@ -15836,7 +15827,6 @@ components: policy: $ref: '#/components/schemas/AgentPolicy' AgentDeviceCode: - title: Agent Device Code type: object required: - code @@ -15862,7 +15852,6 @@ components: description: Whether this device code has already been redeemed by the agent. example: false AgentCreateResponse: - title: Agent Create Response type: object description: Response returned when an agent is created, including the agent and a device code for installation. required: @@ -15874,7 +15863,6 @@ components: deviceCode: $ref: '#/components/schemas/AgentDeviceCode' AgentUpdateRequest: - title: Agent Update Request type: object description: Partial update to an agent's basic fields. At least one field must be provided. properties: @@ -15887,7 +15875,6 @@ components: description: Set to true to pause the agent or false to resume it. example: true AgentSpendingLimitsUpdate: - title: Agent Spending Limits Update type: object description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15916,7 +15903,6 @@ components: description: Maximum monthly spend. Set to null to remove the monthly limit. example: 5000000 AgentPolicyUpdateRequest: - title: Agent Policy Update Request type: object description: Partial update to an agent's policy. Only provided fields will be updated; omitted fields retain their current values. properties: @@ -15934,7 +15920,6 @@ components: approvalThresholds: $ref: '#/components/schemas/AgentApprovalThresholds' AgentDeviceCodeStatusResponse: - title: Agent Device Code Status type: object required: - code @@ -15949,7 +15934,6 @@ components: description: Whether this device code has been redeemed. example: false AgentDeviceCodeRedeemResponse: - title: Agent Device Code Redeem Response type: object required: - agentId diff --git a/openapi/components/schemas/agents/Agent.yaml b/openapi/components/schemas/agents/Agent.yaml index fc5fcebd..65166160 100644 --- a/openapi/components/schemas/agents/Agent.yaml +++ b/openapi/components/schemas/agents/Agent.yaml @@ -1,4 +1,3 @@ -title: Agent type: object description: A programmatic agent with scoped permissions and a spending policy, used to automate payment workflows. required: diff --git a/openapi/components/schemas/agents/AgentAccountRestrictions.yaml b/openapi/components/schemas/agents/AgentAccountRestrictions.yaml index caeffac5..c1b742ac 100644 --- a/openapi/components/schemas/agents/AgentAccountRestrictions.yaml +++ b/openapi/components/schemas/agents/AgentAccountRestrictions.yaml @@ -1,4 +1,3 @@ -title: Agent Account Restrictions type: object description: Optional restrictions that limit the agent to specific accounts or override policy per account. properties: diff --git a/openapi/components/schemas/agents/AgentAccountRule.yaml b/openapi/components/schemas/agents/AgentAccountRule.yaml index 2f97926a..b8738f8a 100644 --- a/openapi/components/schemas/agents/AgentAccountRule.yaml +++ b/openapi/components/schemas/agents/AgentAccountRule.yaml @@ -1,4 +1,3 @@ -title: Agent Account Rule type: object description: Per-account policy override that takes precedence over the agent's default policy for a specific account. required: diff --git a/openapi/components/schemas/agents/AgentApprovalThresholds.yaml b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml index 08d4a991..dcd14c38 100644 --- a/openapi/components/schemas/agents/AgentApprovalThresholds.yaml +++ b/openapi/components/schemas/agents/AgentApprovalThresholds.yaml @@ -1,4 +1,3 @@ -title: Agent Approval Thresholds type: object description: >- Thresholds that force approval for high-value transactions, overriding the default execution mode. diff --git a/openapi/components/schemas/agents/AgentCreateRequest.yaml b/openapi/components/schemas/agents/AgentCreateRequest.yaml index f7d68950..d11e9881 100644 --- a/openapi/components/schemas/agents/AgentCreateRequest.yaml +++ b/openapi/components/schemas/agents/AgentCreateRequest.yaml @@ -1,4 +1,3 @@ -title: Agent Create Request type: object required: - name diff --git a/openapi/components/schemas/agents/AgentCreateResponse.yaml b/openapi/components/schemas/agents/AgentCreateResponse.yaml index fedfcd45..a90a6cb2 100644 --- a/openapi/components/schemas/agents/AgentCreateResponse.yaml +++ b/openapi/components/schemas/agents/AgentCreateResponse.yaml @@ -1,4 +1,3 @@ -title: Agent Create Response type: object description: Response returned when an agent is created, including the agent and a device code for installation. required: diff --git a/openapi/components/schemas/agents/AgentDeviceCode.yaml b/openapi/components/schemas/agents/AgentDeviceCode.yaml index 94dcc3d4..707d45d7 100644 --- a/openapi/components/schemas/agents/AgentDeviceCode.yaml +++ b/openapi/components/schemas/agents/AgentDeviceCode.yaml @@ -1,4 +1,3 @@ -title: Agent Device Code type: object required: - code diff --git a/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml index 21715cf9..d43ec606 100644 --- a/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml +++ b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml @@ -1,4 +1,3 @@ -title: Agent Device Code Redeem Response type: object required: - agentId diff --git a/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml b/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml index 993c3416..926a9c44 100644 --- a/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml +++ b/openapi/components/schemas/agents/AgentDeviceCodeStatusResponse.yaml @@ -1,4 +1,3 @@ -title: Agent Device Code Status type: object required: - code diff --git a/openapi/components/schemas/agents/AgentListResponse.yaml b/openapi/components/schemas/agents/AgentListResponse.yaml index 8fd07c16..04a87763 100644 --- a/openapi/components/schemas/agents/AgentListResponse.yaml +++ b/openapi/components/schemas/agents/AgentListResponse.yaml @@ -1,4 +1,3 @@ -title: Agent List Response type: object required: - data diff --git a/openapi/components/schemas/agents/AgentPolicy.yaml b/openapi/components/schemas/agents/AgentPolicy.yaml index a866fa19..ac251e1d 100644 --- a/openapi/components/schemas/agents/AgentPolicy.yaml +++ b/openapi/components/schemas/agents/AgentPolicy.yaml @@ -1,4 +1,3 @@ -title: Agent Policy type: object description: Policy governing what an agent can do, how it executes actions, and its spending boundaries. required: diff --git a/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml b/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml index 39914805..8cd1f7fa 100644 --- a/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml +++ b/openapi/components/schemas/agents/AgentPolicyUpdateRequest.yaml @@ -1,4 +1,3 @@ -title: Agent Policy Update Request type: object description: >- Partial update to an agent's policy. Only provided fields will be updated; diff --git a/openapi/components/schemas/agents/AgentSpendingLimits.yaml b/openapi/components/schemas/agents/AgentSpendingLimits.yaml index e198b319..b089c9da 100644 --- a/openapi/components/schemas/agents/AgentSpendingLimits.yaml +++ b/openapi/components/schemas/agents/AgentSpendingLimits.yaml @@ -1,4 +1,3 @@ -title: Agent Spending Limits type: object description: >- Spending limits that cap the agent's transaction amounts and frequency. All amount diff --git a/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml index 41360898..80c7b865 100644 --- a/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml +++ b/openapi/components/schemas/agents/AgentSpendingLimitsUpdate.yaml @@ -1,4 +1,3 @@ -title: Agent Spending Limits Update type: object description: Partial update to spending limits. Only provided fields will be updated; omitted fields retain their current values. properties: diff --git a/openapi/components/schemas/agents/AgentUpdateRequest.yaml b/openapi/components/schemas/agents/AgentUpdateRequest.yaml index c890b543..1154a360 100644 --- a/openapi/components/schemas/agents/AgentUpdateRequest.yaml +++ b/openapi/components/schemas/agents/AgentUpdateRequest.yaml @@ -1,4 +1,3 @@ -title: Agent Update Request type: object description: Partial update to an agent's basic fields. At least one field must be provided. properties: diff --git a/openapi/components/schemas/agents/AgentUsage.yaml b/openapi/components/schemas/agents/AgentUsage.yaml index 97b79cac..8de13d24 100644 --- a/openapi/components/schemas/agents/AgentUsage.yaml +++ b/openapi/components/schemas/agents/AgentUsage.yaml @@ -1,4 +1,3 @@ -title: Agent Usage type: object description: Real-time counters tracking the agent's spending and transaction activity against its policy limits. required: From 28ca2ae97308e7672c8dd3bc2c19014b04453820 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 30 Apr 2026 22:58:07 -0700 Subject: [PATCH 05/12] fix(agents): map AgentAuth in Stainless config and fix approval transaction fields - Add agent_client_id/agent_client_secret opts to stainless.yml client_settings so Stainless can resolve the AgentAuth security scheme (fixes SchemeNotFound error) - Fix approvals-and-audit.mdx to use correct OutgoingTransaction field names: sentAmount/receivedAmount (CurrencyAmount objects) instead of sendingAmount, and correct type discriminator value OUTGOING instead of OUTGOING_PAYMENT --- .stainless/stainless.yml | 21 +++++++++++++++++++ .../agents/approvals-and-audit.mdx | 14 +++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index a5a9cf9d..16a3df25 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -500,6 +500,27 @@ client_settings: role: password description: API token authentication using format `:` read_env: GRID_CLIENT_SECRET + agent_client_id: + type: string + nullable: true + auth: + security_scheme: AgentAuth + role: username + description: >- + Agent client ID obtained from redeeming a device code. Required when calling + agent-scoped endpoints (e.g. `GET /agents/me/...`). Leave unset for platform-scoped + operations. + read_env: GRID_AGENT_CLIENT_ID + agent_client_secret: + type: string + nullable: true + auth: + security_scheme: AgentAuth + role: password + description: >- + Agent client secret obtained from redeeming a device code. Required when calling + agent-scoped endpoints. Leave unset for platform-scoped operations. + read_env: GRID_AGENT_CLIENT_SECRET webhook_signature: type: string nullable: true diff --git a/mintlify/global-accounts/agents/approvals-and-audit.mdx b/mintlify/global-accounts/agents/approvals-and-audit.mdx index a9d520d3..0ad4f8d7 100644 --- a/mintlify/global-accounts/agents/approvals-and-audit.mdx +++ b/mintlify/global-accounts/agents/approvals-and-audit.mdx @@ -49,7 +49,9 @@ Pending approval requests are transactions with a `PENDING` status, returned by - `agentId` — the agent that initiated the action - `customerId` / `platformCustomerId` — the customer on whose behalf the agent acted - `status` — `PENDING` while awaiting approval; updated to `COMPLETED`, `REJECTED`, or `FAILED` after the decision is processed -- `type` — transaction type (e.g. outgoing payment, cross-currency transfer) +- `type` — always `OUTGOING` for agent-initiated payment requests +- `sentAmount` — amount and currency the customer will send +- `receivedAmount` — amount and currency the recipient will receive (may differ for cross-currency transfers) - `destination` — destination account or UMA address - `description` — optional memo set by the agent - `createdAt` / `updatedAt` — timestamps for the request lifecycle @@ -60,10 +62,18 @@ For example, a pending approval request surfaced in your product might look like { "id": "Transaction:019542f5-b3e7-1d02-0000-000000000099", "status": "PENDING", - "type": "OUTGOING_PAYMENT", + "type": "OUTGOING", "agentId": "Agent:019542f5-b3e7-1d02-0000-000000000042", "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000010", "platformCustomerId": "user-a1b2c3", + "sentAmount": { + "amount": 50000, + "currency": "USD" + }, + "receivedAmount": { + "amount": 4625000, + "currency": "INR" + }, "destination": { "type": "EXTERNAL_ACCOUNT", "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" From 947116c282fca7d354b05818c2636089662cc0b3 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 30 Apr 2026 23:00:10 -0700 Subject: [PATCH 06/12] feat(agents): switch AgentAuth to Bearer token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace HTTP Basic (clientId + clientSecret) with a single Bearer access token for agent authentication. Simpler for agent software to configure and store. - AgentAuth security scheme: basic → bearer - AgentDeviceCodeRedeemResponse: drop clientId/clientSecret, add accessToken - stainless.yml: replace agent_client_id/secret opts with single agent_access_token --- .stainless/stainless.yml | 17 +++-------------- mintlify/openapi.yaml | 19 +++++++------------ openapi.yaml | 19 +++++++------------ .../agents/AgentDeviceCodeRedeemResponse.yaml | 18 ++++++------------ openapi/openapi.yaml | 6 +++--- .../agents_device-codes_{code}_redeem.yaml | 4 ++-- 6 files changed, 28 insertions(+), 55 deletions(-) diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index 16a3df25..d32afba6 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -500,27 +500,16 @@ client_settings: role: password description: API token authentication using format `:` read_env: GRID_CLIENT_SECRET - agent_client_id: + agent_access_token: type: string nullable: true auth: security_scheme: AgentAuth - role: username description: >- - Agent client ID obtained from redeeming a device code. Required when calling + Bearer access token obtained by redeeming a device code. Required when calling agent-scoped endpoints (e.g. `GET /agents/me/...`). Leave unset for platform-scoped operations. - read_env: GRID_AGENT_CLIENT_ID - agent_client_secret: - type: string - nullable: true - auth: - security_scheme: AgentAuth - role: password - description: >- - Agent client secret obtained from redeeming a device code. Required when calling - agent-scoped endpoints. Leave unset for platform-scoped operations. - read_env: GRID_AGENT_CLIENT_SECRET + read_env: GRID_AGENT_ACCESS_TOKEN webhook_signature: type: string nullable: true diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index c55b65ea..7d9e6750 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -4985,7 +4985,7 @@ paths: post: summary: Redeem device code description: | - Redeem a device code to obtain agent credentials. This endpoint is called by the agent software during installation. On success, returns a clientId and clientSecret that the agent uses for all subsequent API calls. The secret is returned only once and must be stored securely. + Redeem a device code to obtain agent credentials. This endpoint is called by the agent software during installation. On success, returns a Bearer access token that the agent uses for all subsequent API calls. The token is returned only once and must be stored securely. This endpoint does not require platform authentication — the device code itself serves as proof of authorization. operationId: redeemAgentDeviceCode tags: @@ -6527,8 +6527,8 @@ components: description: API token authentication using format `:` AgentAuth: type: http - scheme: basic - description: 'Agent authentication using format `:`, where the credentials are obtained by 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.' + 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 @@ -15938,8 +15938,7 @@ components: required: - agentId - agentName - - clientId - - clientSecret + - accessToken - policy properties: agentId: @@ -15950,14 +15949,10 @@ components: type: string description: The agent's name. example: Payroll Automation Agent - clientId: + accessToken: type: string - description: The client ID to use as the username in HTTP Basic Authentication when calling Grid API endpoints as this agent. - example: 01947d2284054f890000e63bca4810df - clientSecret: - type: string - description: The client secret to use as the password in HTTP Basic Authentication. This secret is returned only once and must be stored securely — it cannot be retrieved again. - example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + 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' WebhookType: diff --git a/openapi.yaml b/openapi.yaml index c55b65ea..7d9e6750 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -4985,7 +4985,7 @@ paths: post: summary: Redeem device code description: | - Redeem a device code to obtain agent credentials. This endpoint is called by the agent software during installation. On success, returns a clientId and clientSecret that the agent uses for all subsequent API calls. The secret is returned only once and must be stored securely. + Redeem a device code to obtain agent credentials. This endpoint is called by the agent software during installation. On success, returns a Bearer access token that the agent uses for all subsequent API calls. The token is returned only once and must be stored securely. This endpoint does not require platform authentication — the device code itself serves as proof of authorization. operationId: redeemAgentDeviceCode tags: @@ -6527,8 +6527,8 @@ components: description: API token authentication using format `:` AgentAuth: type: http - scheme: basic - description: 'Agent authentication using format `:`, where the credentials are obtained by 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.' + 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 @@ -15938,8 +15938,7 @@ components: required: - agentId - agentName - - clientId - - clientSecret + - accessToken - policy properties: agentId: @@ -15950,14 +15949,10 @@ components: type: string description: The agent's name. example: Payroll Automation Agent - clientId: + accessToken: type: string - description: The client ID to use as the username in HTTP Basic Authentication when calling Grid API endpoints as this agent. - example: 01947d2284054f890000e63bca4810df - clientSecret: - type: string - description: The client secret to use as the password in HTTP Basic Authentication. This secret is returned only once and must be stored securely — it cannot be retrieved again. - example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + 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' WebhookType: diff --git a/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml index d43ec606..48336299 100644 --- a/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml +++ b/openapi/components/schemas/agents/AgentDeviceCodeRedeemResponse.yaml @@ -2,8 +2,7 @@ type: object required: - agentId - agentName - - clientId - - clientSecret + - accessToken - policy properties: agentId: @@ -14,17 +13,12 @@ properties: type: string description: The agent's name. example: Payroll Automation Agent - clientId: + accessToken: type: string description: >- - The client ID to use as the username in HTTP Basic Authentication when calling - Grid API endpoints as this agent. - example: 01947d2284054f890000e63bca4810df - clientSecret: - type: string - description: >- - The client secret to use as the password in HTTP Basic Authentication. This secret - is returned only once and must be stored securely — it cannot be retrieved again. - example: ed0ad25881e234cc28fb2dec0a4fe64e4172 + 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: ./AgentPolicy.yaml diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 2c96719e..375a1a01 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -84,10 +84,10 @@ components: secret>` AgentAuth: type: http - scheme: basic + scheme: bearer description: >- - Agent authentication using format `:`, where the - credentials are obtained by redeeming a device code via + 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. diff --git a/openapi/paths/agents/agents_device-codes_{code}_redeem.yaml b/openapi/paths/agents/agents_device-codes_{code}_redeem.yaml index c156369f..e1eef564 100644 --- a/openapi/paths/agents/agents_device-codes_{code}_redeem.yaml +++ b/openapi/paths/agents/agents_device-codes_{code}_redeem.yaml @@ -9,8 +9,8 @@ post: summary: Redeem device code description: > Redeem a device code to obtain agent credentials. This endpoint is called by the - agent software during installation. On success, returns a clientId and clientSecret - that the agent uses for all subsequent API calls. The secret is returned only once + agent software during installation. On success, returns a Bearer access token + that the agent uses for all subsequent API calls. The token is returned only once and must be stored securely. This endpoint does not require platform authentication — the device code itself From 6e9b748cfd31ba2d51d3c55df5324bbd4e36c4e8 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Thu, 30 Apr 2026 23:03:28 -0700 Subject: [PATCH 07/12] fix(agents): clarify AgentUsage spend currency in field descriptions --- mintlify/openapi.yaml | 4 ++-- openapi.yaml | 4 ++-- openapi/components/schemas/agents/AgentUsage.yaml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index 7d9e6750..de3622b0 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -15726,7 +15726,7 @@ components: example: 3 dailySpend: type: integer - description: Total amount spent by the agent today, in the smallest unit of the relevant currency. + description: Total amount spent by the agent today, in the smallest unit of the policy's `spendingLimits.currency`. example: 150000 dailyResetDate: type: string @@ -15735,7 +15735,7 @@ components: example: '2025-07-22' monthlySpend: type: integer - description: Total amount spent by the agent this month, in the smallest unit of the relevant currency. + description: Total amount spent by the agent this month, in the smallest unit of the policy's `spendingLimits.currency`. example: 750000 monthlyResetMonth: type: string diff --git a/openapi.yaml b/openapi.yaml index 7d9e6750..de3622b0 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -15726,7 +15726,7 @@ components: example: 3 dailySpend: type: integer - description: Total amount spent by the agent today, in the smallest unit of the relevant currency. + description: Total amount spent by the agent today, in the smallest unit of the policy's `spendingLimits.currency`. example: 150000 dailyResetDate: type: string @@ -15735,7 +15735,7 @@ components: example: '2025-07-22' monthlySpend: type: integer - description: Total amount spent by the agent this month, in the smallest unit of the relevant currency. + description: Total amount spent by the agent this month, in the smallest unit of the policy's `spendingLimits.currency`. example: 750000 monthlyResetMonth: type: string diff --git a/openapi/components/schemas/agents/AgentUsage.yaml b/openapi/components/schemas/agents/AgentUsage.yaml index 8de13d24..cf269d87 100644 --- a/openapi/components/schemas/agents/AgentUsage.yaml +++ b/openapi/components/schemas/agents/AgentUsage.yaml @@ -11,7 +11,7 @@ properties: example: 3 dailySpend: type: integer - description: Total amount spent by the agent today, in the smallest unit of the relevant currency. + description: Total amount spent by the agent today, in the smallest unit of the policy's `spendingLimits.currency`. example: 150000 dailyResetDate: type: string @@ -20,7 +20,7 @@ properties: example: '2025-07-22' monthlySpend: type: integer - description: Total amount spent by the agent this month, in the smallest unit of the relevant currency. + description: Total amount spent by the agent this month, in the smallest unit of the policy's `spendingLimits.currency`. example: 750000 monthlyResetMonth: type: string From 42dcaea30f4754c29810ea348aaa6e8640ad3dd0 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Fri, 1 May 2026 06:52:23 -0700 Subject: [PATCH 08/12] feat(agents): add GET /agents/me/internal-accounts endpoint --- mintlify/openapi.yaml | 57 +++++++++++++++++ openapi.yaml | 57 +++++++++++++++++ openapi/openapi.yaml | 2 + .../agents/agents_me_internal-accounts.yaml | 61 +++++++++++++++++++ 4 files changed, 177 insertions(+) create mode 100644 openapi/paths/agents/agents_me_internal-accounts.yaml diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index de3622b0..bd74c0f9 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -5504,6 +5504,63 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /agents/me/internal-accounts: + get: + summary: List agent's internal accounts + description: | + Retrieve the internal accounts belonging to the customer this agent operates on behalf of. Use this to discover available source accounts for transfers and quotes, and to verify which accounts are accessible under the agent's `accountRestrictions` policy. + operationId: agentListInternalAccounts + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: currency + in: query + description: Filter by currency code + required: false + schema: + type: string + - name: type + in: query + description: Filter by internal account type. Use `EMBEDDED_WALLET` to find the self-custodial wallet provisioned for the customer, or `INTERNAL_FIAT` / `INTERNAL_CRYPTO` for platform-managed holding accounts. + required: false + schema: + $ref: '#/components/schemas/InternalAccountType' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/InternalAccountListResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /agents/me/external-accounts: get: summary: List agent external accounts diff --git a/openapi.yaml b/openapi.yaml index de3622b0..bd74c0f9 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -5504,6 +5504,63 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /agents/me/internal-accounts: + get: + summary: List agent's internal accounts + description: | + Retrieve the internal accounts belonging to the customer this agent operates on behalf of. Use this to discover available source accounts for transfers and quotes, and to verify which accounts are accessible under the agent's `accountRestrictions` policy. + operationId: agentListInternalAccounts + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: currency + in: query + description: Filter by currency code + required: false + schema: + type: string + - name: type + in: query + description: Filter by internal account type. Use `EMBEDDED_WALLET` to find the self-custodial wallet provisioned for the customer, or `INTERNAL_FIAT` / `INTERNAL_CRYPTO` for platform-managed holding accounts. + required: false + schema: + $ref: '#/components/schemas/InternalAccountType' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/InternalAccountListResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /agents/me/external-accounts: get: summary: List agent external accounts diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 375a1a01..e72b0a27 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -248,6 +248,8 @@ paths: $ref: paths/agents/agents_me_transfer-in.yaml /agents/me/transfer-out: $ref: paths/agents/agents_me_transfer-out.yaml + /agents/me/internal-accounts: + $ref: paths/agents/agents_me_internal-accounts.yaml /agents/me/external-accounts: $ref: paths/agents/agents_me_external-accounts.yaml /agents/me/external-accounts/{externalAccountId}: diff --git a/openapi/paths/agents/agents_me_internal-accounts.yaml b/openapi/paths/agents/agents_me_internal-accounts.yaml new file mode 100644 index 00000000..7ce79b09 --- /dev/null +++ b/openapi/paths/agents/agents_me_internal-accounts.yaml @@ -0,0 +1,61 @@ +get: + summary: List agent's internal accounts + description: > + Retrieve the internal accounts belonging to the customer this agent operates on behalf of. + Use this to discover available source accounts for transfers and quotes, and to verify + which accounts are accessible under the agent's `accountRestrictions` policy. + operationId: agentListInternalAccounts + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: currency + in: query + description: Filter by currency code + required: false + schema: + type: string + - name: type + in: query + description: >- + Filter by internal account type. Use `EMBEDDED_WALLET` to find the + self-custodial wallet provisioned for the customer, or `INTERNAL_FIAT` / + `INTERNAL_CRYPTO` for platform-managed holding accounts. + required: false + schema: + $ref: ../../components/schemas/customers/InternalAccountType.yaml + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/customers/InternalAccountListResponse.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 From 62bcccadaf595342c5747720e56c4498afe0f3c7 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Fri, 1 May 2026 07:00:42 -0700 Subject: [PATCH 09/12] feat(agents): introduce AgentAction as the unified approval model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All agent-initiated operations now return an AgentAction rather than a raw Quote or Transaction, giving the platform a consistent object to approve/reject with its own status lifecycle (PENDING_APPROVAL → APPROVED/REJECTED/FAILED). - New schemas: AgentAction, AgentActionStatus, AgentActionType, AgentActionListResponse, AgentTransferDetails, AgentActionRejectRequest - execute/transfer-out/transfer-in endpoints now return AgentAction - GET /agents/approvals returns AgentActionListResponse (not TransactionListResponse) - Approval endpoints moved from /agents/{id}/transactions/{id}/approve|reject to /agents/{id}/actions/{id}/approve|reject - New agent-scoped: GET /agents/me/actions and GET /agents/me/actions/{actionId} for polling approval decisions --- mintlify/openapi.yaml | 304 +++++++++++++++--- openapi.yaml | 304 +++++++++++++++--- .../schemas/agents/AgentAction.yaml | 71 ++++ .../agents/AgentActionListResponse.yaml | 19 ++ .../agents/AgentActionRejectRequest.yaml | 6 + .../schemas/agents/AgentActionStatus.yaml | 15 + .../schemas/agents/AgentActionType.yaml | 13 + .../schemas/agents/AgentTransferDetails.yaml | 25 ++ openapi/openapi.yaml | 12 +- openapi/paths/agents/agents_approvals.yaml | 12 +- openapi/paths/agents/agents_me_actions.yaml | 51 +++ .../agents/agents_me_actions_{actionId}.yaml | 43 +++ .../agents_me_quotes_{quoteId}_execute.yaml | 9 +- .../paths/agents/agents_me_transfer-in.yaml | 8 +- .../paths/agents/agents_me_transfer-out.yaml | 8 +- ...{agentId}_actions_{actionId}_approve.yaml} | 34 +- ..._{agentId}_actions_{actionId}_reject.yaml} | 27 +- 17 files changed, 838 insertions(+), 123 deletions(-) create mode 100644 openapi/components/schemas/agents/AgentAction.yaml create mode 100644 openapi/components/schemas/agents/AgentActionListResponse.yaml create mode 100644 openapi/components/schemas/agents/AgentActionRejectRequest.yaml create mode 100644 openapi/components/schemas/agents/AgentActionStatus.yaml create mode 100644 openapi/components/schemas/agents/AgentActionType.yaml create mode 100644 openapi/components/schemas/agents/AgentTransferDetails.yaml create mode 100644 openapi/paths/agents/agents_me_actions.yaml create mode 100644 openapi/paths/agents/agents_me_actions_{actionId}.yaml rename openapi/paths/agents/{agents_{agentId}_transactions_{transactionId}_approve.yaml => agents_{agentId}_actions_{actionId}_approve.yaml} (54%) rename openapi/paths/agents/{agents_{agentId}_transactions_{transactionId}_reject.yaml => agents_{agentId}_actions_{actionId}_reject.yaml} (58%) diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index bd74c0f9..a54c54cd 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -4463,7 +4463,7 @@ paths: get: summary: List agent transaction approval requests description: | - Retrieve a paginated list of transactions initiated by agents that require platform approval. Filter by `agentId` or `customerId` to scope results to a specific agent or customer. Approve or reject individual transactions via `POST /agents/{agentId}/transactions/{transactionId}/approve` or `POST /agents/{agentId}/transactions/{transactionId}/reject`. + Retrieve a paginated list of agent actions that require platform approval. Filter by `agentId` or `customerId` to scope results to a specific agent or customer. Approve or reject individual actions via `POST /agents/{agentId}/actions/{actionId}/approve` or `POST /agents/{agentId}/actions/{actionId}/reject`. operationId: listAgentApprovals tags: - Agent Management @@ -4527,7 +4527,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/TransactionListResponse' + $ref: '#/components/schemas/AgentActionListResponse' '400': description: Bad request - Invalid parameters content: @@ -4798,7 +4798,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /agents/{agentId}/transactions/{transactionId}/approve: + /agents/{agentId}/actions/{actionId}/approve: parameters: - name: agentId in: path @@ -4806,37 +4806,32 @@ paths: required: true schema: type: string - - name: transactionId + - name: actionId in: path - description: Unique identifier of the transaction to approve + description: Unique identifier of the agent action to approve required: true schema: type: string post: - summary: Approve an agent-initiated transaction + summary: Approve an agent action description: | - Approve a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + Approve a pending agent action, allowing Grid to proceed with execution. The action must have status `PENDING_APPROVAL`. Once approved, Grid executes the underlying operation (quote execution or transfer) and the action transitions to `APPROVED`. + For `EXECUTE_QUOTE` actions, note that the underlying quote may have expired between submission and approval — in that case the action will transition to `FAILED` instead. This endpoint is called by the platform's backend using platform credentials, not by the agent itself. - operationId: approveAgentTransaction + operationId: approveAgentAction tags: - Agent Management security: - BasicAuth: [] - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/ApprovePaymentRequest' responses: '200': - description: Transaction approved successfully + description: Action approved successfully. Returns the updated AgentAction. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': - description: Bad request - Transaction cannot be approved + description: Bad request - Action cannot be approved content: application/json: schema: @@ -4848,13 +4843,13 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Agent or transaction not found + description: Agent or action not found content: application/json: schema: $ref: '#/components/schemas/Error404' '409': - description: Conflict - Transaction is not pending approval or has already been processed + description: Conflict - Action is not pending approval or has already been processed content: application/json: schema: @@ -4865,7 +4860,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /agents/{agentId}/transactions/{transactionId}/reject: + /agents/{agentId}/actions/{actionId}/reject: parameters: - name: agentId in: path @@ -4873,18 +4868,18 @@ paths: required: true schema: type: string - - name: transactionId + - name: actionId in: path - description: Unique identifier of the transaction to reject + description: Unique identifier of the agent action to reject required: true schema: type: string post: - summary: Reject an agent-initiated transaction + summary: Reject an agent action description: | - Reject a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + Reject a pending agent action, preventing execution. The action must have status `PENDING_APPROVAL`. Once rejected, the action transitions to `REJECTED` and the underlying operation is not executed. This endpoint is called by the platform's backend using platform credentials, not by the agent itself. - operationId: rejectAgentTransaction + operationId: rejectAgentAction tags: - Agent Management security: @@ -4894,16 +4889,16 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RejectPaymentRequest' + $ref: '#/components/schemas/AgentActionRejectRequest' responses: '200': - description: Transaction rejected successfully + description: Action rejected successfully. Returns the updated AgentAction. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': - description: Bad request - Transaction cannot be rejected + description: Bad request - Action cannot be rejected content: application/json: schema: @@ -4915,13 +4910,13 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Agent or transaction not found + description: Agent or action not found content: application/json: schema: $ref: '#/components/schemas/Error404' '409': - description: Conflict - Transaction is not pending approval or has already been processed + description: Conflict - Action is not pending approval or has already been processed content: application/json: schema: @@ -5318,11 +5313,11 @@ paths: example: MEUCIQDx7k2N0aK4p8f3vR9J6yT5wL1mB0sXnG2hQ4vJ8zYkCgIgZ4rP9dT7eWfU3oM6KjR1qSpNvBwL0tXyA2iG8fH5dE= responses: '200': - description: Quote executed successfully. Transfer has been initiated. + description: 'Action submitted successfully. If the agent''s policy requires approval, the returned `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the policy permits automatic execution, status will be `APPROVED` and `transaction` will be populated. Note: if approval is required, the underlying quote may expire before the platform approves — in that case the action will transition to `FAILED`.' content: application/json: schema: - $ref: '#/components/schemas/Quote' + $ref: '#/components/schemas/AgentAction' '400': description: Bad request - Quote cannot be executed content: @@ -5359,6 +5354,99 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /agents/me/actions: + get: + summary: List agent's own actions + description: | + Retrieve a paginated list of actions submitted by the authenticated agent. Use this to poll for approval decisions after submitting an action that requires approval. + operationId: agentListActions + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: status + in: query + description: Filter by action status + required: false + schema: + $ref: '#/components/schemas/AgentActionStatus' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentActionListResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/actions/{actionId}: + parameters: + - name: actionId + in: path + description: Unique identifier of the agent action + required: true + schema: + type: string + get: + summary: Get an agent action + description: | + Retrieve a specific action submitted by the authenticated agent. Poll this endpoint after submitting an action that requires approval to check whether it has been approved, rejected, or has failed. + operationId: agentGetAction + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentAction' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Action not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /agents/me/transfer-in: post: summary: Create a transfer-in @@ -5397,11 +5485,11 @@ paths: amount: 12550 responses: '201': - description: Transfer-in created successfully + description: Action submitted successfully. If the agent's policy requires approval, the returned `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the policy permits automatic execution, status will be `APPROVED` and `transaction` will be populated. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': description: Bad request - Invalid parameters content: @@ -5469,11 +5557,11 @@ paths: amount: 12550 responses: '201': - description: Transfer-out created successfully + description: Action submitted successfully. If the agent's policy requires approval, the returned `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the policy permits automatic execution, status will be `APPROVED` and `transaction` will be populated. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': description: Bad request - Invalid parameters content: @@ -15919,6 +16007,141 @@ components: $ref: '#/components/schemas/Agent' deviceCode: $ref: '#/components/schemas/AgentDeviceCode' + AgentActionStatus: + type: string + enum: + - PENDING_APPROVAL + - APPROVED + - REJECTED + - FAILED + description: | + Status of an agent action. + + | Status | Description | + |--------|-------------| + | `PENDING_APPROVAL` | Submitted by the agent, awaiting platform approval before execution | + | `APPROVED` | Approved by the platform; execution is in progress or completed | + | `REJECTED` | Rejected by the platform; the underlying transaction was not executed | + | `FAILED` | Approved but execution failed (e.g. quote expired, insufficient funds) | + AgentActionType: + type: string + enum: + - EXECUTE_QUOTE + - TRANSFER_OUT + - TRANSFER_IN + description: | + The type of action the agent is requesting. + + | Type | Description | + |------|-------------| + | `EXECUTE_QUOTE` | Execute a cross-currency quote | + | `TRANSFER_OUT` | Transfer from an internal account to an external account | + | `TRANSFER_IN` | Transfer from an external account to an internal account | + AgentTransferDetails: + type: object + description: Details of a transfer-type agent action (TRANSFER_OUT or TRANSFER_IN). + required: + - amount + - currency + - sourceAccountId + - destinationAccountId + properties: + amount: + type: integer + format: int64 + description: Transfer amount in the smallest unit of the specified currency. + example: 50000 + currency: + type: string + description: ISO 4217 currency code for the transfer amount. + example: USD + sourceAccountId: + type: string + description: ID of the source account (internal or external). + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destinationAccountId: + type: string + description: ID of the destination account (internal or external). + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + AgentAction: + type: object + description: An action submitted by an agent that may require platform approval before execution. All agent-initiated operations (quote execution, transfers) are represented as AgentActions, giving the platform a consistent object to approve, reject, and audit regardless of the underlying operation type. + required: + - id + - agentId + - customerId + - platformCustomerId + - status + - type + - createdAt + - updatedAt + properties: + id: + type: string + description: System-generated unique identifier for this action. + example: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: + type: string + description: The agent that submitted this action. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: + type: string + description: The customer on whose behalf the action was submitted. + example: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: + type: string + description: Platform-specific ID of the customer. + example: user-a1b2c3 + status: + $ref: '#/components/schemas/AgentActionStatus' + type: + $ref: '#/components/schemas/AgentActionType' + quote: + allOf: + - $ref: '#/components/schemas/Quote' + description: The quote being executed. Populated for `EXECUTE_QUOTE` actions; absent for transfer actions. Contains the full amount, currency, destination, and rate details needed to present an approval decision to the user. + transferDetails: + allOf: + - $ref: '#/components/schemas/AgentTransferDetails' + description: Details of the transfer being requested. Populated for `TRANSFER_OUT` and `TRANSFER_IN` actions; absent for `EXECUTE_QUOTE` actions. + transaction: + allOf: + - $ref: '#/components/schemas/TransactionOneOf' + description: The resulting transaction, populated once the action has been approved and execution has begun. Absent while the action is `PENDING_APPROVAL` or `REJECTED`. + rejectionReason: + type: string + 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. @@ -15976,6 +16199,13 @@ components: $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: diff --git a/openapi.yaml b/openapi.yaml index bd74c0f9..a54c54cd 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -4463,7 +4463,7 @@ paths: get: summary: List agent transaction approval requests description: | - Retrieve a paginated list of transactions initiated by agents that require platform approval. Filter by `agentId` or `customerId` to scope results to a specific agent or customer. Approve or reject individual transactions via `POST /agents/{agentId}/transactions/{transactionId}/approve` or `POST /agents/{agentId}/transactions/{transactionId}/reject`. + Retrieve a paginated list of agent actions that require platform approval. Filter by `agentId` or `customerId` to scope results to a specific agent or customer. Approve or reject individual actions via `POST /agents/{agentId}/actions/{actionId}/approve` or `POST /agents/{agentId}/actions/{actionId}/reject`. operationId: listAgentApprovals tags: - Agent Management @@ -4527,7 +4527,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/TransactionListResponse' + $ref: '#/components/schemas/AgentActionListResponse' '400': description: Bad request - Invalid parameters content: @@ -4798,7 +4798,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /agents/{agentId}/transactions/{transactionId}/approve: + /agents/{agentId}/actions/{actionId}/approve: parameters: - name: agentId in: path @@ -4806,37 +4806,32 @@ paths: required: true schema: type: string - - name: transactionId + - name: actionId in: path - description: Unique identifier of the transaction to approve + description: Unique identifier of the agent action to approve required: true schema: type: string post: - summary: Approve an agent-initiated transaction + summary: Approve an agent action description: | - Approve a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + Approve a pending agent action, allowing Grid to proceed with execution. The action must have status `PENDING_APPROVAL`. Once approved, Grid executes the underlying operation (quote execution or transfer) and the action transitions to `APPROVED`. + For `EXECUTE_QUOTE` actions, note that the underlying quote may have expired between submission and approval — in that case the action will transition to `FAILED` instead. This endpoint is called by the platform's backend using platform credentials, not by the agent itself. - operationId: approveAgentTransaction + operationId: approveAgentAction tags: - Agent Management security: - BasicAuth: [] - requestBody: - required: false - content: - application/json: - schema: - $ref: '#/components/schemas/ApprovePaymentRequest' responses: '200': - description: Transaction approved successfully + description: Action approved successfully. Returns the updated AgentAction. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': - description: Bad request - Transaction cannot be approved + description: Bad request - Action cannot be approved content: application/json: schema: @@ -4848,13 +4843,13 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Agent or transaction not found + description: Agent or action not found content: application/json: schema: $ref: '#/components/schemas/Error404' '409': - description: Conflict - Transaction is not pending approval or has already been processed + description: Conflict - Action is not pending approval or has already been processed content: application/json: schema: @@ -4865,7 +4860,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' - /agents/{agentId}/transactions/{transactionId}/reject: + /agents/{agentId}/actions/{actionId}/reject: parameters: - name: agentId in: path @@ -4873,18 +4868,18 @@ paths: required: true schema: type: string - - name: transactionId + - name: actionId in: path - description: Unique identifier of the transaction to reject + description: Unique identifier of the agent action to reject required: true schema: type: string post: - summary: Reject an agent-initiated transaction + summary: Reject an agent action description: | - Reject a pending transaction that was initiated by an agent and is awaiting platform approval. A transaction enters a pending state when the agent's policy requires approval — either because the agent's defaultExecutionMode is APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + Reject a pending agent action, preventing execution. The action must have status `PENDING_APPROVAL`. Once rejected, the action transitions to `REJECTED` and the underlying operation is not executed. This endpoint is called by the platform's backend using platform credentials, not by the agent itself. - operationId: rejectAgentTransaction + operationId: rejectAgentAction tags: - Agent Management security: @@ -4894,16 +4889,16 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RejectPaymentRequest' + $ref: '#/components/schemas/AgentActionRejectRequest' responses: '200': - description: Transaction rejected successfully + description: Action rejected successfully. Returns the updated AgentAction. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': - description: Bad request - Transaction cannot be rejected + description: Bad request - Action cannot be rejected content: application/json: schema: @@ -4915,13 +4910,13 @@ paths: schema: $ref: '#/components/schemas/Error401' '404': - description: Agent or transaction not found + description: Agent or action not found content: application/json: schema: $ref: '#/components/schemas/Error404' '409': - description: Conflict - Transaction is not pending approval or has already been processed + description: Conflict - Action is not pending approval or has already been processed content: application/json: schema: @@ -5318,11 +5313,11 @@ paths: example: MEUCIQDx7k2N0aK4p8f3vR9J6yT5wL1mB0sXnG2hQ4vJ8zYkCgIgZ4rP9dT7eWfU3oM6KjR1qSpNvBwL0tXyA2iG8fH5dE= responses: '200': - description: Quote executed successfully. Transfer has been initiated. + description: 'Action submitted successfully. If the agent''s policy requires approval, the returned `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the policy permits automatic execution, status will be `APPROVED` and `transaction` will be populated. Note: if approval is required, the underlying quote may expire before the platform approves — in that case the action will transition to `FAILED`.' content: application/json: schema: - $ref: '#/components/schemas/Quote' + $ref: '#/components/schemas/AgentAction' '400': description: Bad request - Quote cannot be executed content: @@ -5359,6 +5354,99 @@ paths: application/json: schema: $ref: '#/components/schemas/Error500' + /agents/me/actions: + get: + summary: List agent's own actions + description: | + Retrieve a paginated list of actions submitted by the authenticated agent. Use this to poll for approval decisions after submitting an action that requires approval. + operationId: agentListActions + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: status + in: query + description: Filter by action status + required: false + schema: + $ref: '#/components/schemas/AgentActionStatus' + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentActionListResponse' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' + /agents/me/actions/{actionId}: + parameters: + - name: actionId + in: path + description: Unique identifier of the agent action + required: true + schema: + type: string + get: + summary: Get an agent action + description: | + Retrieve a specific action submitted by the authenticated agent. Poll this endpoint after submitting an action that requires approval to check whether it has been approved, rejected, or has failed. + operationId: agentGetAction + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AgentAction' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '404': + description: Action not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error404' + '500': + description: Internal service error + content: + application/json: + schema: + $ref: '#/components/schemas/Error500' /agents/me/transfer-in: post: summary: Create a transfer-in @@ -5397,11 +5485,11 @@ paths: amount: 12550 responses: '201': - description: Transfer-in created successfully + description: Action submitted successfully. If the agent's policy requires approval, the returned `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the policy permits automatic execution, status will be `APPROVED` and `transaction` will be populated. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': description: Bad request - Invalid parameters content: @@ -5469,11 +5557,11 @@ paths: amount: 12550 responses: '201': - description: Transfer-out created successfully + description: Action submitted successfully. If the agent's policy requires approval, the returned `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the policy permits automatic execution, status will be `APPROVED` and `transaction` will be populated. content: application/json: schema: - $ref: '#/components/schemas/TransactionOneOf' + $ref: '#/components/schemas/AgentAction' '400': description: Bad request - Invalid parameters content: @@ -15919,6 +16007,141 @@ components: $ref: '#/components/schemas/Agent' deviceCode: $ref: '#/components/schemas/AgentDeviceCode' + AgentActionStatus: + type: string + enum: + - PENDING_APPROVAL + - APPROVED + - REJECTED + - FAILED + description: | + Status of an agent action. + + | Status | Description | + |--------|-------------| + | `PENDING_APPROVAL` | Submitted by the agent, awaiting platform approval before execution | + | `APPROVED` | Approved by the platform; execution is in progress or completed | + | `REJECTED` | Rejected by the platform; the underlying transaction was not executed | + | `FAILED` | Approved but execution failed (e.g. quote expired, insufficient funds) | + AgentActionType: + type: string + enum: + - EXECUTE_QUOTE + - TRANSFER_OUT + - TRANSFER_IN + description: | + The type of action the agent is requesting. + + | Type | Description | + |------|-------------| + | `EXECUTE_QUOTE` | Execute a cross-currency quote | + | `TRANSFER_OUT` | Transfer from an internal account to an external account | + | `TRANSFER_IN` | Transfer from an external account to an internal account | + AgentTransferDetails: + type: object + description: Details of a transfer-type agent action (TRANSFER_OUT or TRANSFER_IN). + required: + - amount + - currency + - sourceAccountId + - destinationAccountId + properties: + amount: + type: integer + format: int64 + description: Transfer amount in the smallest unit of the specified currency. + example: 50000 + currency: + type: string + description: ISO 4217 currency code for the transfer amount. + example: USD + sourceAccountId: + type: string + description: ID of the source account (internal or external). + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destinationAccountId: + type: string + description: ID of the destination account (internal or external). + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + AgentAction: + type: object + description: An action submitted by an agent that may require platform approval before execution. All agent-initiated operations (quote execution, transfers) are represented as AgentActions, giving the platform a consistent object to approve, reject, and audit regardless of the underlying operation type. + required: + - id + - agentId + - customerId + - platformCustomerId + - status + - type + - createdAt + - updatedAt + properties: + id: + type: string + description: System-generated unique identifier for this action. + example: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: + type: string + description: The agent that submitted this action. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: + type: string + description: The customer on whose behalf the action was submitted. + example: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: + type: string + description: Platform-specific ID of the customer. + example: user-a1b2c3 + status: + $ref: '#/components/schemas/AgentActionStatus' + type: + $ref: '#/components/schemas/AgentActionType' + quote: + allOf: + - $ref: '#/components/schemas/Quote' + description: The quote being executed. Populated for `EXECUTE_QUOTE` actions; absent for transfer actions. Contains the full amount, currency, destination, and rate details needed to present an approval decision to the user. + transferDetails: + allOf: + - $ref: '#/components/schemas/AgentTransferDetails' + description: Details of the transfer being requested. Populated for `TRANSFER_OUT` and `TRANSFER_IN` actions; absent for `EXECUTE_QUOTE` actions. + transaction: + allOf: + - $ref: '#/components/schemas/TransactionOneOf' + description: The resulting transaction, populated once the action has been approved and execution has begun. Absent while the action is `PENDING_APPROVAL` or `REJECTED`. + rejectionReason: + type: string + 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. @@ -15976,6 +16199,13 @@ components: $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: diff --git a/openapi/components/schemas/agents/AgentAction.yaml b/openapi/components/schemas/agents/AgentAction.yaml new file mode 100644 index 00000000..10561449 --- /dev/null +++ b/openapi/components/schemas/agents/AgentAction.yaml @@ -0,0 +1,71 @@ +type: object +description: >- + An action submitted by an agent that may require platform approval before execution. + All agent-initiated operations (quote execution, transfers) are represented as AgentActions, + giving the platform a consistent object to approve, reject, and audit regardless of the + underlying operation type. +required: + - id + - agentId + - customerId + - platformCustomerId + - status + - type + - createdAt + - updatedAt +properties: + id: + type: string + description: System-generated unique identifier for this action. + example: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: + type: string + description: The agent that submitted this action. + example: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: + type: string + description: The customer on whose behalf the action was submitted. + example: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: + type: string + description: Platform-specific ID of the customer. + example: user-a1b2c3 + status: + $ref: ./AgentActionStatus.yaml + type: + $ref: ./AgentActionType.yaml + quote: + allOf: + - $ref: ../quotes/Quote.yaml + 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: ./AgentTransferDetails.yaml + description: >- + Details of the transfer being requested. Populated for `TRANSFER_OUT` and `TRANSFER_IN` + actions; absent for `EXECUTE_QUOTE` actions. + transaction: + allOf: + - $ref: ../transactions/TransactionOneOf.yaml + 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' diff --git a/openapi/components/schemas/agents/AgentActionListResponse.yaml b/openapi/components/schemas/agents/AgentActionListResponse.yaml new file mode 100644 index 00000000..4aa18755 --- /dev/null +++ b/openapi/components/schemas/agents/AgentActionListResponse.yaml @@ -0,0 +1,19 @@ +type: object +required: + - data + - hasMore +properties: + data: + type: array + description: List of agent actions matching the filter criteria. + items: + $ref: ./AgentAction.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 (only present if hasMore is true). + totalCount: + type: integer + description: Total number of actions matching the criteria (excluding pagination). diff --git a/openapi/components/schemas/agents/AgentActionRejectRequest.yaml b/openapi/components/schemas/agents/AgentActionRejectRequest.yaml new file mode 100644 index 00000000..09da3f87 --- /dev/null +++ b/openapi/components/schemas/agents/AgentActionRejectRequest.yaml @@ -0,0 +1,6 @@ +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. diff --git a/openapi/components/schemas/agents/AgentActionStatus.yaml b/openapi/components/schemas/agents/AgentActionStatus.yaml new file mode 100644 index 00000000..9be66ac7 --- /dev/null +++ b/openapi/components/schemas/agents/AgentActionStatus.yaml @@ -0,0 +1,15 @@ +type: string +enum: + - PENDING_APPROVAL + - APPROVED + - REJECTED + - FAILED +description: | + Status of an agent action. + + | Status | Description | + |--------|-------------| + | `PENDING_APPROVAL` | Submitted by the agent, awaiting platform approval before execution | + | `APPROVED` | Approved by the platform; execution is in progress or completed | + | `REJECTED` | Rejected by the platform; the underlying transaction was not executed | + | `FAILED` | Approved but execution failed (e.g. quote expired, insufficient funds) | diff --git a/openapi/components/schemas/agents/AgentActionType.yaml b/openapi/components/schemas/agents/AgentActionType.yaml new file mode 100644 index 00000000..8b957347 --- /dev/null +++ b/openapi/components/schemas/agents/AgentActionType.yaml @@ -0,0 +1,13 @@ +type: string +enum: + - EXECUTE_QUOTE + - TRANSFER_OUT + - TRANSFER_IN +description: | + The type of action the agent is requesting. + + | Type | Description | + |------|-------------| + | `EXECUTE_QUOTE` | Execute a cross-currency quote | + | `TRANSFER_OUT` | Transfer from an internal account to an external account | + | `TRANSFER_IN` | Transfer from an external account to an internal account | diff --git a/openapi/components/schemas/agents/AgentTransferDetails.yaml b/openapi/components/schemas/agents/AgentTransferDetails.yaml new file mode 100644 index 00000000..d8eb2f5c --- /dev/null +++ b/openapi/components/schemas/agents/AgentTransferDetails.yaml @@ -0,0 +1,25 @@ +type: object +description: Details of a transfer-type agent action (TRANSFER_OUT or TRANSFER_IN). +required: + - amount + - currency + - sourceAccountId + - destinationAccountId +properties: + amount: + type: integer + format: int64 + description: Transfer amount in the smallest unit of the specified currency. + example: 50000 + currency: + type: string + description: ISO 4217 currency code for the transfer amount. + example: USD + sourceAccountId: + type: string + description: ID of the source account (internal or external). + example: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destinationAccountId: + type: string + description: ID of the destination account (internal or external). + example: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index e72b0a27..e36ca6b4 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -225,10 +225,10 @@ paths: $ref: paths/agents/agents_{agentId}_policy.yaml /agents/{agentId}/device-codes: $ref: paths/agents/agents_{agentId}_device-codes.yaml - /agents/{agentId}/transactions/{transactionId}/approve: - $ref: paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml - /agents/{agentId}/transactions/{transactionId}/reject: - $ref: paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml + /agents/{agentId}/actions/{actionId}/approve: + $ref: paths/agents/agents_{agentId}_actions_{actionId}_approve.yaml + /agents/{agentId}/actions/{actionId}/reject: + $ref: paths/agents/agents_{agentId}_actions_{actionId}_reject.yaml /agents/device-codes/{code}/status: $ref: paths/agents/agents_device-codes_{code}_status.yaml /agents/device-codes/{code}/redeem: @@ -244,6 +244,10 @@ paths: $ref: paths/agents/agents_me_quotes_{quoteId}.yaml /agents/me/quotes/{quoteId}/execute: $ref: paths/agents/agents_me_quotes_{quoteId}_execute.yaml + /agents/me/actions: + $ref: paths/agents/agents_me_actions.yaml + /agents/me/actions/{actionId}: + $ref: paths/agents/agents_me_actions_{actionId}.yaml /agents/me/transfer-in: $ref: paths/agents/agents_me_transfer-in.yaml /agents/me/transfer-out: diff --git a/openapi/paths/agents/agents_approvals.yaml b/openapi/paths/agents/agents_approvals.yaml index f79cb704..152d7978 100644 --- a/openapi/paths/agents/agents_approvals.yaml +++ b/openapi/paths/agents/agents_approvals.yaml @@ -1,11 +1,11 @@ get: summary: List agent transaction approval requests description: > - Retrieve a paginated list of transactions initiated by agents that require - platform approval. Filter by `agentId` or `customerId` to scope results to a - specific agent or customer. Approve or reject individual transactions via - `POST /agents/{agentId}/transactions/{transactionId}/approve` or - `POST /agents/{agentId}/transactions/{transactionId}/reject`. + Retrieve a paginated list of agent actions that require platform approval. + Filter by `agentId` or `customerId` to scope results to a specific agent or customer. + Approve or reject individual actions via + `POST /agents/{agentId}/actions/{actionId}/approve` or + `POST /agents/{agentId}/actions/{actionId}/reject`. operationId: listAgentApprovals tags: - Agent Management @@ -69,7 +69,7 @@ get: content: application/json: schema: - $ref: ../../components/schemas/transactions/TransactionListResponse.yaml + $ref: ../../components/schemas/agents/AgentActionListResponse.yaml '400': description: Bad request - Invalid parameters content: diff --git a/openapi/paths/agents/agents_me_actions.yaml b/openapi/paths/agents/agents_me_actions.yaml new file mode 100644 index 00000000..4d9bc27d --- /dev/null +++ b/openapi/paths/agents/agents_me_actions.yaml @@ -0,0 +1,51 @@ +get: + summary: List agent's own actions + description: > + Retrieve a paginated list of actions submitted by the authenticated agent. + Use this to poll for approval decisions after submitting an action that requires approval. + operationId: agentListActions + tags: + - Agent Operations + security: + - AgentAuth: [] + parameters: + - name: status + in: query + description: Filter by action status + required: false + schema: + $ref: ../../components/schemas/agents/AgentActionStatus.yaml + - name: limit + in: query + description: Maximum number of results to return (default 20, max 100) + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 20 + - name: cursor + in: query + description: Cursor for pagination (returned from previous request) + required: false + schema: + type: string + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentActionListResponse.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/agents/agents_me_actions_{actionId}.yaml b/openapi/paths/agents/agents_me_actions_{actionId}.yaml new file mode 100644 index 00000000..4d486a29 --- /dev/null +++ b/openapi/paths/agents/agents_me_actions_{actionId}.yaml @@ -0,0 +1,43 @@ +parameters: + - name: actionId + in: path + description: Unique identifier of the agent action + required: true + schema: + type: string +get: + summary: Get an agent action + description: > + Retrieve a specific action submitted by the authenticated agent. + Poll this endpoint after submitting an action that requires approval to check + whether it has been approved, rejected, or has failed. + operationId: agentGetAction + tags: + - Agent Operations + security: + - AgentAuth: [] + responses: + '200': + description: Successful operation + content: + application/json: + schema: + $ref: ../../components/schemas/agents/AgentAction.yaml + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: ../../components/schemas/errors/Error401.yaml + '404': + description: Action 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/agents/agents_me_quotes_{quoteId}_execute.yaml b/openapi/paths/agents/agents_me_quotes_{quoteId}_execute.yaml index 216e8eb4..c1126e8e 100644 --- a/openapi/paths/agents/agents_me_quotes_{quoteId}_execute.yaml +++ b/openapi/paths/agents/agents_me_quotes_{quoteId}_execute.yaml @@ -47,11 +47,16 @@ post: example: MEUCIQDx7k2N0aK4p8f3vR9J6yT5wL1mB0sXnG2hQ4vJ8zYkCgIgZ4rP9dT7eWfU3oM6KjR1qSpNvBwL0tXyA2iG8fH5dE= responses: '200': - description: Quote executed successfully. Transfer has been initiated. + description: >- + Action submitted successfully. If the agent's policy requires approval, the returned + `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the + policy permits automatic execution, status will be `APPROVED` and `transaction` will + be populated. Note: if approval is required, the underlying quote may expire before + the platform approves — in that case the action will transition to `FAILED`. content: application/json: schema: - $ref: ../../components/schemas/quotes/Quote.yaml + $ref: ../../components/schemas/agents/AgentAction.yaml '400': description: Bad request - Quote cannot be executed content: diff --git a/openapi/paths/agents/agents_me_transfer-in.yaml b/openapi/paths/agents/agents_me_transfer-in.yaml index cd8bef31..3a282417 100644 --- a/openapi/paths/agents/agents_me_transfer-in.yaml +++ b/openapi/paths/agents/agents_me_transfer-in.yaml @@ -44,11 +44,15 @@ post: amount: 12550 responses: '201': - description: Transfer-in created successfully + description: >- + Action submitted successfully. If the agent's policy requires approval, the returned + `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the + policy permits automatic execution, status will be `APPROVED` and `transaction` will + be populated. content: application/json: schema: - $ref: ../../components/schemas/transactions/TransactionOneOf.yaml + $ref: ../../components/schemas/agents/AgentAction.yaml '400': description: Bad request - Invalid parameters content: diff --git a/openapi/paths/agents/agents_me_transfer-out.yaml b/openapi/paths/agents/agents_me_transfer-out.yaml index 05aa4203..57d9a25a 100644 --- a/openapi/paths/agents/agents_me_transfer-out.yaml +++ b/openapi/paths/agents/agents_me_transfer-out.yaml @@ -40,11 +40,15 @@ post: amount: 12550 responses: '201': - description: Transfer-out created successfully + description: >- + Action submitted successfully. If the agent's policy requires approval, the returned + `AgentAction` will have status `PENDING_APPROVAL` and no `transaction` yet. If the + policy permits automatic execution, status will be `APPROVED` and `transaction` will + be populated. content: application/json: schema: - $ref: ../../components/schemas/transactions/TransactionOneOf.yaml + $ref: ../../components/schemas/agents/AgentAction.yaml '400': description: Bad request - Invalid parameters content: diff --git a/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml b/openapi/paths/agents/agents_{agentId}_actions_{actionId}_approve.yaml similarity index 54% rename from openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml rename to openapi/paths/agents/agents_{agentId}_actions_{actionId}_approve.yaml index 5b7f9e50..c85a649b 100644 --- a/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_approve.yaml +++ b/openapi/paths/agents/agents_{agentId}_actions_{actionId}_approve.yaml @@ -5,42 +5,38 @@ parameters: required: true schema: type: string - - name: transactionId + - name: actionId in: path - description: Unique identifier of the transaction to approve + description: Unique identifier of the agent action to approve required: true schema: type: string post: - summary: Approve an agent-initiated transaction + summary: Approve an agent action description: > - Approve a pending transaction that was initiated by an agent and is awaiting - platform approval. A transaction enters a pending state when the agent's policy - requires approval — either because the agent's defaultExecutionMode is - APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + Approve a pending agent action, allowing Grid to proceed with execution. The action + must have status `PENDING_APPROVAL`. Once approved, Grid executes the underlying + operation (quote execution or transfer) and the action transitions to `APPROVED`. + + For `EXECUTE_QUOTE` actions, note that the underlying quote may have expired between + submission and approval — in that case the action will transition to `FAILED` instead. This endpoint is called by the platform's backend using platform credentials, not by the agent itself. - operationId: approveAgentTransaction + operationId: approveAgentAction tags: - Agent Management security: - BasicAuth: [] - requestBody: - required: false - content: - application/json: - schema: - $ref: ../../components/schemas/transactions/ApprovePaymentRequest.yaml responses: '200': - description: Transaction approved successfully + description: Action approved successfully. Returns the updated AgentAction. content: application/json: schema: - $ref: ../../components/schemas/transactions/TransactionOneOf.yaml + $ref: ../../components/schemas/agents/AgentAction.yaml '400': - description: Bad request - Transaction cannot be approved + description: Bad request - Action cannot be approved content: application/json: schema: @@ -52,13 +48,13 @@ post: schema: $ref: ../../components/schemas/errors/Error401.yaml '404': - description: Agent or transaction not found + description: Agent or action not found content: application/json: schema: $ref: ../../components/schemas/errors/Error404.yaml '409': - description: Conflict - Transaction is not pending approval or has already been processed + description: Conflict - Action is not pending approval or has already been processed content: application/json: schema: diff --git a/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml b/openapi/paths/agents/agents_{agentId}_actions_{actionId}_reject.yaml similarity index 58% rename from openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml rename to openapi/paths/agents/agents_{agentId}_actions_{actionId}_reject.yaml index cd08130f..47ae1d1a 100644 --- a/openapi/paths/agents/agents_{agentId}_transactions_{transactionId}_reject.yaml +++ b/openapi/paths/agents/agents_{agentId}_actions_{actionId}_reject.yaml @@ -5,23 +5,22 @@ parameters: required: true schema: type: string - - name: transactionId + - name: actionId in: path - description: Unique identifier of the transaction to reject + description: Unique identifier of the agent action to reject required: true schema: type: string post: - summary: Reject an agent-initiated transaction + summary: Reject an agent action description: > - Reject a pending transaction that was initiated by an agent and is awaiting - platform approval. A transaction enters a pending state when the agent's policy - requires approval — either because the agent's defaultExecutionMode is - APPROVAL_REQUIRED, or the transaction amount exceeds the agent's approvalThresholds. + Reject a pending agent action, preventing execution. The action must have status + `PENDING_APPROVAL`. Once rejected, the action transitions to `REJECTED` and the + underlying operation is not executed. This endpoint is called by the platform's backend using platform credentials, not by the agent itself. - operationId: rejectAgentTransaction + operationId: rejectAgentAction tags: - Agent Management security: @@ -31,16 +30,16 @@ post: content: application/json: schema: - $ref: ../../components/schemas/transactions/RejectPaymentRequest.yaml + $ref: ../../components/schemas/agents/AgentActionRejectRequest.yaml responses: '200': - description: Transaction rejected successfully + description: Action rejected successfully. Returns the updated AgentAction. content: application/json: schema: - $ref: ../../components/schemas/transactions/TransactionOneOf.yaml + $ref: ../../components/schemas/agents/AgentAction.yaml '400': - description: Bad request - Transaction cannot be rejected + description: Bad request - Action cannot be rejected content: application/json: schema: @@ -52,13 +51,13 @@ post: schema: $ref: ../../components/schemas/errors/Error401.yaml '404': - description: Agent or transaction not found + description: Agent or action not found content: application/json: schema: $ref: ../../components/schemas/errors/Error404.yaml '409': - description: Conflict - Transaction is not pending approval or has already been processed + description: Conflict - Action is not pending approval or has already been processed content: application/json: schema: From 3c0839ceb56496cc68a2b765c7133639d3946bd3 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Fri, 1 May 2026 07:08:23 -0700 Subject: [PATCH 10/12] feat(agents): add AGENT_ACTION.PENDING_APPROVAL webhook --- mintlify/openapi.yaml | 100 +++++++++++++++++ openapi.yaml | 100 +++++++++++++++++ .../schemas/webhooks/AgentActionWebhook.yaml | 12 ++ .../schemas/webhooks/WebhookType.yaml | 1 + openapi/openapi.yaml | 2 + openapi/webhooks/agent-action.yaml | 103 ++++++++++++++++++ 6 files changed, 318 insertions(+) create mode 100644 openapi/components/schemas/webhooks/AgentActionWebhook.yaml create mode 100644 openapi/webhooks/agent-action.yaml diff --git a/mintlify/openapi.yaml b/mintlify/openapi.yaml index a54c54cd..823518cd 100644 --- a/mintlify/openapi.yaml +++ b/mintlify/openapi.yaml @@ -5854,6 +5854,92 @@ paths: 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 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 + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentActionWebhook' + examples: + pendingApproval: + summary: Agent action pending approval + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: AGENT_ACTION.PENDING_APPROVAL + timestamp: '2025-10-03T15:00:00Z' + data: + id: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: user-a1b2c3 + status: PENDING_APPROVAL + type: EXECUTE_QUOTE + quote: + id: Quote:019542f5-b3e7-1d02-0000-000000000006 + status: PENDING + expiresAt: '2025-10-03T15:00:30Z' + createdAt: '2025-10-03T15:00:00Z' + source: + sourceType: ACCOUNT + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + sendingCurrency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + receivingCurrency: + code: INR + name: Indian Rupee + symbol: ₹ + decimals: 2 + totalSendingAmount: 50000 + totalReceivingAmount: 4625000 + exchangeRate: 92.5 + feesIncluded: 250 + transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 + createdAt: '2025-10-03T15:00:00Z' + updatedAt: '2025-10-03T15:00:00Z' + responses: + '200': + description: Webhook received and acknowledged. + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' incoming-payment: post: summary: Incoming payment webhook and approval mechanism @@ -16272,6 +16358,7 @@ components: - INVITATION.CLAIMED - BULK_UPLOAD.COMPLETED - BULK_UPLOAD.FAILED + - AGENT_ACTION.PENDING_APPROVAL - TEST description: Type of webhook event in OBJECT.EVENT dot-notation. The part before the dot identifies the resource, the part after identifies the event. This lets consumers route purely on type without inspecting data.status. BaseWebhook: @@ -16293,6 +16380,19 @@ components: format: date-time description: ISO 8601 timestamp of when the webhook was sent example: '2025-08-15T14:32:00Z' + AgentActionWebhook: + allOf: + - $ref: '#/components/schemas/BaseWebhook' + - type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AgentAction' + type: + type: string + enum: + - AGENT_ACTION.PENDING_APPROVAL IncomingPaymentWebhookData: title: Incoming Payment Webhook Data allOf: diff --git a/openapi.yaml b/openapi.yaml index a54c54cd..823518cd 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -5854,6 +5854,92 @@ paths: 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 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 + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/AgentActionWebhook' + examples: + pendingApproval: + summary: Agent action pending approval + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: AGENT_ACTION.PENDING_APPROVAL + timestamp: '2025-10-03T15:00:00Z' + data: + id: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: user-a1b2c3 + status: PENDING_APPROVAL + type: EXECUTE_QUOTE + quote: + id: Quote:019542f5-b3e7-1d02-0000-000000000006 + status: PENDING + expiresAt: '2025-10-03T15:00:30Z' + createdAt: '2025-10-03T15:00:00Z' + source: + sourceType: ACCOUNT + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + sendingCurrency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + receivingCurrency: + code: INR + name: Indian Rupee + symbol: ₹ + decimals: 2 + totalSendingAmount: 50000 + totalReceivingAmount: 4625000 + exchangeRate: 92.5 + feesIncluded: 250 + transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 + createdAt: '2025-10-03T15:00:00Z' + updatedAt: '2025-10-03T15:00:00Z' + responses: + '200': + description: Webhook received and acknowledged. + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: '#/components/schemas/Error401' + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: '#/components/schemas/Error409' incoming-payment: post: summary: Incoming payment webhook and approval mechanism @@ -16272,6 +16358,7 @@ components: - INVITATION.CLAIMED - BULK_UPLOAD.COMPLETED - BULK_UPLOAD.FAILED + - AGENT_ACTION.PENDING_APPROVAL - TEST description: Type of webhook event in OBJECT.EVENT dot-notation. The part before the dot identifies the resource, the part after identifies the event. This lets consumers route purely on type without inspecting data.status. BaseWebhook: @@ -16293,6 +16380,19 @@ components: format: date-time description: ISO 8601 timestamp of when the webhook was sent example: '2025-08-15T14:32:00Z' + AgentActionWebhook: + allOf: + - $ref: '#/components/schemas/BaseWebhook' + - type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/AgentAction' + type: + type: string + enum: + - AGENT_ACTION.PENDING_APPROVAL IncomingPaymentWebhookData: title: Incoming Payment Webhook Data allOf: diff --git a/openapi/components/schemas/webhooks/AgentActionWebhook.yaml b/openapi/components/schemas/webhooks/AgentActionWebhook.yaml new file mode 100644 index 00000000..a1f66b84 --- /dev/null +++ b/openapi/components/schemas/webhooks/AgentActionWebhook.yaml @@ -0,0 +1,12 @@ +allOf: + - $ref: ./BaseWebhook.yaml + - type: object + required: + - data + properties: + data: + $ref: ../agents/AgentAction.yaml + type: + type: string + enum: + - AGENT_ACTION.PENDING_APPROVAL diff --git a/openapi/components/schemas/webhooks/WebhookType.yaml b/openapi/components/schemas/webhooks/WebhookType.yaml index d24a8e54..cc77a2d2 100644 --- a/openapi/components/schemas/webhooks/WebhookType.yaml +++ b/openapi/components/schemas/webhooks/WebhookType.yaml @@ -27,6 +27,7 @@ enum: - INVITATION.CLAIMED - BULK_UPLOAD.COMPLETED - BULK_UPLOAD.FAILED + - AGENT_ACTION.PENDING_APPROVAL - TEST description: >- Type of webhook event in OBJECT.EVENT dot-notation. The part before the dot diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index e36ca6b4..96f695d1 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -259,6 +259,8 @@ paths: /agents/me/external-accounts/{externalAccountId}: $ref: paths/agents/agents_me_external-accounts_{externalAccountId}.yaml webhooks: + agent-action: + $ref: webhooks/agent-action.yaml incoming-payment: $ref: webhooks/incoming-payment.yaml outgoing-payment: diff --git a/openapi/webhooks/agent-action.yaml b/openapi/webhooks/agent-action.yaml new file mode 100644 index 00000000..ab64f43c --- /dev/null +++ b/openapi/webhooks/agent-action.yaml @@ -0,0 +1,103 @@ +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 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 + tags: + - Webhooks + security: + - WebhookSignature: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/webhooks/AgentActionWebhook.yaml' + examples: + pendingApproval: + summary: Agent action pending approval + value: + id: Webhook:019542f5-b3e7-1d02-0000-000000000020 + type: AGENT_ACTION.PENDING_APPROVAL + timestamp: '2025-10-03T15:00:00Z' + data: + id: AgentAction:019542f5-b3e7-1d02-0000-000000000099 + agentId: Agent:019542f5-b3e7-1d02-0000-000000000042 + customerId: Customer:019542f5-b3e7-1d02-0000-000000000010 + platformCustomerId: user-a1b2c3 + status: PENDING_APPROVAL + type: EXECUTE_QUOTE + quote: + id: Quote:019542f5-b3e7-1d02-0000-000000000006 + status: PENDING + expiresAt: '2025-10-03T15:00:30Z' + createdAt: '2025-10-03T15:00:00Z' + source: + sourceType: ACCOUNT + accountId: InternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123 + destination: + destinationType: ACCOUNT + accountId: ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965 + sendingCurrency: + code: USD + name: United States Dollar + symbol: $ + decimals: 2 + receivingCurrency: + code: INR + name: Indian Rupee + symbol: ₹ + decimals: 2 + totalSendingAmount: 50000 + totalReceivingAmount: 4625000 + exchangeRate: 92.5 + feesIncluded: 250 + transactionId: Transaction:019542f5-b3e7-1d02-0000-000000000099 + createdAt: '2025-10-03T15:00:00Z' + updatedAt: '2025-10-03T15:00:00Z' + responses: + '200': + description: Webhook received and acknowledged. + '401': + description: Unauthorized - Signature validation failed + content: + application/json: + schema: + $ref: ../components/schemas/errors/Error401.yaml + '409': + description: Conflict - Webhook has already been processed (duplicate id) + content: + application/json: + schema: + $ref: ../components/schemas/errors/Error409.yaml From 4d606af54ffc21ff6f9c60894874b1507d59fe7c Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Fri, 1 May 2026 07:17:42 -0700 Subject: [PATCH 11/12] fix(agents): add explicit agents resource to Stainless config Maps all agent management endpoints explicitly to prevent stale guessed-config errors after the approve/reject paths moved from /transactions/ to /actions/. --- .stainless/stainless.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.stainless/stainless.yml b/.stainless/stainless.yml index d32afba6..40478f74 100644 --- a/.stainless/stainless.yml +++ b/.stainless/stainless.yml @@ -362,6 +362,43 @@ resources: models: session_list_response: '#/components/schemas/SessionListResponse' + agents: + models: + agent: '#/components/schemas/Agent' + agent_create_request: '#/components/schemas/AgentCreateRequest' + agent_create_response: '#/components/schemas/AgentCreateResponse' + agent_update_request: '#/components/schemas/AgentUpdateRequest' + agent_list_response: '#/components/schemas/AgentListResponse' + agent_device_code: '#/components/schemas/AgentDeviceCode' + agent_device_code_status_response: '#/components/schemas/AgentDeviceCodeStatusResponse' + agent_device_code_redeem_response: '#/components/schemas/AgentDeviceCodeRedeemResponse' + agent_action: '#/components/schemas/AgentAction' + agent_action_list_response: '#/components/schemas/AgentActionListResponse' + agent_action_reject_request: '#/components/schemas/AgentActionRejectRequest' + methods: + create: post /agents + list: get /agents + retrieve: get /agents/{agentId} + update: patch /agents/{agentId} + delete: delete /agents/{agentId} + list_approvals: get /agents/approvals + subresources: + policy: + models: + agent_policy: '#/components/schemas/AgentPolicy' + agent_policy_update_request: '#/components/schemas/AgentPolicyUpdateRequest' + methods: + update: patch /agents/{agentId}/policy + device_codes: + methods: + regenerate: post /agents/{agentId}/device-codes + get_status: get /agents/device-codes/{code}/status + redeem: post /agents/device-codes/{code}/redeem + actions: + methods: + approve: post /agents/{agentId}/actions/{actionId}/approve + reject: post /agents/{agentId}/actions/{actionId}/reject + internal_accounts: methods: export: post /internal-accounts/{id}/export From 39d41f33387a0d8de531d9c7cab9528633b437a6 Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Fri, 1 May 2026 07:18:55 -0700 Subject: [PATCH 12/12] docs(agents): rewrite approvals-and-audit.mdx for AgentAction model Update to reflect current API: AgentAction objects (not Transactions), PENDING_APPROVAL status, AGENT_ACTION.PENDING_APPROVAL webhook flow, new approve/reject endpoint paths, quote/transferDetails fields, and FAILED state for expired quotes. --- .../agents/approvals-and-audit.mdx | 110 ++++++++++-------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/mintlify/global-accounts/agents/approvals-and-audit.mdx b/mintlify/global-accounts/agents/approvals-and-audit.mdx index 0ad4f8d7..0433493d 100644 --- a/mintlify/global-accounts/agents/approvals-and-audit.mdx +++ b/mintlify/global-accounts/agents/approvals-and-audit.mdx @@ -17,74 +17,87 @@ Treat approval requests like first-class user tasks. They should be easy to find ## Approval lifecycle -When an agent requests an action that is not eligible for automatic execution: +When an agent submits an action that is not eligible for automatic execution, Grid creates an `AgentAction` in `PENDING_APPROVAL` status and fires an `AGENT_ACTION.PENDING_APPROVAL` webhook to your backend. The full action payload is included in the webhook body so you can render the approval UI and send a push notification to the customer without a second API call. -1. Grid creates a permission request for your product. -2. Grid dispatches that request to your product, typically via webhook or another configured callback mechanism. -3. Your app or dashboard shows the user the requested amount, source account, destination, and reason. -4. The user approves or rejects the action from that trusted surface. -5. Grid executes or rejects the action based on the latest account and policy state. -6. Grid records the final status and links it to the resulting transaction or quote execution. +1. Agent submits an action (quote execution or transfer). +2. Grid creates an `AgentAction` with `status: PENDING_APPROVAL` and returns it to the agent. +3. Grid fires `AGENT_ACTION.PENDING_APPROVAL` to your webhook endpoint with the full action payload. +4. Your backend sends a push notification to the customer. +5. Your app shows the customer the requested amount, accounts, and reason. +6. The customer approves or rejects from that trusted surface. +7. Your backend calls `POST /agents/{agentId}/actions/{actionId}/approve` or `.../reject`. +8. Grid executes the action and the `AgentAction` transitions to `APPROVED`, then `COMPLETED` — or `REJECTED` if declined. ## Approval outcomes -An approval request shown to the user is still subject to the latest account and policy state when Grid processes the decision. - -For example, between the original request and the final decision: +An approved action is still subject to the latest account and policy state when Grid executes it. Between the original request and your approval decision: - The agent may have been paused - The customer's limits may have been reduced - The permitted accounts may have changed -- Another action may already have consumed the available daily spend +- Another action may have already consumed the available daily spend +- For `EXECUTE_QUOTE` actions, the underlying quote may have expired -An approval in your UI is not always a guarantee that the original request will execute successfully. Your product should be ready to show a final rejected or failed state if the request is no longer valid when Grid processes it. +An approval is not always a guarantee that the action will execute. Your product should be ready to show a `FAILED` state — for example, if a quote expired while waiting for approval. The `AgentAction.status` field reflects the final outcome. -## Activity and audit records +## AgentAction fields -Pending approval requests are transactions with a `PENDING` status, returned by `GET /agents/approvals`. Each record includes: +`GET /agents/approvals` returns a paginated list of `AgentAction` objects. Filter by `agentId` or `customerId` to scope results. Each record includes: -- `id` — transaction identifier -- `agentId` — the agent that initiated the action +- `id` — action identifier (e.g. `AgentAction:...`) +- `agentId` — the agent that submitted the action - `customerId` / `platformCustomerId` — the customer on whose behalf the agent acted -- `status` — `PENDING` while awaiting approval; updated to `COMPLETED`, `REJECTED`, or `FAILED` after the decision is processed -- `type` — always `OUTGOING` for agent-initiated payment requests -- `sentAmount` — amount and currency the customer will send -- `receivedAmount` — amount and currency the recipient will receive (may differ for cross-currency transfers) -- `destination` — destination account or UMA address -- `description` — optional memo set by the agent -- `createdAt` / `updatedAt` — timestamps for the request lifecycle +- `status` — `PENDING_APPROVAL` while awaiting a decision; transitions to `APPROVED`, `REJECTED`, or `FAILED` +- `type` — `EXECUTE_QUOTE`, `TRANSFER_OUT`, or `TRANSFER_IN` +- `quote` — for `EXECUTE_QUOTE` actions, the full quote object including amounts, currencies, exchange rate, and destination +- `transferDetails` — for `TRANSFER_OUT` / `TRANSFER_IN` actions, amount, currency, and source/destination account IDs +- `transaction` — populated after the action is approved and execution begins; absent while pending or rejected +- `rejectionReason` — optional reason string set when your platform rejects the action +- `createdAt` / `updatedAt` — timestamps for the action lifecycle -For example, a pending approval request surfaced in your product might look like: +For example, a pending approval request delivered via webhook might look like: ```json { - "id": "Transaction:019542f5-b3e7-1d02-0000-000000000099", - "status": "PENDING", - "type": "OUTGOING", + "id": "AgentAction:019542f5-b3e7-1d02-0000-000000000099", "agentId": "Agent:019542f5-b3e7-1d02-0000-000000000042", "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000010", "platformCustomerId": "user-a1b2c3", - "sentAmount": { - "amount": 50000, - "currency": "USD" - }, - "receivedAmount": { - "amount": 4625000, - "currency": "INR" - }, - "destination": { - "type": "EXTERNAL_ACCOUNT", - "accountId": "ExternalAccount:a12dcbd6-dced-4ec4-b756-3c3a9ea3d123" + "status": "PENDING_APPROVAL", + "type": "EXECUTE_QUOTE", + "quote": { + "id": "Quote:019542f5-b3e7-1d02-0000-000000000006", + "totalSendingAmount": 50000, + "sendingCurrency": { "code": "USD", "name": "United States Dollar", "symbol": "$", "decimals": 2 }, + "totalReceivingAmount": 4625000, + "receivingCurrency": { "code": "INR", "name": "Indian Rupee", "symbol": "₹", "decimals": 2 }, + "exchangeRate": 92.5, + "feesIncluded": 250, + "expiresAt": "2025-10-03T15:00:30Z" }, - "description": "Send supplier payout", "createdAt": "2025-10-03T15:00:00Z", "updatedAt": "2025-10-03T15:00:00Z" } ``` -This lets you present a clean customer-facing activity feed while preserving an operator-friendly audit trail. +## Approving and rejecting + +Call these endpoints from your platform backend using your platform credentials (`BasicAuth`): + +```bash +# Approve +POST /agents/{agentId}/actions/{actionId}/approve + +# Reject (optional reason body) +POST /agents/{agentId}/actions/{actionId}/reject +{ + "reason": "Transaction amount exceeds customer's current risk limit." +} +``` + +Both return the updated `AgentAction`. The `agentId` and `actionId` are available in the webhook payload. ## Pause and revoke @@ -92,8 +105,8 @@ Customers need immediate control over delegated access. Support at least two controls: -- `Pause`: temporarily block new executions while preserving the agent configuration. -- `Revoke`: permanently remove delegated access and invalidate the agent connection. +- **Pause** — temporarily block new executions while preserving the agent configuration. Use `PATCH /agents/{agentId}` with `isPaused: true`. +- **Revoke** — permanently remove delegated access. Use `DELETE /agents/{agentId}`. Pause is useful for temporary uncertainty. Revoke is appropriate when a device is lost, a credential is exposed, or the customer no longer wants the agent connected. @@ -105,18 +118,19 @@ Your approval UI should answer: - What is the agent trying to do? - Which account is affected? -- How much value is moving? +- How much value is moving, and in what currencies? - Who or what is on the other side of the transaction? - Why is approval required? -If the user cannot answer those questions quickly, the approval surface is too opaque. +All of this information is present in the `AgentAction` payload delivered via webhook. If the user cannot answer those questions quickly, the approval surface is too opaque. ## Integration guidance -- Use Grid events or webhooks to reconcile approval decisions with the final activity and transaction state. -- Treat approval decisions as idempotent in your integration so duplicate taps or retries do not create a confusing UX. -- Preserve status history in your UI instead of collapsing everything into a single final state. -- Make agent connection status, approval queue state, and audit history easy to surface in your apps and dashboards. +- Subscribe to `AGENT_ACTION.PENDING_APPROVAL` webhooks and send the customer a push notification immediately — quote-based actions expire quickly. +- Use `GET /agents/approvals` to build an in-app approval queue as a fallback for users who miss the push notification. +- Treat approval and rejection calls as idempotent in your integration so duplicate taps or retries do not cause confusing UX. +- Show `FAILED` and `REJECTED` outcomes clearly — they are distinct states with different meanings for the customer. +- Make agent connection status, approval queue state, and action history easy to surface close to the customer's account view. Show approvals and audit history close to the account or transaction views users already trust. That reduces confusion and makes agent activity feel like part of the main account lifecycle rather than a separate subsystem.