Skip to main content

Budget Requests

Budget requests let an agent ask for a spending budget that a human reviews and approves in the dashboard. Once approved, spend is tracked against the approved amount across all payment types (standard, x402, MPP, card). When the budget is exhausted, further payments are blocked.
Budget requests are optional. If no active budget exists for an agent, all payment flows work normally using existing spend limits and policies. When an active budget does exist, both the budget and policies must pass for a payment to go through.

How It Works

Agent                                    Human (Dashboard)
  │                                          │
  ├─ request_budget ──────────────────────>  │ Sees request in Budgets tab
  │  (amount, purpose)                       │
  │                                          │
  ├─ get_budget_request ◄──────────────────  │ Approves (optionally adjusts
  │  (polls for APPROVED)                    │ amount) or rejects
  │                                          │
  ├─ Makes payments normally:                │
  │  • payments/request ──> budget check     │
  │  • x402/pre-authorize ──> budget check   │
  │  • mpp/pre-authorize ──> budget check    │
  │  • After execution ──> spend decremented │
  │                                          │
  └─ Budget exhausted → payments blocked     │ Sees spend progress bar

Lifecycle

A budget request moves through these states:
StatusDescription
PENDINGAwaiting human review. Expires 24h after creation if not acted on.
APPROVEDHuman approved. Spend is tracked. Expires at a set time (default 24h after approval).
REJECTEDHuman rejected with an optional reason.
EXPIREDTimed out without approval, or approved budget window elapsed.
EXHAUSTEDApproved budget fully spent (currentSpend >= approvedAmount).
Constraints:
  • One active (PENDING or APPROVED) budget request per agent at a time
  • Creating a new request while one is active returns 409 BUDGET_REQUEST_EXISTS

SDK API

Create a Budget Request

curl -X POST https://conto.finance/api/sdk/budget-request \
  -H "Authorization: Bearer $CONTO_SDK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50,
    "purpose": "Research 200 companies via StableEnrich and generate reports",
    "category": "API_PROVIDER"
  }'
Parameters:
ParameterTypeRequiredDescription
amountnumberYesRequested budget in USDC
purposestringYesWhat this budget is for (shown to the reviewer)
categorystringNoSpend category (e.g., API_PROVIDER, INFRASTRUCTURE)
metadataobjectNoArbitrary context (JSON)
Response (201):
{
  "budgetRequestId": "cmm59z...",
  "status": "PENDING",
  "requestedAmount": 50.00,
  "purpose": "Research 200 companies via StableEnrich and generate reports",
  "category": "API_PROVIDER",
  "createdAt": "2026-04-07T12:00:00.000Z"
}
Error (409) — active request already exists:
{
  "error": "Agent already has an active budget request",
  "code": "BUDGET_REQUEST_EXISTS",
  "existingBudgetRequestId": "cmm58y..."
}

Check Budget Request Status

curl https://conto.finance/api/sdk/budget-request?status=APPROVED \
  -H "Authorization: Bearer $CONTO_SDK_KEY"
Query Parameters:
ParameterTypeRequiredDescription
idstringNoSpecific budget request ID
statusstringNoFilter: PENDING, APPROVED, REJECTED, EXPIRED, EXHAUSTED
Response (200):
{
  "budgetRequests": [
    {
      "id": "cmm59z...",
      "status": "APPROVED",
      "requestedAmount": 50.00,
      "approvedAmount": 25.00,
      "currentSpend": 12.50,
      "remainingBudget": 12.50,
      "purpose": "Research 200 companies via StableEnrich and generate reports",
      "category": "API_PROVIDER",
      "expiresAt": "2026-04-08T12:00:00.000Z",
      "createdAt": "2026-04-07T12:00:00.000Z"
    }
  ]
}

MCP Tools

request_budget

