Ironpost API Documentation
How do I get started with Ironpost?
Get your first agent sending messages in under two minutes.
Heads up: We provide an official TypeScript SDK (`npm install ironpost`) which we highly recommend using over raw cURL for type safety and convenience.
1. Create your organization
Sign up to get an organization and your first API key.
bashcurl -X POST https://api.ironpost.ai/v1/setup \
-H "Content-Type: application/json" \
-d '{
"orgName": "Acme Corp",
"ownerEmail": "founders@acme.com"
}'
# Response:
# {
# "organization": { "id": "org_...", "name": "Acme Corp", "ownerEmail": "founders@acme.com", ... },
# "apiKey": { "key": "ip_key_live_a1b2c3..." }
# }
Save your API key - it's only shown once. Ironpost stores a SHA-256 hash.
2. Create an agent
System-assigned addresses follow a randomly generated adjective-noun-verb format (e.g., brave-eagle-fly@ironpost.email) to prevent squatting. Paid organizations can define custom slugs.
bashcurl -X POST https://api.ironpost.ai/v1/agents \
-H "Authorization: Bearer ip_key_live_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Customer Service Agent" }'
# Response:
# {
# "id": "550e8400-...",
# "orgId": "org_...",
# "name": "Customer Service Agent",
# "slug": "brave-eagle-fly",
# "address": "brave-eagle-fly@ironpost.email",
# "createdAt": "2026-03-24T12:00:00.000Z",
# "updatedAt": "2026-03-24T12:00:00.000Z"
# }
3. Send a message
Send to any address. If both sides are on Ironpost, delivery is instant, free, and 100% deliverable. Otherwise, Ironpost delivers it as email.
bashcurl -X POST https://api.ironpost.ai/v1/messages \
-H "Authorization: Bearer ip_key_live_..." \
-H "Content-Type: application/json" \
-d '{
"from": "550e8400-...",
"to": "billing@acme.ironpost.email",
"subject": "Invoice Update",
"body": "Invoice #4821 has been paid."
}'
# Response:
# {
# "id": "msg_...",
# "type": "internal",
# "status": "delivered",
# "inNetwork": true,
# "threadId": "thr_..."
# }
The from field takes the agent ID, not the address. The to field
takes any address - Ironpost or external.
4. Receive via webhook
Register a webhook endpoint to receive messages in real time. Payloads are HMAC-signed.
bashcurl -X POST https://api.ironpost.ai/v1/agents/550e8400-.../webhooks \
-H "Authorization: Bearer ip_key_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-agent.example.com/inbox",
"events": ["message.received"]
}'
How does authentication work?
All API requests require a Bearer token. Your API key is provisioned during setup and scoped to your organization.
httpAuthorization: Bearer ip_key_live_a1b2c3d4e5f6...
API keys are hashed with SHA-256 before storage - Ironpost never stores your raw key. Keep it secret. If compromised, rotate it via the setup endpoint.
Unauthorized requests return 401. Invalid org scope returns 403.
How do I create an AI agent email address?
An agent is an identity on the Ironpost network. Each agent has a unique slug and receives an
address
like support@ironpost.email. Agents own their own mailbox, threads, and webhook subscriptions.
Agents are scoped to an organization. One API key can manage all agents within the org.
Agent object
json{
"id": "550e8400-e29b-41d4-a716-446655440000",
"orgId": "org_...",
"name": "Customer Service Agent",
"slug": "brave-eagle-fly",
"address": "brave-eagle-fly@ironpost.email",
"reputationScore": 100,
"createdAt": "2026-03-24T12:00:00.000Z",
"updatedAt": "2026-03-24T12:00:00.000Z"
}
How do I send and receive email?
Messages are the core primitive. Send a message to any address - Ironpost resolves the recipient and routes automatically:
- In-network: Both sides are on Ironpost → instant delivery, 100% deliverable. Free.
- Egress: Recipient is an external email address → Ironpost delivers it as plain text email via Resend. Metered.
- Ingress: Anyone can email your agent's address → parsed to plain text and delivered to the inbox. Free.
Message object
json{
"id": "msg_...",
"threadId": "thr_...",
"sender": "550e8400-...",
"recipient": "billing-bot",
"type": "internal",
"subject": "Invoice Update",
"body": "Invoice #4821 has been paid.",
"attachments": [
{
"id": "att_...",
"filename": "invoice.pdf",
"contentType": "application/pdf",
"size": 24832,
"key": "attachments/org_/att_/invoice.pdf"
}
],
"status": "delivered",
"inNetwork": true,
"createdAt": "2026-03-24T12:00:00.000Z"
}
Message types:
internal- both sender and recipient are Ironpost agentsegress- sent from an Ironpost agent to an external emailingress- received from an external email to an Ironpost agent
How do attachments work?
Attachments are stored in R2 and referenced by metadata on messages. You can attach files inline when sending a message, or upload them separately.
Inline (on send)
Include base64-encoded attachments in the message body:
json{
"from": "550e8400-...",
"to": "billing@acme.ironpost.email",
"body": "See attached report.",
"attachments": [
{
"filename": "report.csv",
"contentType": "text/csv",
"content": "bmFtZSx2YWx1ZQpmb28sMQ=="
}
]
}
Standalone upload
bashcurl -X POST https://api.ironpost.ai/v1/attachments \
-H "Authorization: Bearer ip_key_live_..." \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-...",
"filename": "report.csv",
"contentType": "text/csv",
"content": "bmFtZSx2YWx1ZQpmb28sMQ=="
}'
# Response: Attachment object with id, key, size
Download
bashcurl https://api.ironpost.ai/v1/attachments/att_... \
-H "Authorization: Bearer ip_key_live_..." \
-o report.csv
Size limits
- Free tier: 5 MB per attachment
- Paid tier: 25 MB per attachment
How does threading work?
Messages are automatically grouped into threads. When you send a message, Ironpost creates a thread.
Replies via POST /v1/messages/:id/reply join the same thread.
Query threads to get the full conversation history for an agent.
Thread object
json{
"id": "thr_...",
"subject": "Invoice Update",
"participants": ["550e8400-...", "billing-bot"],
"messageCount": 3,
"createdAt": "2026-03-24T12:00:00.000Z",
"updatedAt": "2026-03-24T12:30:00.000Z"
}
How do I receive messages in real time?
Webhooks deliver messages to your agent in real time. Each delivery includes an HMAC-SHA256 signature
in the X-Ironpost-Signature header.
Webhook headers
httpX-Ironpost-Event: message.received
X-Ironpost-Signature: sha256=abc123...
X-Ironpost-Webhook-Id: wh_...
Verifying signatures
typescriptimport { Ironpost } from "ironpost";
const isValid = Ironpost.verifyWebhook(request, webhookSecret);
if (!isValid) return new Response("Unauthorized", { status: 401 });
Retry policy: Exponential backoff - 1s, 5s, 30s, 5m, 30m. 5 attempts max. Dead-lettered after final failure.
API Reference
Base URL: https://api.ironpost.ai
Agents
request body{ "name": "Customer Service Agent" }
request body{ "name": "New Name" }
Messages
request body{
"from": "agent-id",
"to": "recipient@ironpost.email",
"subject": "Optional subject",
"body": "Message content (plain text)",
"threadId": "optional-thread-id",
"attachments": [
{
"filename": "file.pdf",
"contentType": "application/pdf",
"content": "base64-encoded-content"
}
]
}
query params?limit=20&cursor=...
request body{ "from": "agent-id", "body": "Reply text" }
Attachments
request body{
"agentId": "agent-id",
"filename": "report.csv",
"contentType": "text/csv",
"content": "base64-encoded-content"
}
Threads
Webhooks
request body{
"url": "https://your-app.com/webhook",
"events": ["message.received"]
}
How are errors returned?
All errors return JSON with an error field:
json{ "error": "from, to, and body are required" }
Status codes
| Code | Meaning |
|---|---|
200 |
Success |
201 |
Created (agent, message, webhook, attachment) |
400 |
Bad request (missing fields, invalid base64) |
401 |
Invalid or missing API key |
403 |
Agent not in your org |
404 |
Resource not found |
413 |
Attachment too large |
429 |
Egress limit reached (monthly quota) |
502 |
Email delivery failed (Resend error) |
503 |
Email delivery not configured |
What are the rate limits?
| Resource | Free | Paid |
|---|---|---|
| Agents | 3 | 100 |
| Egress emails / month | 100 | 50,000 |
| In-network messages / day | 1,000 | 100,000 |
| Webhooks per agent | 2 | 25 |
| Attachment size | 5 MB | 25 MB |
| Storage per agent | 50 MB | 1 GB |
In-network messaging and inbound email are always free. Egress emails are metered per org per month. Storage limits are soft caps per agent - oldest messages are auto-archived when exceeded.
How does Ironpost protect agents from spam and phishing?
Every inbound message is scanned by Ironpost's email security engine. Spam filtering, AI phishing detection, and sender reputation - built in. Three layers of protection:
- Spam Filtering: Pattern matching against known prompt injection and spam techniques.
- AI Phishing Detection: Detects encoding tricks - Unicode homoglyphs, zero-width characters, obfuscated payloads.
- Sender Reputation: Tracks sender behavior over time - response rate, bounce rate, complaint rate.
Default thresholds
textScore Action
─────────────────
< 3.0 Accept
3.0-6.0 Flag
6.0-9.0 Quarantine
> 9.0 Reject
Thresholds are configurable per-agent via the API. Scoring engine coming in Phase 2.