• Pricing
  • Story
  • Sign in
Get started
Docs/Crypto Payouts API v1 — Solana USDC

Crypto Payouts API v1 — Solana USDC

Live `/v1/crypto/*` API for governed Solana USDC payouts.

Status: Implemented

This page describes the live public API for governed USDC payouts on Solana. These routes are implemented in apps/api/src/rest/routers/agent-spend-v1.ts.

#Scope

  • Chain: solana
  • Asset: USDC
  • Mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
  • Decimals: 6
  • Auth: Dino spending keys (din_...) and team API keys (dba_..., legacy mid_...)

For devnet wallet testing, use Crypto devnet guide. Dino's sandbox faucet is USD-only and does not mint SOL or USDC.

#AI agents: natural language → tool → Dino

Same pattern as Connecting AI Agents to Dino: the model proposes the payout; your server or MCP tool injects the bearer token and Idempotency-Key on POST /v1/crypto/payout-intents. Never paste spending keys into chat or prompts.

Example tools: create_crypto_payout_intent(amount_atomic, recipient_address, reason?, merchant_name?, idempotency_key?, metadata?) → POST /v1/crypto/payout-intents; get_crypto_payout_intent(id) → GET /v1/crypto/payout-intents/:id. Approve / decline require a team API key or dashboard (spending keys cannot approve).

For MCP, keep calling these REST routes from a trusted process. See Assistant and MCP Integration.

#Endpoints

  • GET /v1/crypto/capabilities — Dino spending key or team API key
  • GET /v1/crypto/balance — team API key only
  • POST /v1/crypto/payout-intents — Dino spending key or team API key
  • GET /v1/crypto/payout-intents — Dino spending key or team API key
  • GET /v1/crypto/payout-intents/:id — Dino spending key or team API key
  • POST /v1/crypto/payout-intents/:id/cancel — Dino spending key or team API key; only while status is needs_approval
  • POST /v1/crypto/payout-intents/:id/approve — team API key only
  • POST /v1/crypto/payout-intents/:id/decline — team API key only
  • GET /v1/crypto/recipients — team API key only
  • POST /v1/crypto/recipients — team API key only
  • PATCH /v1/crypto/recipients/:id — team API key only

#Execution Modes

  • Create supports workspace_custodial only (workspace USDC custody).
  • Read models may still return user_wallet for older linked-wallet spend rows (compatibility only; not advertised for new integrations).

#Payout Lifecycle

Returned status values can include:

  • needs_approval
  • approved
  • awaiting_signature
  • submitted
  • completed
  • failed
  • declined
  • cancelled
  • expired

#Auth notes

  • Team API keys must include the matching spend scope: spend.read for reads, spend.write for writes.
  • Dino spending keys cannot approve, decline, or manage saved recipients.
  • GET /v1/crypto/balance is workspace-scoped and requires a team API key.
  • GET /v1/crypto/balance is read-only and returns zeroed balances when the workspace has no crypto wallet yet.

#Example: create payout intent

curl -sS -X POST "https://api.dino.id/v1/crypto/payout-intents" \
  -H "Authorization: Bearer YOUR_DINO_SPEND_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "amount_atomic": "12500000",
    "chain": "solana",
    "asset_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "recipient_address": "7xKXtg2CWJ1Axn7x2LQ5vF7oWQ8B8yrW5K8J2R6dJ1QH",
    "merchant_name": "Payout recipient",
    "reason": "Affiliate payout",
    "execution_mode": "workspace_custodial",
    "metadata": { "invoice_id": "inv_123" }
  }'

#Example: read payout status

curl -sS "https://api.dino.id/v1/crypto/payout-intents/cpi_123" \
  -H "Authorization: Bearer YOUR_DINO_SPEND_KEY"

Current response fields include:

  • pending_reason
  • failure_reason
  • tx_signature
  • submitted_at
  • idempotency_key

#Runnable example

The monorepo includes a REST-only quickstart that reads capabilities, creates a payout intent, and reads it back:

cd examples/crypto-payout-quickstart
cp .env.example .env
bun run start

See examples/crypto-payout-quickstart.

#List Filters

GET /v1/crypto/payout-intents currently supports:

  • status
  • limit
  • cursor
  • created_after
  • agent_account_id
  • idempotency_key
  • merchant_name_prefix
  • execution_mode

#Error Model

Common error.code values include:

  • invalid_request
  • insufficient_scope
  • not_found
  • policy_declined
  • idempotency_key_conflict

#Webhooks

Crypto payout webhooks currently include:

  • crypto_payout.created
  • crypto_payout.needs_approval
  • crypto_payout.approved
  • crypto_payout.submitted
  • crypto_payout.confirmed
  • crypto_payout.failed
  • crypto_payout.expired
  • crypto_payout.cancelled
  • crypto_payout.declined

Payload note: event types are crypto-specific, but the body may still use the generic data.spend shape (same fields as spend_request.* webhooks — e.g. amount_cents, no chain, mint, recipient, or tx_signature) until an explicitly crypto-shaped payload ships or the generic shape is documented as the supported contract.

Integration-complete checklist: remove the unsafe unknown-status → approved fallback in mapCryptoIntentStatus (agent-spend-v1.ts), and ship crypto-shaped webhook payloads (or formally version/document the generic envelope) before promising crypto fields to external integrators.

#Related docs

  • API Reference
  • Crypto devnet guide
  • Agent Bank API
  • Purchase Intents API
Proxy cards: issue, manage, test