---
title: "Propose a spending mandate"
method: POST
path: "/mandates"
---

# Propose a spending mandate

`POST /mandates`

The agent proposes a mandate with a suggested budget, merchant restrictions, and cadence. The mandate is created with `status: pending_approval` and is not usable until the human owner approves it out-of-band (via push notification, email, or in-app review). The agent should poll `GET /v1/mandates/{id}` to detect when status becomes `active`.

## Headers

- `Idempotency-Key` string

## Request body

- CreateMandateRequest
  - `agent_id` string, required
  - `budget` AllowanceBudget, required
    - `cadence` 'once' | 'daily' | 'weekly' | 'monthly' | 'annually' | 'never', required — Spending cadence. 'once' = single-use mandate — expires after first credential is issued. 'never' = a lifetime cap that never resets. All others reset per interval.
    - `per_transaction_max` integer, required — Maximum amount per credential request in minor currency units (cents for USD). Example: 50000 = $500.00.
    - `total_max` integer, nullable — Total cap across all credential requests in minor units. Resets per cadence interval. null = no cap.
    - `currency` string, required — ISO 4217 currency code.
    - `merchants` string[] — Allowlist of merchant names. Empty array = no merchant restriction.
    - `merchant_category_codes` string[] — Allowlist of 4-digit ISO 18245 MCCs. Empty array = no MCC restriction.
    - `categories` string[] — Semantic category labels. Supplementary to MCC — used for display and audit, not enforcement.
    - `expires_at` string, date-time, nullable — Mandate expiry as ISO 8601 datetime. null = no expiry. Always set this for sensitive or one-time tasks.
  - `risk_controls` object
    - `require_merchant_match` boolean
    - `block_international` boolean
    - `max_daily_spend` integer, nullable
    - `velocity_limit_per_hour` integer, nullable
  - `metadata` object

## Response `201`

Mandate created in `pending_approval` status

- AllowanceMandate
  - `id` string, required — Unique mandate ID.
  - `owner_id` string, required — ID of the human user who owns and approved this mandate.
  - `agent_id` string, required — ID of the AI agent authorized to request credentials under this mandate.
  - `budget` AllowanceBudget, required
    - `cadence` 'once' | 'daily' | 'weekly' | 'monthly' | 'annually' | 'never', required — Spending cadence. 'once' = single-use mandate — expires after first credential is issued. 'never' = a lifetime cap that never resets. All others reset per interval.
    - `per_transaction_max` integer, required — Maximum amount per credential request in minor currency units (cents for USD). Example: 50000 = $500.00.
    - `total_max` integer, nullable — Total cap across all credential requests in minor units. Resets per cadence interval. null = no cap.
    - `currency` string, required — ISO 4217 currency code.
    - `merchants` string[] — Allowlist of merchant names. Empty array = no merchant restriction.
    - `merchant_category_codes` string[] — Allowlist of 4-digit ISO 18245 MCCs. Empty array = no MCC restriction.
    - `categories` string[] — Semantic category labels. Supplementary to MCC — used for display and audit, not enforcement.
    - `expires_at` string, date-time, nullable — Mandate expiry as ISO 8601 datetime. null = no expiry. Always set this for sensitive or one-time tasks.
  - `risk_controls` object
    - `require_merchant_match` boolean — If true, credential requests must exactly match a merchant in the budget.merchants allowlist.
    - `block_international` boolean — If true, credential requests for international merchants are denied.
    - `max_daily_spend` integer, nullable — Hard daily cap across all credential requests, in minor units.
    - `velocity_limit_per_hour` integer, nullable — Maximum number of credential requests allowed per hour.
  - `status` 'pending_approval' | 'active' | 'exhausted' | 'expired' | 'revoked', required — pending_approval = created, awaiting human approval. active = approved, credential requests accepted. exhausted = once mandate fully used. expired = past expires_at. revoked = manually cancelled.
  - `approved_at` string, date-time, nullable — When the human owner approved the mandate.
  - `created_at` string, date-time, required
  - `expires_at` string, date-time, nullable
  - `metadata` object — Up to 10 key-value string pairs. Use to record user instruction, task context, etc.
  - `x-ap2-note` string — In a future AP2-compatible version, this mandate will be issued as a signed Intent Mandate VDC and approved_at will carry a cryptographic attestation.

## Other responses

- `400` — Invalid request parameters
- `401` — Missing or invalid API key
- `501` — Pre-launch: this endpoint is not yet active

---

[API](https://skmtc.dev/useallowance/apis/allowance-api.md) · [All operations](https://skmtc.dev/useallowance/apis/allowance-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/useallowance/allowance-api/revisions/c94c99b9f8c7/schema)
