Questions · Published 2026-09-29 · Updated 2026-09-29 · AgentiSend
How do I let an AI agent send email?
To let an AI agent send email, create a key, set a ceiling the key cannot raise, then send. A refusal comes back with a code and a fix.
To let an AI agent send email, make three requests, in this order. POST /api-keys creates a key with permission sending_access. PATCH /limits/keys/{id} sets budget_per_period, period, and rate_ceiling_per_minute. POST /emails is the send. The agent cannot raise its own ceiling. A refusal carries code, message, fix, and retryable, and the agent stops when retryable is false.
The three requests
POST /api-keys returns the secret once. Keep it on that agent alone. The default budget on a new key is the plan's monthly inclusion, which on the Free plan is 1,000 emails a month. A person tightens it before handing the key over.
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": 1000,
"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",
"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"
}PATCH /limits/keys/{id} is the ceiling. An API key may lower its own budget. Raising one is a person's decision, made in the console. A key that sends a higher budget_per_period is answered human_action_required. Read the ceiling back with GET /limits/keys/{id}.
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"
}POST /emails is the send. Before a domain is verified, onboarding@agentisend.com delivers only to member sign-in addresses, and an address at simulator.agentisend.com costs nothing and reaches nobody.
curl -sS -X POST https://api.agentisend.com/emails \
-H "Authorization: Bearer $AGENTISEND_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"from":"billing@yourdomain.com","to":"delivered@simulator.agentisend.com","subject":"Your receipt","text":"Thanks — the details are attached."}'201
{
"id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
"simulated": true,
"warnings": []
}What a refusal looks like
A send past the budget answers agent_budget_exceeded. A held send answers approval_required. A paused key answers kill_switch_active. Each page quotes the catalogue message and the fix. The agent quotes code and fix and does not invent a retry when retryable is false.
How do I put a spending limit on an AI agent? is the ceiling in more detail. How do I stop an AI agent from sending too many emails? is the same door from the other side.
Next
Written by the AgentiSend team.