For the complete documentation index, see llms.txt. This page is also available as Markdown.

Payment Intents API

The canonical Brain HTTP surface for proposing, approving, and executing financial actions is the PaymentIntent family. The agent_id-keyed proposal route from earlier drafts (POST /v1/agents/{agent_id}/propose) and the /v1/actions/* paths are not implemented. Both are documented as deprecated stubs in the spec and return 404. Use the routes below.

Operation
Endpoint

Create (propose)

POST /v1/payment-intents

Get

GET /v1/payment-intents/{id}

Approve (confirm-mode)

POST /v1/payment-intents/{id}/approve

Reject

POST /v1/payment-intents/{id}/reject

Execute (gated)

POST /v1/payment-intents/{id}/execute

Pause / Resume

POST /v1/payment-intents/{id}/{pause,resume}

Replay-investigation

GET /v1/payment-intents/{id}/replay-investigation

Agent-driven full run

POST /v1/agents/run (see Agents API)

Propose a Payment

POST /v1/payment-intents
Authorization: Bearer <token>
Content-Type: application/json

{
  "action_type":                "ach_outbound",
  "source_account_id":          "acct_ops",
  "destination_counterparty_id": "cp_aws",
  "amount":                     "7800.00",
  "currency":                   "USD",
  "invoice_id":                 "inv_8231",
  "evidence_ids":               ["rp_001"]
}

action_type is one of ach_outbound | ach_inbound | wire | onchain_transfer | erp_writeback | card_payment | x402_settle | escrow_release. amount is a decimal string. The valid currency depends on action_type: the two on-chain settlement actions (x402_settle, escrow_release) require USDC and reject three-letter codes, while every other action requires a three-letter code matching ^[A-Z]{3}$ and rejects USDC.

For the special invoice shortcut (resolves amount / currency / counterparty / source / evidence from a Ledger invoice):

Response (201 Created) is a full PaymentIntent with a PolicyDecision already attached:

Errors: 400, 403, 404 (invoice not found / not accessible), 409 (invoice already paid / agent_proposal_duplicate), 422.

Get a PaymentIntent

Returns the same PaymentIntent shape as above. 404 if unknown or tenant-isolated.

Status Lifecycle

Status
Meaning

proposed

Created; Policy is evaluating

pending_approval

Policy returned confirm; awaiting approver signatures

awaiting_second_approval

First approval recorded; a distinct second approver must sign

approved

All required approvals collected (or Policy returned allow)

paused

Kill-switch hold on an approved intent; resume re-runs the gate

dispatching

Gate passed; execution enqueued to the outbox, settling async

rejected

Policy returned reject, or an approver rejected

executed

Rail dispatch succeeded

failed

§6 gate failed or rail dispatch errored

cancelled

Cancelled before approval, or from paused → cancelled

dispatching is a full PaymentIntent state, not an outbox-only one: execute transitions the intent approved → dispatching and it stays there until the outbox worker settles it to executed or failed. The execution row the worker drives has its own separate ExecutionState values (dispatched, in_flight, completed, failed).

SDK status aliases. The SDK's higher-level action.status collapses these HTTP states onto the policy-decision triple: proposed / approvedauto, pending_approvalneeds_approval, rejectedrejected; executed, failed, and cancelled pass through unchanged. So SDK code branching on "auto" is matching the same state HTTP code sees as approved. See Policy → decision vocabulary across surfaces.

Approve a pending_approval Intent

No request body. Returns 200 with the updated PaymentIntent. Approvers are determined by Policy (the confirm rule's required_approvers / quorum); each approver hits this endpoint independently and the intent flips to approved once the quorum is met.

Reject

reason is optional (≤ 500 chars). Returns 200 with the rejected PaymentIntent.

Execute an Approved Intent

No request body. Runs the deterministic §6 pre-execution gate against live Ledger state, then atomically transitions the intent approved → dispatching and enqueues a pending outbox row. The outbox worker dispatches the rail and settles asynchronously.

202 Accepted:

execution_id is null on this immediate response and populated when the worker picks the row up. Settlement notifications arrive via the rail-specific webhook (e.g. Plaid TRANSFER_EVENTS_UPDATE).

A gate failure returns 409 with payment_intent_gate_failed and details naming the failing check (see Errors → Pre-execution gate failures).

Rails

The rail returned on execute is not the same vocabulary as the create-time action_type. The mapping:

rail

Implementation

bank_ach

Plaid Transfer (authorize → create; settled async via webhook)

onchain_base

BrainSmartAccount.executeViaSessionKey (Base)

erp_writeback

NetSuite SuiteTalk (fail-closed stub)

x402_base

USDC-on-Base settlement (mapped from x402_settle; unregistered at boot, fail-closed)

escrow_base

BrainEscrow lock release (mapped from escrow_release; unregistered at boot, fail-closed)

notification

Surface-to-human (no money path)

The x402_base and escrow_base rails are shadow-first: they throw rather than fake-settle until promoted.

Pause / Resume (Kill-Switch)

An approved intent can be held without a terminal transition, then released:

No request body for either. Resume re-evaluates the §6 gate against the current Ledger state. Defending against drift while paused. And returns 409 if any check now fails.

A halted agent (POST /v1/agents/{agent_id}/halt) pauses every one of its in-flight intents at once.

Replay Investigation

Typed forensic record. The intent, each execution (with its typed rail receipt), and the linking ids you'd join to reconstruct exactly what happened:

The policy decision and the audit chain are referenced by id and joined via their owning service APIs (Policy + Audit).

Agent-Driven Runs

Most agent activity goes through the higher-level run endpoint, which routes → resolves an action → dry-runs the §6 gate → persists an agent_runs row → proposes through this same gated path:

See the Agents API for the full run / routing / kill-switch surface.

What's Next

📜 Audit API

Pull proofs for executed PaymentIntents.

🤖 Agents API

Register agents, route events, run agents.

Last updated