Policies API
Policies define the spending rules that govern an agent's behavior. Every payment request is evaluated against the agent's active policy using the policy engine. A policy is bound to both an agent and a vault.
Create Policy#
/v1/policiesCreate a new spending policy for an agent.
Request Body#
| Field | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | The agent this policy governs |
| vault_id | string | Yes | The vault this policy applies to |
| budget | object | Yes | Spending limits (see below) |
| categories | object | No | Category restrictions |
| merchants | object | No | Merchant allow/block lists |
| time_restrictions | object | No | Time-of-day and day-of-week restrictions |
| approval_rules | array | No | Conditional approval rules |
| velocity_controls | object | No | Transaction rate limits |
| escrow_rules | object | No | Automatic escrow thresholds |
Budget Object#
| Field | Type | Required | Description |
|---|---|---|---|
| max_per_transaction | number | Yes | Maximum amount for a single payment (USDC) |
| max_daily | number | No | Maximum daily spending (USDC) |
| max_weekly | number | No | Maximum weekly spending (USDC) |
| max_monthly | number | No | Maximum monthly spending (USDC) |
| currency | string | Yes | Must be "USDC" |
Categories Object#
| Field | Type | Required | Description |
|---|---|---|---|
| mode | string | Yes | "allowlist" or "blocklist" |
| list | array | Yes | Array of category strings |
Merchants Object#
| Field | Type | Required | Description |
|---|---|---|---|
| blocklist | array | Yes | Array of merchant IDs to block |
| allowlist_only | boolean | No | If true, only allow merchants not on the blocklist |
Time Restrictions Object#
| Field | Type | Required | Description |
|---|---|---|---|
| allowed_hours | object | No | { "start": "09:00", "end": "17:00" } |
| timezone | string | Yes | IANA timezone (e.g., "America/New_York") |
| allowed_days | array | No | Days of the week (e.g., ["monday", "tuesday", "wednesday", "thursday", "friday"]) |
Approval Rules Array#
Each rule is an object:
| Field | Type | Required | Description |
|---|---|---|---|
| condition | string | Yes | Expression to evaluate (e.g., "amount > 100") |
| action | string | Yes | "auto_approve", "request_approval", or "reject" |
| timeout_seconds | number | No | Seconds to wait for approval before fallback (default 3600) |
| fallback | string | No | Action if approval times out: "reject" or "approve" |
Velocity Controls Object#
| Field | Type | Required | Description |
|---|---|---|---|
| max_transactions_per_hour | number | No | Maximum transactions allowed per hour |
| max_transactions_per_day | number | No | Maximum transactions allowed per day |
| cooldown_after_rejection_seconds | number | No | Seconds to wait after a rejection before allowing new requests |
Escrow Rules Object#
| Field | Type | Required | Description |
|---|---|---|---|
| require_escrow_above | number | No | Payments above this amount automatically use escrow (USDC) |
| default_escrow_expiry_hours | number | No | Default escrow expiration in hours |
Example Request#
{
"agent_id": "agt_550e8400-e29b-41d4-a716-446655440000",
"vault_id": "550e8400-e29b-41d4-a716-446655440000",
"budget": {
"max_per_transaction": 100,
"max_daily": 500,
"max_weekly": 2000,
"max_monthly": 5000,
"currency": "USDC"
},
"categories": {
"mode": "allowlist",
"list": ["groceries", "household", "electronics"]
},
"merchants": {
"blocklist": ["mrc_blocked_vendor_1"],
"allowlist_only": false
},
"time_restrictions": {
"allowed_hours": { "start": "08:00", "end": "22:00" },
"timezone": "America/New_York",
"allowed_days": ["monday", "tuesday", "wednesday", "thursday", "friday"]
},
"approval_rules": [
{
"condition": "amount > 50",
"action": "request_approval",
"timeout_seconds": 3600,
"fallback": "reject"
}
],
"velocity_controls": {
"max_transactions_per_hour": 10,
"max_transactions_per_day": 50,
"cooldown_after_rejection_seconds": 300
},
"escrow_rules": {
"require_escrow_above": 200,
"default_escrow_expiry_hours": 48
}
}
Response#
{
"policy_id": "pol_880e8400-e29b-41d4-a716-446655440000",
"agent_id": "agt_550e8400-e29b-41d4-a716-446655440000",
"vault_id": "550e8400-e29b-41d4-a716-446655440000",
"policy_hash": "sha256:a3f2b8c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1",
"version": 1,
"status": "active",
"created_at": "2025-01-15T10:30:00.000Z"
}
The policy_hash is a SHA-256 hash of the policy JSON. This hash is used on-chain to verify that payments were evaluated against the correct policy version.
Errors#
| Error Code | Description |
|---|---|
| vault_not_found | The specified vault does not exist |
| agent_not_authorized | The specified agent does not exist |
Get Policy#
/v1/policies/:idRetrieve a policy with its full configuration.
Path Parameters#
| Parameter | Type | Description |
|---|---|---|
| id | string | The policy ID |
Response#
{
"policy_id": "pol_880e8400-e29b-41d4-a716-446655440000",
"agent_id": "agt_550e8400-e29b-41d4-a716-446655440000",
"vault_id": "550e8400-e29b-41d4-a716-446655440000",
"policy_hash": "sha256:a3f2b8c1...",
"version": 1,
"status": "active",
"budget": {
"max_per_transaction": 100,
"max_daily": 500,
"max_weekly": 2000,
"max_monthly": 5000,
"currency": "USDC"
},
"categories": {
"mode": "allowlist",
"list": ["groceries", "household", "electronics"]
},
"velocity_controls": {
"max_transactions_per_hour": 10,
"max_transactions_per_day": 50
},
"created_at": "2025-01-15T10:30:00.000Z",
"updated_at": "2025-01-15T10:30:00.000Z"
}
Errors#
| Error Code | Description |
|---|---|
| policy_not_found | No policy exists with the given ID |
Update Policy#
/v1/policies/:idUpdate an existing policy. Increments the version number.
You can update any subset of the policy fields. Unchanged fields retain their existing values. Each update increments the version number and generates a new policy_hash.
Path Parameters#
| Parameter | Type | Description |
|---|---|---|
| id | string | The policy ID |
Request Body#
Same schema as Create Policy, but all fields are optional. Only include the fields you want to change.
Example Request#
{
"budget": {
"max_per_transaction": 200,
"max_daily": 1000,
"currency": "USDC"
}
}
Response#
{
"policy_id": "pol_880e8400-e29b-41d4-a716-446655440000",
"agent_id": "agt_550e8400-e29b-41d4-a716-446655440000",
"vault_id": "550e8400-e29b-41d4-a716-446655440000",
"policy_hash": "sha256:b4g3c9d2e5f6g7h8...",
"version": 2,
"status": "active",
"updated_at": "2025-01-16T09:00:00.000Z"
}
Errors#
| Error Code | Description |
|---|---|
| policy_not_found | No policy exists with the given ID |
Policy Statuses#
| Status | Description |
|---|---|
| active | Policy is in effect and used for payment evaluation |
| archived | Policy is no longer active (replaced by a newer version) |