Create an inbound route

Create an inbound route from an expression and actions, or with the one-line convenience body { address, url, secret } that stores and forwards.

Two body shapes are accepted — exactly one of them per request:

  • Full form — { "expression", "actions", "priority"?, "enabled"? }: any expression of the grammar and one to five ordered actions.
  • Convenience form — { "address", "url", "secret"?, "priority"?, "enabled"? }: the server builds match_recipient("<address>") (a literal, case-insensitive match on that one address) with the actions [{"type":"store"},{"type":"forward","url":"<url>","secret":"<secret>"}] — the message is kept for the poll API and POSTed to your endpoint.

POST /v3/routes

Request body

ParameterTypeRequiredDescription
expressionstringOptionalFull form. match_recipient("…"), match_header("name", "…") or catch_all() — up to 1 000 characters, patterns up to 256.
actionsobject[]OptionalFull form. 1–5 of {"type":"store"}, {"type":"forward","url":"https://…","secret":"…"}, {"type":"stop"}, run in order.
addressstringOptionalConvenience form. A single e-mail address to match literally.
urlstring (URL)OptionalConvenience form. Public HTTPS URL that receives the signed POST.
secretstringOptionalConvenience form, optional. 8–128 characters; enables the Apifon-Signature HMAC-SHA256 header. Stored encrypted, never returned.
priorityintegerOptionalEvaluation priority, 0–1 000 000 — lower runs first. Default 0.
enabledbooleanOptionalDisabled routes are never evaluated. Default true.

Requires a full_access key. Changes apply to the next message received (routes are cached for up to 30 seconds on the receiver).

Responses

StatusDescription
201Created. The route with its public actions (has_secret instead of the secret).
400validation_error — body shape (both forms at once, neither form), or a forward url that is not a public HTTPS address.
401Missing or invalid API key.
403insufficient_scope — route writes need a full_access key.
422invalid_expression — the grammar rejected the expression (position in message); invalid_actions — empty list, unknown type, forward without an https:// URL, more than five actions.

Code examples

cURL
# Convenience form: store + forward everything sent to one address
curl -X POST https://api.wemail.io/v3/routes \
  -H "Authorization: Bearer afn_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "kostas@leads.example.com",
    "url": "https://app.example.com/inbound",
    "secret": "whsec_replace_me_1234"
  }'

# Full form: drop auto-replies before anything else
curl -X POST https://api.wemail.io/v3/routes \
  -H "Authorization: Bearer afn_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "expression": "match_header(\"auto-submitted\", \"auto-replied\")",
    "actions": [{ "type": "stop" }],
    "priority": 0
  }'
Node.js
const res = await fetch("https://api.wemail.io/v3/routes", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.WEMAIL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    expression: 'match_recipient(".*@leads\\\\.example\\\\.com")',
    actions: [
      { type: "store" },
      { type: "forward", url: "https://app.example.com/inbound", secret: "whsec_replace_me_1234" },
    ],
    priority: 10,
  }),
});
const route = await res.json(); // 201 — actions[1].has_secret === true
Python
import os, requests

r = requests.post(
    "https://api.wemail.io/v3/routes",
    headers={"Authorization": f"Bearer {os.environ['WEMAIL_API_KEY']}"},
    json={
        "address": "kostas@leads.example.com",
        "url": "https://app.example.com/inbound",
        "secret": "whsec_replace_me_1234",
    },
)
route = r.json()  # 201 — match_recipient("kostas@leads.example.com") + [store, forward]
Go
client, _ := wemail.NewClient(os.Getenv("WEMAIL_API_KEY"))
ctx := context.WithValue(context.Background(), wemail.ContextAccessToken, os.Getenv("WEMAIL_API_KEY"))
req := wemail.CreateInboundRouteRequest{}
req.SetAddress("kostas@leads.example.com")
req.SetUrl("https://app.example.com/inbound")
req.SetSecret("whsec_replace_me_1234")
route, _, err := client.API.RoutesAPI.CreateInboundRoute(ctx).CreateInboundRouteRequest(req).Execute()
ResponseExample response
{
  "id": "3d9a1f6e-2b7c-4c8d-9e0f-7a1b2c3d4e5f",
  "account_id": "acc_01HBYD3M…",
  "expression": "match_recipient(\"kostas@leads.example.com\")",
  "actions": [
    { "type": "store" },
    { "type": "forward", "url": "https://app.example.com/inbound", "has_secret": true }
  ],
  "priority": 0,
  "enabled": true,
  "created_at": "2026-11-03T07:59:30.000Z"
}