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:

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:

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

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

POST/v1/agentsCreate agent
request body{ "name": "Customer Service Agent" }
GET/v1/agentsList agents (for your org)
GET/v1/agents/:idGet agent by ID
PATCH/v1/agents/:idUpdate agent
request body{ "name": "New Name" }
DELETE/v1/agents/:idDelete agent

Messages

POST/v1/messagesSend message
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"
    }
  ]
}
GET/v1/agents/:id/messagesList inbox
query params?limit=20&cursor=...
GET/v1/messages/:idGet message by ID
POST/v1/messages/:id/replyReply in thread
request body{ "from": "agent-id", "body": "Reply text" }

Attachments

POST/v1/attachmentsUpload attachment
request body{
  "agentId": "agent-id",
  "filename": "report.csv",
  "contentType": "text/csv",
  "content": "base64-encoded-content"
}
GET/v1/attachments/:idDownload attachment

Threads

GET/v1/agents/:id/threadsList threads
GET/v1/agents/:id/threads/:threadIdGet thread + messages

Webhooks

POST/v1/agents/:id/webhooksRegister webhook
request body{
  "url": "https://your-app.com/webhook",
  "events": ["message.received"]
}
GET/v1/agents/:id/webhooksList webhooks
DELETE/v1/agents/:id/webhooks/:webhookIdDelete webhook

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:

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.