Routes
Inbound routing rules — match an address and deliver it to a webhook, agent, or forward. See Inbound webhooks for a guided walk-through.
Auth: Session token · Base URL:
https://api.mailkite.dev
Endpoints
Each row expands to its request and response schema. The address bar follows along, so any endpoint can be linked to directly.
GET /api/routes List inbound routing rules.
List inbound routing rules.
An inbound routing rule: which addresses it matches and what happens to matching mail (webhook POST, forward, store, drop, or an inbox agent). The per-route signing secret is returned ONCE on create and via GET /api/domains/:id/webhook/secret — list responses omit it.
| Field | Type | Notes |
|---|---|---|
| id req | string | Route id (rte_…). |
| user_id req | string | Owning account (usr_…). |
| match_pattern req | string | Which recipient addresses this route matches: an exact address, `*@domain`, a prefix pattern like `ticket+*@domain`, or a `/regex/`. |
| action req | "webhook" · "forward" · "store" · "drop" · "agent" | What happens to a matching message. |
| destination | string · null | Webhook URL or forward address. null for store/drop/agent actions. |
| agent_prompt | string · null | Instructions for the built-in inbox agent (action 'agent' only). |
| agent_forward_to | string · null | Extra addresses the inbox agent's forward tool may reach, as a JSON array string. null = owner-controlled addresses only. |
| agent_context | "message" · "thread" · "sender" · null | How much mail the inbox agent may read once the sender is verified. null = 'message' (just the inbound email). |
| active req | 0 · 1 | 1 while the route is enabled. |
| ack_mode req | "lenient" · "ack" | Webhook acknowledgement strictness: 'lenient' accepts any 2xx; 'ack' also requires {"status":"ok"} (or the x-mailkite-ack header) on every delivery. |
| last_status | "ok" · "fail" · "running" · "timeout" · null | Outcome of the route's most recent action. null = never exercised. |
| last_status_message | string · null | Human-readable detail of the last outcome (e.g. 'HTTP 500'). |
| last_status_code | integer · null | Transport status code of the last outcome, when relevant. |
| last_status_at | integer · null | When the last outcome landed, in Unix epoch milliseconds (UTC); null when it has never happened. |
| consecutive_failures | integer | Current failing streak (0 when healthy). |
| first_failed_at | integer · null | When the current failing streak began, in Unix epoch milliseconds (UTC); null when it has never happened. |
| unhealthy_notified_at | integer · null | When the owner was emailed about the current streak, in Unix epoch milliseconds (UTC); null when it has never happened. |
| signing_secret | string · null | Per-route webhook signing secret (whsec_…). Returned on create; read later via GET /api/domains/:id/webhook/secret. null until first read lazily creates it. |
| created_at req | integer | When the route was created, in Unix epoch milliseconds (UTC). |
An actual array of results, recorded from the conformance suite.
[
{
"id": "rte_4Bn8XcVm",
"user_id": "usr_7Fj3MnQw",
"match_pattern": "*@myapp.ai",
"action": "webhook",
"destination": "https://myapp.ai/hooks/mailkite",
"agent_prompt": null,
"agent_forward_to": null,
"agent_context": null,
"active": 1,
"ack_mode": "lenient",
"last_status": "ok",
"last_status_message": null,
"last_status_code": 200,
"last_status_at": 1769817600000,
"consecutive_failures": 0,
"first_failed_at": null,
"unhealthy_notified_at": null,
"signing_secret": null,
"created_at": 1769731200000
}
] {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://api.mailkite.dev/v1/schemas/route.json",
"title": "Route",
"description": "An inbound routing rule: which addresses it matches and what happens to matching mail (webhook POST, forward, store, drop, or an inbox agent). The per-route signing secret is returned ONCE on create and via GET /api/domains/:id/webhook/secret — list responses omit it.",
"type": "object",
"required": [
"id",
"user_id",
"match_pattern",
"action",
"active",
"ack_mode",
"created_at"
],
"properties": {
"id": {
"type": "string",
"description": "Route id (rte_…).",
"examples": [
"rte_4Bn8XcVm"
]
},
"user_id": {
"type": "string",
"description": "Owning account (usr_…).",
"examples": [
"usr_7Fj3MnQw"
]
},
"match_pattern": {
"type": "string",
"description": "Which recipient addresses this route matches: an exact address, `*@domain`, a prefix pattern like `ticket+*@domain`, or a `/regex/`.",
"examples": [
"*@myapp.ai"
]
},
"action": {
"type": "string",
"enum": [
"webhook",
"forward",
"store",
"drop",
"agent"
],
"description": "What happens to a matching message."
},
"destination": {
"type": [
"string",
"null"
],
"description": "Webhook URL or forward address. null for store/drop/agent actions.",
"examples": [
"https://myapp.ai/hooks/mailkite"
]
},
"agent_prompt": {
"type": [
"string",
"null"
],
"description": "Instructions for the built-in inbox agent (action 'agent' only)."
},
"agent_forward_to": {
"type": [
"string",
"null"
],
"description": "Extra addresses the inbox agent's forward tool may reach, as a JSON array string. null = owner-controlled addresses only."
},
"agent_context": {
"type": [
"string",
"null"
],
"enum": [
"message",
"thread",
"sender",
null
],
"description": "How much mail the inbox agent may read once the sender is verified. null = 'message' (just the inbound email)."
},
"active": {
"type": "integer",
"enum": [
0,
1
],
"description": "1 while the route is enabled."
},
"ack_mode": {
"type": "string",
"enum": [
"lenient",
"ack"
],
"description": "Webhook acknowledgement strictness: 'lenient' accepts any 2xx; 'ack' also requires {\"status\":\"ok\"} (or the x-mailkite-ack header) on every delivery."
},
"last_status": {
"type": [
"string",
"null"
],
"enum": [
"ok",
"fail",
"running",
"timeout",
null
],
"description": "Outcome of the route's most recent action. null = never exercised."
},
"last_status_message": {
"type": [
"string",
"null"
],
"description": "Human-readable detail of the last outcome (e.g. 'HTTP 500')."
},
"last_status_code": {
"type": [
"integer",
"null"
],
"description": "Transport status code of the last outcome, when relevant.",
"examples": [
200
]
},
"last_status_at": {
"type": [
"integer",
"null"
],
"description": "When the last outcome landed, in Unix epoch milliseconds (UTC); null when it has never happened.",
"examples": [
1769731200000
]
},
"consecutive_failures": {
"type": "integer",
"description": "Current failing streak (0 when healthy)."
},
"first_failed_at": {
"type": [
"integer",
"null"
],
"description": "When the current failing streak began, in Unix epoch milliseconds (UTC); null when it has never happened.",
"examples": [
1769731200000
]
},
"unhealthy_notified_at": {
"type": [
"integer",
"null"
],
"description": "When the owner was emailed about the current streak, in Unix epoch milliseconds (UTC); null when it has never happened.",
"examples": [
1769731200000
]
},
"signing_secret": {
"type": [
"string",
"null"
],
"description": "Per-route webhook signing secret (whsec_…). Returned on create; read later via GET /api/domains/:id/webhook/secret. null until first read lazily creates it."
},
"created_at": {
"type": "integer",
"description": "When the route was created, in Unix epoch milliseconds (UTC).",
"examples": [
1769731200000
]
}
}
} POST /api/routes Create a route (match, action, destination).
Create a route (match, action, destination).
Request body
create-route-request.json| Field | Type | Notes |
|---|---|---|
| match req | string | Address pattern: exact, *@domain, addr+*@domain, or /regex/. |
| action | "webhook" · "forward" · "store" · "drop" · "agent" | What to do with matching mail. Defaults to webhook. |
| destination | string | Required for action webhook (URL) or forward (address). |
| agentPrompt | string | Required for action agent — instructions for the inbox agent. |
| agentForwardTo | string[] | For action agent: addresses the inbox agent's forward tool may send to. The agent can always forward to your account email and any address on a verified domain you own; this adds extra approved addresses (e.g. an escalation inbox). |
| agentContext | "message" · "thread" · "sender" | For action agent: how much mail the agent may read once the sender is verified (they replied to an earlier agent message from a DMARC-passing address). 'message' (default) = only the incoming email; 'thread' = this conversation; 'sender' = all past mail with this sender. |
The smallest body that makes this call — every other field is optional.
{
"match": "*@app.mailkite.dev",
"action": "webhook",
"destination": "https://app.com/hooks"
} {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://api.mailkite.dev/v1/schemas/create-route-request.json",
"title": "Create route request body",
"type": "object",
"required": [
"match"
],
"additionalProperties": false,
"properties": {
"match": {
"type": "string",
"description": "Address pattern: exact, *@domain, addr+*@domain, or /regex/."
},
"action": {
"type": "string",
"enum": [
"webhook",
"forward",
"store",
"drop",
"agent"
],
"description": "What to do with matching mail. Defaults to webhook."
},
"destination": {
"type": "string",
"description": "Required for action webhook (URL) or forward (address)."
},
"agentPrompt": {
"type": "string",
"description": "Required for action agent — instructions for the inbox agent."
},
"agentForwardTo": {
"type": "array",
"items": {
"type": "string"
},
"description": "For action agent: addresses the inbox agent's forward tool may send to. The agent can always forward to your account email and any address on a verified domain you own; this adds extra approved addresses (e.g. an escalation inbox)."
},
"agentContext": {
"type": "string",
"enum": [
"message",
"thread",
"sender"
],
"description": "For action agent: how much mail the agent may read once the sender is verified (they replied to an earlier agent message from a DMARC-passing address). 'message' (default) = only the incoming email; 'thread' = this conversation; 'sender' = all past mail with this sender."
}
}
} Response body
route.jsonAn inbound routing rule: which addresses it matches and what happens to matching mail (webhook POST, forward, store, drop, or an inbox agent). The per-route signing secret is returned ONCE on create and via GET /api/domains/:id/webhook/secret — list responses omit it.
| Field | Type | Notes |
|---|---|---|
| id req | string | Route id (rte_…). |
| user_id req | string | Owning account (usr_…). |
| match_pattern req | string | Which recipient addresses this route matches: an exact address, `*@domain`, a prefix pattern like `ticket+*@domain`, or a `/regex/`. |
| action req | "webhook" · "forward" · "store" · "drop" · "agent" | What happens to a matching message. |
| destination | string · null | Webhook URL or forward address. null for store/drop/agent actions. |
| agent_prompt | string · null | Instructions for the built-in inbox agent (action 'agent' only). |
| agent_forward_to | string · null | Extra addresses the inbox agent's forward tool may reach, as a JSON array string. null = owner-controlled addresses only. |
| agent_context | "message" · "thread" · "sender" · null | How much mail the inbox agent may read once the sender is verified. null = 'message' (just the inbound email). |
| active req | 0 · 1 | 1 while the route is enabled. |
| ack_mode req | "lenient" · "ack" | Webhook acknowledgement strictness: 'lenient' accepts any 2xx; 'ack' also requires {"status":"ok"} (or the x-mailkite-ack header) on every delivery. |
| last_status | "ok" · "fail" · "running" · "timeout" · null | Outcome of the route's most recent action. null = never exercised. |
| last_status_message | string · null | Human-readable detail of the last outcome (e.g. 'HTTP 500'). |
| last_status_code | integer · null | Transport status code of the last outcome, when relevant. |
| last_status_at | integer · null | When the last outcome landed, in Unix epoch milliseconds (UTC); null when it has never happened. |
| consecutive_failures | integer | Current failing streak (0 when healthy). |
| first_failed_at | integer · null | When the current failing streak began, in Unix epoch milliseconds (UTC); null when it has never happened. |
| unhealthy_notified_at | integer · null | When the owner was emailed about the current streak, in Unix epoch milliseconds (UTC); null when it has never happened. |
| signing_secret | string · null | Per-route webhook signing secret (whsec_…). Returned on create; read later via GET /api/domains/:id/webhook/secret. null until first read lazily creates it. |
| created_at req | integer | When the route was created, in Unix epoch milliseconds (UTC). |
An actual response, recorded from the conformance suite.
{
"id": "rte_4Bn8XcVm",
"user_id": "usr_7Fj3MnQw",
"match_pattern": "*@myapp.ai",
"action": "webhook",
"destination": "https://myapp.ai/hooks/mailkite",
"agent_prompt": null,
"agent_forward_to": null,
"agent_context": null,
"active": 1,
"ack_mode": "lenient",
"last_status": "ok",
"last_status_message": null,
"last_status_code": 200,
"last_status_at": 1769817600000,
"consecutive_failures": 0,
"first_failed_at": null,
"unhealthy_notified_at": null,
"signing_secret": null,
"created_at": 1769731200000
} {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://api.mailkite.dev/v1/schemas/route.json",
"title": "Route",
"description": "An inbound routing rule: which addresses it matches and what happens to matching mail (webhook POST, forward, store, drop, or an inbox agent). The per-route signing secret is returned ONCE on create and via GET /api/domains/:id/webhook/secret — list responses omit it.",
"type": "object",
"required": [
"id",
"user_id",
"match_pattern",
"action",
"active",
"ack_mode",
"created_at"
],
"properties": {
"id": {
"type": "string",
"description": "Route id (rte_…).",
"examples": [
"rte_4Bn8XcVm"
]
},
"user_id": {
"type": "string",
"description": "Owning account (usr_…).",
"examples": [
"usr_7Fj3MnQw"
]
},
"match_pattern": {
"type": "string",
"description": "Which recipient addresses this route matches: an exact address, `*@domain`, a prefix pattern like `ticket+*@domain`, or a `/regex/`.",
"examples": [
"*@myapp.ai"
]
},
"action": {
"type": "string",
"enum": [
"webhook",
"forward",
"store",
"drop",
"agent"
],
"description": "What happens to a matching message."
},
"destination": {
"type": [
"string",
"null"
],
"description": "Webhook URL or forward address. null for store/drop/agent actions.",
"examples": [
"https://myapp.ai/hooks/mailkite"
]
},
"agent_prompt": {
"type": [
"string",
"null"
],
"description": "Instructions for the built-in inbox agent (action 'agent' only)."
},
"agent_forward_to": {
"type": [
"string",
"null"
],
"description": "Extra addresses the inbox agent's forward tool may reach, as a JSON array string. null = owner-controlled addresses only."
},
"agent_context": {
"type": [
"string",
"null"
],
"enum": [
"message",
"thread",
"sender",
null
],
"description": "How much mail the inbox agent may read once the sender is verified. null = 'message' (just the inbound email)."
},
"active": {
"type": "integer",
"enum": [
0,
1
],
"description": "1 while the route is enabled."
},
"ack_mode": {
"type": "string",
"enum": [
"lenient",
"ack"
],
"description": "Webhook acknowledgement strictness: 'lenient' accepts any 2xx; 'ack' also requires {\"status\":\"ok\"} (or the x-mailkite-ack header) on every delivery."
},
"last_status": {
"type": [
"string",
"null"
],
"enum": [
"ok",
"fail",
"running",
"timeout",
null
],
"description": "Outcome of the route's most recent action. null = never exercised."
},
"last_status_message": {
"type": [
"string",
"null"
],
"description": "Human-readable detail of the last outcome (e.g. 'HTTP 500')."
},
"last_status_code": {
"type": [
"integer",
"null"
],
"description": "Transport status code of the last outcome, when relevant.",
"examples": [
200
]
},
"last_status_at": {
"type": [
"integer",
"null"
],
"description": "When the last outcome landed, in Unix epoch milliseconds (UTC); null when it has never happened.",
"examples": [
1769731200000
]
},
"consecutive_failures": {
"type": "integer",
"description": "Current failing streak (0 when healthy)."
},
"first_failed_at": {
"type": [
"integer",
"null"
],
"description": "When the current failing streak began, in Unix epoch milliseconds (UTC); null when it has never happened.",
"examples": [
1769731200000
]
},
"unhealthy_notified_at": {
"type": [
"integer",
"null"
],
"description": "When the owner was emailed about the current streak, in Unix epoch milliseconds (UTC); null when it has never happened.",
"examples": [
1769731200000
]
},
"signing_secret": {
"type": [
"string",
"null"
],
"description": "Per-route webhook signing secret (whsec_…). Returned on create; read later via GET /api/domains/:id/webhook/secret. null until first read lazily creates it."
},
"created_at": {
"type": "integer",
"description": "When the route was created, in Unix epoch milliseconds (UTC).",
"examples": [
1769731200000
]
}
}
} DELETE /api/routes/:id Delete an inbound routing rule by id. Pair with createRoute to register and tear down a webhook destination — e.g. an automation platform subscribing on enable and cleaning up on disable.
Delete an inbound routing rule by id. Pair with createRoute to register and tear down a webhook destination — e.g. an automation platform subscribing on enable and cleaning up on disable.
Response body
ok-response.jsonThe uniform acknowledgement for deletes and other actions with nothing else to report.
| Field | Type | Notes |
|---|---|---|
| ok req | true | Always true — a non-2xx error body is returned otherwise. |
An actual response, recorded from the conformance suite.
{
"ok": true
} {
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://api.mailkite.dev/v1/schemas/ok-response.json",
"title": "OK",
"description": "The uniform acknowledgement for deletes and other actions with nothing else to report.",
"type": "object",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean",
"const": true,
"description": "Always true — a non-2xx error body is returned otherwise."
}
}
}