Skip to main content
The Agents API must be enabled for your platform; until it is, agent endpoints answer 403. To enable it, book a demo or reach out to your Lightspark contact.
Agents send money with the same quote-then-execute pattern as the rest of Grid, through agent-scoped endpoints authenticated with the agent’s token. Every send is checked against the agent’s policy and spending pool, and either runs at once or waits for the customer’s approval.

Before the agent can send

  • The policy grants CREATE_QUOTES and EXECUTE_QUOTES.
  • The customer has an ACTIVE delegated key for this agent on the Global Account the agent pays from.
  • The Global Account is funded. See Funding.
The agent finds its source account with GET /agents/me/internal-accounts?type=EMBEDDED_WALLET.

Quote a send

POST /agents/me/quotes takes a source, a destination, lockedCurrencySide and lockedCurrencyAmount. The source is an EMBEDDED_WALLET internal account of the agent’s customer. The destination is one of:
The response is the quote, with its amounts, fees, rate and expiresAt, plus agent-specific fields: destinationChainAddress, destinationLightningInvoice or destinationSparkAddress name what it pays, and minimumReceivingAmount is what a CHAIN_ADDRESS recipient receives. How each destination prices:
  • CHAIN_ADDRESS: with SENDING, the quote commits to the USDB amount; with RECEIVING, to exactly what the destination receives, with fees added to the USDB sent. Grid pays the chain at a locked rate, so minimumReceivingAmount equals totalReceivingAmount. If Grid cannot deliver a RECEIVING amount exactly, it refuses the quote with 400 EXACT_AMOUNT_UNAVAILABLE.
  • LIGHTNING_INVOICE: lockedCurrencySide must be RECEIVING and lockedCurrencyAmount the invoice’s amount in satoshis. Grid pays exactly the invoice and adds the fees to the amount debited. An invoice has one live quote at a time; another quote for it answers 409 INVOICE_ALREADY_USED unless it repeats the same request with the same Idempotency-Key.
403 DESTINATION_NOT_ALLOWED means Grid will not let the agent pay that destination, for example a Spark address that was refused or is held for review on any of the customer’s records of it, or a bank account that is not the customer’s own and ACTIVE.

Execute the quote

Execution returns an AgentAction:
  • Within policy: status: APPROVED with transaction set. Grid signs with the agent’s delegated key and the money moves.
  • Needs approval: status: PENDING_APPROVAL with no transaction yet. This happens when the policy’s defaultExecutionMode (or the source account’s rule) is APPROVAL_REQUIRED, or the amount is above the agent’s approvalThresholds or its spending pool’s approvalThreshold. Grid sends AGENT_ACTION.PENDING_APPROVAL to your platform.
  • Refused: 403 when the policy does not permit the send, a spending limit would be exceeded, the agent has no active delegated key on the wallet, or the destination is no longer allowed. 409 when the quote was already executed, expired, or is in an invalid state.
Executing a quote that already has an action returns that action, so the agent can retry safely. Once executed, a send cannot be cancelled.

Waiting for approval

The agent polls GET /agents/me/actions/{actionId} (or lists GET /agents/me/actions?status=PENDING_APPROVAL) until the status changes. Tell the user in the agent’s own words that the customer has been asked. Without priceTolerance, a pending send expires with its quote, which is often within minutes. Where Grid enables re-quoting for your platform, the action carries priceTolerance and waits until its own expiresAt; an approval after the quote expired quotes the send again. A retry of execute with the first quote’s id still returns the action after approval replaced its quote. See Re-quoted sends.

Idempotency keys

Agents retry. Send an Idempotency-Key (up to 255 characters) on every write so a retry returns the first result instead of moving money twice.

Saved destinations

With MANAGE_EXTERNAL_ACCOUNTS, the agent manages the customer’s external accounts under /agents/me/external-accounts (list, add, read, delete). customerId is inferred from the agent. Grid saves a Spark address under its network’s current prefix (spark1...), so a legacy spelling (sp1...) of a saved address conflicts with it, and refuses to save a Spark address that was refused or is held for review (DESTINATION_NOT_ALLOWED).

Pay a bank account

With MANAGE_EXTERNAL_ACCOUNTS, the agent can save a US bank account as one of the customer’s external accounts and pay it directly, with the same quote and execute flow as any other send.
  1. Save the recipient with POST /agents/me/external-accounts, giving currency: USD and an accountInfo with accountType: USD_ACCOUNT, accountNumber, routingNumber, bankAccountType, bankName and the beneficiary (beneficiaryType, fullName, address). The response is the ExternalAccount. GET /agents/me/external-accounts?currency=USD lists the ones already saved, and an account that already exists is refused with 409. Grid screens the account, and only one it cleared becomes ACTIVE.
  2. Quote the send with POST /agents/me/quotes: destination is { "destinationType": "ACCOUNT", "accountId": "ExternalAccount:..." }, with the wallet as source, lockedCurrencySide and lockedCurrencyAmount. A destination takes no payment rail.
  3. Execute it as in Execute the quote.
