Use cases · Published 2026-09-29 · AgentiSend team
Receipts from a store agent
A store agent sends a receipt after a payment. The key's ceiling is a monthly count, and each address on the message counts as one.
A store agent sends one receipt after a payment that has already happened, to the address on that order. The message is transactional: it confirms the amount, the order, and where the full receipt lives.
The ceiling
Set the key before the route below runs. PATCH /limits/keys/{id} accepts only budget_per_period, period and rate_ceiling_per_minute. This job uses:
{
"budget_per_period": 400,
"period": "monthly",
"rate_ceiling_per_minute": 20
}Four hundred is under a Free plan's 1,000 a month, and twenty a minute is under the default 600. A key cannot raise either. The budget period stays monthly.
The send
"""Flask: one POST route that sends an order receipt.
POST /send {"email": "ada@example.com", "order_id": "1042"}
200 {"id": "..."} accepted
400 {"error": "..."} not one address; the API was not called
4xx/5xx {"code": "...", "fix": "..."} the API refused, and says what to do
Environment: AGENTISEND_API_KEY (a key with sending_access), MAIL_FROM (an
address on a domain you have verified), and optionally AGENTISEND_BASE_URL.
Run: flask --app app run
"""
from __future__ import annotations
import os
import re
from flask import Flask, jsonify, request
from agentisend import AgentiSend, AgentiSendError, idempotency_key
agentisend = AgentiSend() # reads AGENTISEND_API_KEY and AGENTISEND_BASE_URL
MAIL_FROM = os.environ["MAIL_FROM"]
# One address, no spaces, a dot in the domain. The API checks properly; this
# only stops a form typo from costing a request.
ADDRESS = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
app = Flask(__name__)
@app.post("/send")
def send():
body = request.get_json(silent=True) or {}
email = str(body.get("email", "")).strip()
order_id = str(body.get("order_id", "")).strip()
if not ADDRESS.match(email):
return jsonify(error="email must be one address, like you@example.com"), 400
if not order_id:
return jsonify(error="order_id is required"), 400
try:
sent = agentisend.send_email(
{
"from": MAIL_FROM,
"to": email,
"subject": f"Receipt for order {order_id}",
"text": f"Thanks for your order. Order {order_id} is paid.",
},
# One receipt per order, whoever asks and however often: a retry
# after a timeout replays the first send instead of mailing twice.
idempotency=idempotency_key("receipt", order_id),
)
except AgentiSendError as err:
return jsonify(code=err.code, fix=err.fix), err.status
return jsonify(id=sent["id"])The starter for the message itself is Receipt.
The refusal
An address that hard-bounced before is on the suppression list. The send is refused and nothing is delivered:
{
"error": {
"code": "suppressed_recipient",
"message": "Recipient is on the account suppression list.",
"fix": "GET /suppressions says which address and why. A hard bounce you have fixed can be cleared with DELETE /suppressions/:id; an unsubscribe or a spam complaint cannot — that address asked not to be contacted.",
"docs_url": "https://agentisend.com/what-does-suppressed-recipient-mean#suppressed_recipient",
"retryable": false
}
}Honest limit
Each To, Cc and Bcc address counts as one email against the key and against the plan inclusion. A scheduled receipt is counted when it is accepted. Cancelling it before it sends gives that count back.