Request a spending budget for payments. Submits a request for human approval. Only one active budget request per agent at a time. Applies to all payment types.
ParameterTypeRequiredDescription
amountnumberYesRequested budget in USDC
purposestringYesWhat this budget is for (shown to reviewer)
categorystringNoSpend category (e.g., API_PROVIDER, INFRASTRUCTURE)
metadataobjectNoAdditional context

get_budget_request

Check status and remaining balance of your budget requests. Use to poll for approval and monitor remaining budget.
ParameterTypeRequiredDescription
budgetRequestIdstringNoSpecific request ID
statusstringNoFilter: PENDING, APPROVED, REJECTED, EXPIRED, EXHAUSTED

Payment Flow Integration

When an active (approved, non-expired) budget exists, every payment flow checks it automatically: Pre-execution (blocking):
  • payments/request — checks budget before policy evaluation
  • payments/approve — checks budget for external wallet payments
  • x402/pre-authorize — checks budget before authorizing x402 payments
  • mpp/pre-authorize — checks budget before authorizing MPP payments
Post-execution (decrement):
  • payments/execute — decrements budget after successful execution
  • x402/record — decrements budget when recording x402 payments
  • mpp/record — decrements budget when recording MPP payments
If a payment would exceed the remaining budget, it is denied with a budgetRequest object in the response:
{
  "authorized": false,
  "reasons": ["Payment of $30.00 exceeds remaining budget of $12.50"],
  "budgetRequest": {
    "id": "cmm59z...",
    "approvedAmount": 25.00,
    "currentSpend": 12.50,
    "remainingBudget": 12.50
  }
}

Dashboard

Budget requests appear in the Budgets tab on the Alerts & Approvals page. Pending requests show:
  • Agent name, purpose, requested amount, category
  • Approve / Reject buttons
  • Optional amount adjustment field (approve a different amount than requested)
Approved requests show:
  • Spend progress bar (currentSpend / approvedAmount)
  • Remaining balance and expiry countdown
  • Whether the amount was adjusted from the original request
Completed requests (rejected, expired, exhausted) show their final state.

Approving a Request

curl -X POST https://conto.finance/api/budget-requests/{id}/decide \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "decision": "APPROVED",
    "approvedAmount": 25.00,
    "expiresInHours": 48
  }'
ParameterTypeRequiredDescription
decisionstringYesAPPROVED or REJECTED
approvedAmountnumberNoOverride amount (defaults to requested amount)
expiresInHoursnumberNoBudget window in hours (default: 24)
commentstringNoOptional note

Audit Trail

Every state transition creates an audit log entry:
TransitionActionActor
Agent creates requestCREATEAgent
Human approvesAPPROVEUser
Human rejectsREJECTUser
Spend recordedUPDATEAgent
Budget exhaustedUPDATESystem
Budget expiredUPDATESystem

Example: Agent Workflow

// 1. Request a budget
const budget = await fetch('/api/sdk/budget-request', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 50,
    purpose: 'Research 200 companies via paid APIs',
    category: 'API_PROVIDER',
  }),
}).then(r => r.json());

console.log('Budget request:', budget.budgetRequestId); // PENDING

// 2. Poll for approval
let approved = false;
while (!approved) {
  const status = await fetch(
    `/api/sdk/budget-request?id=${budget.budgetRequestId}`,
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  ).then(r => r.json());

  const req = status.budgetRequests[0];
  if (req.status === 'APPROVED') {
    console.log(`Approved: $${req.approvedAmount} budget`);
    approved = true;
  } else if (req.status === 'REJECTED' || req.status === 'EXPIRED') {
    throw new Error(`Budget ${req.status}`);
  }

  await new Promise(r => setTimeout(r, 5000));
}

// 3. Make payments normally — budget is enforced automatically
await conto.payments.pay({
  amount: 0.05,
  recipientAddress: '0x...',
  purpose: 'StableEnrich API call',
});
// Budget decremented: $49.95 remaining

Next Steps

Payments

Standard payment request and execution

x402 Payments

HTTP 402 micropayment handling

Spend Limits

Configure wallet spend limits

MCP Tools

Full MCP tools reference