The account must be one of the agent’s customer’s saved bank accounts on your platform and ACTIVE. Any other bank account is refused with 403 DESTINATION_NOT_ALLOWED when the agent quotes or executes. If the account is removed while the action waits for approval, approving it fails the action with ADDRESS_REFUSED. A bank payout cannot be called back once it leaves, so above a small amount that Lightspark sets for your platform it waits in PENDING_APPROVAL for the customer, whatever the agent’s defaultExecutionMode and approval thresholds say. At or below that amount the usual rules still apply: APPROVAL_REQUIRED, the approval thresholds and the spending pool can each still hold it for approval. A spending pool counts it as a BANK_PAYOUTS payment.

Withdraw to the customer’s own bank account

Withdrawing is the same send to a bank account the customer owns. The customer’s own account is one of the ACTIVE USD external accounts that GET /agents/me/external-accounts?currency=USD returns, including a bank account your platform validated through Plaid for bank pulls. The agent quotes with that account’s ExternalAccount:... id as the ACCOUNT destination and executes the quote. The same rules apply as for any bank payout: the account must be ACTIVE, a payout above the platform’s small-payout amount always waits for the customer’s approval, and below it the policy and pool rules decide, and 403 DESTINATION_NOT_ALLOWED means Grid will not pay that account.

Pay a person by phone or email

Where your platform enables claimable payouts and agent bank payouts, an agent can send money to someone with no Grid account using POST /agents/me/claimable-payouts. The customer’s KYC status must be APPROVED.
  • Exactly one of phoneNumber and email is set. country defaults to the phone number’s country and is required with email.
  • Grid holds amount against the wallet’s balance and the agent’s limits from creation; the money stays in the wallet until the recipient claims it.
  • The payout is checked as a send of the same amount to a bank account. It needs EXECUTE_QUOTES, counts toward the spending limits, and waits for approval (PENDING_APPROVAL, with a CLAIMABLE_PAYOUT action) above the policy’s or pool’s threshold, in APPROVAL_REQUIRED mode, or above your platform’s limit for bank payouts without approval. Otherwise it is created AWAITING_CLAIM.
  • Once it is AWAITING_CLAIM, your backend issues a claim token with POST /claimable-payouts/{claimablePayoutId}/claim-token, puts it in a link to your own claim page, and sends it to the recipient’s phone or email. The token is returned once, and issuing another replaces it. Never show it to the agent. The recipient chooses how to be paid from what Grid pays out to in her country.
  • The claim window ends 7 days after approval. The agent can cancel with POST /agents/me/claimable-payouts/{claimablePayoutId}/cancel while it is PENDING_APPROVAL or AWAITING_CLAIM, which releases the hold.

Build the claim page

Your claim page takes the recipient from the link to payment:
1

Look up the payout

Call POST /claimable-payouts/claim/lookup with the token. Show only the sender’s name and the amount until the recipient enters a one-time code that you send to the payout’s phone number or email. A forwarded link alone must not be enough to claim the payout.
2

List payout options

Call POST /claimable-payouts/claim/options to list the currencies and rails Grid pays out to in her country, priced for the payout.
3

Lock a quote

Call POST /claimable-payouts/claim/quote with her account details and chosen rail. Grid validates and screens them, saves her as an external account under the sender’s customer, and locks a quote.
4

Confirm the payment

Call POST /claimable-payouts/claim/confirm to pay her on that quote. The payout becomes CLAIMED, then PAID or FAILED.
Because the recipient is saved as an external account, the agent can pay her again later without a link. Statuses are PENDING_APPROVAL, AWAITING_CLAIM, CLAIMED, PAID, EXPIRED, CANCELLED and FAILED. Grid sends CLAIMABLE_PAYOUT.* webhooks when a payout is claimed, paid, expires or fails.

Pay many people at once

Where your platform enables payout runs and agent payout runs, POST /agents/me/payout-runs pays up to 50 rows from the customer’s stablecoin Embedded Wallet in one approved action. Each row pays a contact by phone or email (as a claimable payout) or one of the customer’s own ACTIVE external accounts.
  • Validation is all or nothing: one row the agent may not send refuses the whole request.
  • The run is checked against the policy as one payment of total, and needs CREATE_QUOTES and EXECUTE_QUOTES, plus MANAGE_EXTERNAL_ACCOUNTS when a row pays a contact.
  • It runs at once (PROCESSING) when the policy allows it without approval; otherwise it waits as a PAYOUT_RUN action for up to 24 hours. The customer’s one approval covers every row.
  • Rows succeed or fail one by one. total is what leaves the wallet; each row’s fees come out of what its recipient receives.
  • Preview a run with POST /agents/me/payout-runs/preview first: it returns total, the wallet’s free balance after it, and whether and why it would need approval, without creating or holding anything.
Grid sends a PAYOUT_RUN.* webhook when no row is left to pay.

Split incoming payments

With MANAGE_SETTLEMENT_RULES, and where your platform enables settlement rules, an agent can propose a standing rule that splits the customer’s incoming payments into their stablecoin Embedded Wallet and pays shares onward (POST /agents/me/settlement-rules, previewed with POST /agents/me/settlement-rules/preview). A rule outside what the policy sends without approval waits for the customer as a CREATE_SETTLEMENT_RULE action for up to seven days. Each share is still checked against the agent’s policy when it is paid.

Reading activity

With VIEW_TRANSACTIONS, the agent lists the customer’s transactions with GET /agents/me/transactions (filtered by account, status, type, reference and date) and reads one with GET /agents/me/transactions/{transactionId}. Your platform receives the usual OUTGOING_PAYMENT and INCOMING_PAYMENT webhooks for every send.

Next steps