Skip to main content

Priorities & routing

Priority does three things: it puts the event on a broker lane, it chooses between reachability and cost when picking a channel, and — only for a Postmark-primary email setup — it changes which email provider is tried first.

Setting priority​

Send the X-Priority-Override header on POST /v1/events/trigger. The header is optional; when it is absent or unrecognised the event resolves to NORMAL.

# The header is the only place priority is set — there is no `priority` body field.
curl -X POST https://api.nervly.io/v1/events/trigger \
--connect-timeout 5 \
--max-time 10 \
-H "Authorization: Bearer $NERVLY_API_KEY" \
-H "X-Priority-Override: CRITICAL" \
-H "Content-Type: application/json" \
-d '{
"name": "otp-login",
"to": { "subscriberId": "user_8f21c", "phone": "+2348012345678" }
}'
ValueLaneUse it for
CRITICALNOTIFY_CRITICALOTPs, security alerts, fraud holds — anything blocking a user
HIGHNOTIFY_CRITICALTransaction confirmations, failed payments
NORMALNOTIFY_BULKDefault. Receipts, status updates
LOWNOTIFY_BULKDigests, marketing, anything batchable

The header is case-insensitive. Anything unrecognised silently becomes NORMAL — there is no validation error for a typo, so check the priority field in the response if it matters:

{
"eventId": "evt_9c4f1a2b3d5e6f708192a3b4c5d6e7f8",
"status": "QUEUED",
"priority": "CRITICAL",
"channel": "sms",
"timestamp": "2026-08-28T09:15:04.221Z"
}

What priority actually changes​

The broker lane and stream. Every accepted event is published to NATS JetStream on:

notify.{class}.{channel}

class is critical when the resolved priority is CRITICAL or HIGH (stream NOTIFY_CRITICAL) and bulk for NORMAL and LOW (stream NOTIFY_BULK). So a CRITICAL SMS produces notify.critical.sms, and a NORMAL email produces notify.bulk.email. The workspace, subscriber and payload travel in the Protobuf message body, not the subject, so subject cardinality does not grow with signups and one tenant's digest can never sit in front of another tenant's OTP.

Bulk always uses the bulk lane​

POST /v1/events/bulk ignores X-Priority-Override. Every event in a batch is published to NOTIFY_BULK on notify.bulk.{channel}, even if you set the header to CRITICAL. Use POST /v1/events/trigger when a lane guarantee matters for a specific event.

The channel. Urgent events take the most reachable channel, routine events the cheapest — so the same recipient gets SMS for a CRITICAL event and email for a NORMAL one. This is the single biggest cost lever you have. See Channels & providers.

The email provider. Priority does not choose the email provider on its own. The order is resolved per workspace: a workspace with an explicit enabled email provider order uses that order for every priority, otherwise the worker uses the deployment's email primary provider. That default is resend, so every priority tries Resend first, then ZeptoMail. Priority only reorders the built-in order when the email primary provider is postmark — then CRITICAL/HIGH tries Postmark → SendGrid and NORMAL/LOW tries SendGrid → Postmark. A sendgrid primary always yields SendGrid → Postmark, a zeptomail primary always yields ZeptoMail → Resend, and a cloudflare primary always yields Cloudflare → Resend → ZeptoMail, regardless of priority. See Channels & providers.

Priority does not change SMS provider order, and does not bypass rate limits or subscriber preferences. A CRITICAL event to a subscriber who has turned off SMS is still suppressed — see Subscriber preferences.

The subject's channel is the channel Nervly chose​

The gateway and the worker resolve the channel with the same rules, so notify.bulk.email means the event was routed as email. The trigger response reports the same value as channel.

It is still not a guarantee of the delivered channel

If every provider on the chosen channel rejects the message, the worker falls back to the next eligible channel — the event stays on its original subject while going out by a different route. For what actually carried a message, read channel from the delivery receipt, not from the subject.

The full path of an event​

The gateway waits for the broker's ack before returning, so a 202 means the event is durable. Everything after the ack is asynchronous.

Next​