Agent Bank is the treasury control plane for agents: budgets, wallet funding, approvals, cards, API keys, and ledger-backed audit trails.
Today, the stable public integration surface for Agent Bank is the agent spend REST API on https://api.dino.id/v1.
#What is public today
#Dino spending key (Authorization: Bearer din_...)
POST /v1/spend-requestsGET /v1/spend-requests— cursor-paginated list for this key’s agent account (status,limit,cursor,created_after,idempotency_key,merchant_name_prefix)GET /v1/spend-requests/:idGET /v1/spend-requests/:id/ledger— policy / decision rows for that requestPOST /v1/spend-requests/:id/cancel— whileneeds_approvalGET /v1/balance
#Team API key (workspace)
With spend.read, list spend for a chosen agent account (GET /v1/spend-requests requires agent_account_id), and read any team spend request with GET /v1/spend-requests/:id or GET /v1/spend-requests/:id/ledger. GET /v1/accounts and GET /v1/accounts/:id require accounts.read; the detail route returns policy fields (budgets, thresholds, merchant allow/deny lists, funding summary). Dino keys cannot list all accounts or fetch arbitrary account detail — use GET /v1/balance for the key’s account.
Cross-team transfers: move balance between two Dino workspaces (platform book transfer; recipient accepts). All routes are under /v1/transfers — see the full guide: Cross-Team Transfers.
You can also subscribe to state changes through Agent Spend Webhooks.
#Canonical integration loop
Apply this same loop across server integrations, SDK wrappers, and internal tools:
- Create request:
POST /v1/spend-requests(always idempotent). - Route approvals: if
status=needs_approval, send operator toapproval_url. - Reconcile outcome: consume webhook events first, then fallback to
GET /v1/spend-requests/:id.
#Recommended integration flow
- In dashboard, fund the team wallet. New teams get a default policy profile, card, and key automatically; create extra budgets only when you need isolated caps or workflows.
- Issue or rotate a Dino spending key for the target profile (Cards → View policy → Keys, or API Keys overview).
- Call
POST /v1/spend-requestswith idempotency. - If
status=needs_approval, route operator to approval UI and wait for webhook. - Reconcile final state in your app using webhook event payload or
GET /v1/spend-requests/:id. - Optionally list or filter history with
GET /v1/spend-requests, or inspect the decision trail withGET /v1/spend-requests/:id/ledger.
#Example: create spend request
curl -sS -X POST "https://api.dino.id/v1/spend-requests" \
-H "Authorization: Bearer YOUR_DINO_SPEND_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"amount_cents": 25000,
"currency": "usd",
"merchant_name": "OpenAI",
"reason": "model inference for support agent"
}'
#Example: check request status
curl -sS "https://api.dino.id/v1/spend-requests/req_123" \
-H "Authorization: Bearer YOUR_DINO_SPEND_KEY"
GET /v1/spend-requests/:id is the canonical lifecycle read. It includes:
- decision context (
decision_reason, pluspending_reason/failure_reason) - execution rail (
execution) - chain execution linkage for crypto payouts (
tx_signature,submitted_at, recipient + mint fields)
#Example: list spend requests (with filters)
curl -sS "https://api.dino.id/v1/spend-requests?status=completed&limit=20" \
-H "Authorization: Bearer YOUR_DINO_SPEND_KEY"
Optional query parameters include cursor (from next_cursor), created_after (ISO-8601), idempotency_key (exact match), and merchant_name_prefix (case-insensitive prefix on merchant name). Team API keys must pass agent_account_id (a UUID on your team) on GET /v1/spend-requests.
#Example: spend request ledger
curl -sS "https://api.dino.id/v1/spend-requests/req_123/ledger" \
-H "Authorization: Bearer YOUR_DINO_SPEND_KEY"
#Example: check account budget/balance context
curl -sS "https://api.dino.id/v1/balance" \
-H "Authorization: Bearer YOUR_DINO_SPEND_KEY"
#Core implementation guidance
- Always send
Idempotency-KeyforPOST /v1/spend-requests. - Treat
needs_approvalas pending, not failure. - Use webhooks first, polling second for approval outcomes.
- Never expose spending keys to client-side code.
- Keep LLMs away from raw keys; use a server-side tool boundary.
#Shared status vocabulary
- Decision-time:
approved,declined,needs_approval - Lifecycle/terminal:
completed,cancelled,failed,expired - A request can be approved first, then move through later lifecycle states as execution settles.
#Error handling
Expect machine-readable errors (example):
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded"
}
}
Common codes include:
invalid_api_keyrevoked_api_keyinvalid_requestfunding_source_budget_exceededplan_spend_volume_exceededrate_limited
For the authoritative schema and every operation, use the embedded API Reference (OpenAPI) or GET https://api.dino.id/openapi.