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.Before the agent can send
- The policy grants
CREATE_QUOTESandEXECUTE_QUOTES. - The customer has an
ACTIVEdelegated key for this agent on the Global Account the agent pays from. - The Global Account is funded. See Funding.
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:
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: withSENDING, the quote commits to theUSDBamount; withRECEIVING, to exactly what the destination receives, with fees added to theUSDBsent. Grid pays the chain at a locked rate, sominimumReceivingAmountequalstotalReceivingAmount. If Grid cannot deliver aRECEIVINGamount exactly, it refuses the quote with400 EXACT_AMOUNT_UNAVAILABLE.LIGHTNING_INVOICE:lockedCurrencySidemust beRECEIVINGandlockedCurrencyAmountthe 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 answers409 INVOICE_ALREADY_USEDunless it repeats the same request with the sameIdempotency-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
AgentAction:
- Within policy:
status: APPROVEDwithtransactionset. Grid signs with the agent’s delegated key and the money moves. - Needs approval:
status: PENDING_APPROVALwith notransactionyet. This happens when the policy’sdefaultExecutionMode(or the source account’s rule) isAPPROVAL_REQUIRED, or the amount is above the agent’sapprovalThresholdsor its spending pool’sapprovalThreshold. Grid sendsAGENT_ACTION.PENDING_APPROVALto your platform. - Refused:
403when 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.409when the quote was already executed, expired, or is in an invalid state.
Waiting for approval
The agent pollsGET /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 anIdempotency-Key (up to 255 characters) on every write so a retry returns the first result instead of moving money twice.
Saved destinations
WithMANAGE_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
WithMANAGE_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.
- Save the recipient with
POST /agents/me/external-accounts, givingcurrency: USDand anaccountInfowithaccountType: USD_ACCOUNT,accountNumber,routingNumber,bankAccountType,bankNameand thebeneficiary(beneficiaryType,fullName,address). The response is theExternalAccount.GET /agents/me/external-accounts?currency=USDlists the ones already saved, and an account that already exists is refused with409. Grid screens the account, and only one it cleared becomesACTIVE. - Quote the send with
POST /agents/me/quotes:destinationis{ "destinationType": "ACCOUNT", "accountId": "ExternalAccount:..." }, with the wallet assource,lockedCurrencySideandlockedCurrencyAmount. A destination takes no payment rail. - Execute it as in Execute the quote.
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 theACTIVE 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 usingPOST /agents/me/claimable-payouts. The customer’s KYC status must be APPROVED.
- Exactly one of
phoneNumberandemailis set.countrydefaults to the phone number’s country and is required withemail. - Grid holds
amountagainst 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 aCLAIMABLE_PAYOUTaction) above the policy’s or pool’s threshold, inAPPROVAL_REQUIREDmode, or above your platform’s limit for bank payouts without approval. Otherwise it is createdAWAITING_CLAIM. - Once it is
AWAITING_CLAIM, your backend issues a claim token withPOST /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}/cancelwhile it isPENDING_APPROVALorAWAITING_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.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 needsCREATE_QUOTESandEXECUTE_QUOTES, plusMANAGE_EXTERNAL_ACCOUNTSwhen a row pays a contact. - It runs at once (
PROCESSING) when the policy allows it without approval; otherwise it waits as aPAYOUT_RUNaction for up to 24 hours. The customer’s one approval covers every row. - Rows succeed or fail one by one.
totalis what leaves the wallet; each row’s fees come out of what its recipient receives. - Preview a run with
POST /agents/me/payout-runs/previewfirst: it returnstotal, the wallet’s free balance after it, and whether and why it would need approval, without creating or holding anything.
PAYOUT_RUN.* webhook when no row is left to pay.
Split incoming payments
WithMANAGE_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
WithVIEW_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.