Skip to content

For agents · Published 2026-09-18 · Updated 2026-10-26 · AgentiSend

Agent email budgets

To cap how much email an AI agent can send, give it its own API key and set a budget on that key with PATCH /limits/keys/{id}. The ceiling is enforced before the send.

To cap how much email an AI agent can send, give the agent its own API key and set a budget on that key with PATCH /limits/keys/{id}. The ceiling is checked before each send, the agent cannot raise it, and a send past it is refused with agent_budget_exceeded rather than queued or charged.

Do it in two requests

Create a key for the agent, so its ceiling is its own:

curl -sS -X POST https://api.agentisend.com/api-keys \
  -H "Authorization: Bearer $AGENTISEND_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"example","permission":"full_access"}'
201
{
  "budget_per_period": 5000,
  "created_at": "2026-09-04T09:14:00.000Z",
  "domain_scope": "example",
  "expires_at": "2026-09-04T09:14:00.000Z",
  "id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
  "last_used_at": "2026-09-04T09:14:00.000Z",
  "loop_guard": "off",
  "name": "example",
  "object": "api_key",
  "period": "monthly",
  "permission": "full_access",
  "previous_key_expires_at": "2026-09-04T09:14:00.000Z",
  "rate_ceiling_per_minute": 600,
  "request_count_30d": -9007199254740991,
  "rotated_at": "2026-09-04T09:14:00.000Z",
  "scopes": [],
  "system": false,
  "token": "as_abababababababababababababababababababababababababababababababab",
  "token_prefix": "as_abababab"
}
Response

Then set the budget on it:

curl -sS -X PATCH https://api.agentisend.com/limits/keys/9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42 \
  -H "Authorization: Bearer $AGENTISEND_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"budget_per_period":500,"rate_ceiling_per_minute":20}'
200
{
  "api_key_id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
  "budget_per_period": -9007199254740991,
  "consumed_in_period": -9007199254740991,
  "consumed_in_window": -9007199254740991,
  "paused": false,
  "paused_at": "2026-09-04T09:14:00.000Z",
  "paused_reason": "example",
  "period": "hourly",
  "period_started_at": "2026-09-04T09:14:00.000Z",
  "rate_ceiling_per_minute": -9007199254740991,
  "rate_window_started_at": "2026-09-04T09:14:00.000Z",
  "updated_at": "2026-09-04T09:14:00.000Z"
}
Response

The body is three optional fields:

{ "budget_per_period": 500, "rate_ceiling_per_minute": 20 }

period is hourly, daily or monthly. budget_per_period counts sends in that period. rate_ceiling_per_minute is the separate burst ceiling. An API key can only lower its limits, and a shorter period is compared over 30 days: 500 a day is up to 15,000, far more than a new Free key's 5,000 a month, so a change like that is made by a person in the console. Passing null for either clears it.

Read the state back

GET /limits/keys/{id} returns budget_per_period, consumed_in_period, period_started_at, rate_ceiling_per_minute, consumed_in_window, and whether the key is paused. GET /limits/keys returns the same for every key on the account, plus each key's name, its last use and its current loop state.

What the agent sees at the ceiling

{
  "error": {
    "code": "agent_budget_exceeded",
    "message": "This key has used 1 of its 1 recipients for the current monthly period. Each To, CC and BCC recipient counts as one email.",
    "fix": "Wait for the period to reset — get_agent_budget and GET /limits/keys/:id both say when. Raising a budget is a person’s decision, made in the console; a key cannot raise its own.",
    "docs_url": "https://agentisend.com/what-does-agent-budget-exceeded-mean#agent_budget_exceeded",
    "retryable": false
  }
}

retryable is false, so a well-behaved client stops instead of spinning. Raising the budget is a human's call: there is no request an agent can make that lifts its own ceiling.

The account's plan inclusion is a second, separate ceiling. When that is spent the code is plan_limit_reached and sending pauses; nothing is auto-charged. On a paid plan an owner can turn overage on with a ceiling of their own; past that ceiling the code is overage_cap_reached.

Two ceilings a budget does not replace

A budget caps volume. It does not stop an agent that is repeating itself inside its budget, and it does not stop an agent a human wants stopped right now. Those are loop detection and the kill switch, POST /limits/kill-all.