Skip to main content

Sending

Every send endpoint triggers a Novu workflow by its workflowId — the workflow decides which channels fire and what the message looks like. Call manage/list-workflows first to discover the IDs you can trigger.

There is no "send this text to this user" endpoint: content lives in the workflow template, and payload supplies the variables it renders.

All endpoints on this page are management endpoints — they need a secret key (sk_*) or an admin JWT, not an end-user token.

Send to One User

POST /api/v1/notifications/manage/send
{
"workflowId": "push-notification",
"userId": "recipient-user-id",
"payload": {
"title": "New Message",
"body": "You have a new coaching update",
"deep_link": "travila://conversation/conv_abc"
},
"transactionId": "optional-idempotency-key"
}

Response:

{
"acknowledged": true,
"status": "processed",
"transactionId": "txn_abc123"
}
FieldTypeDescription
workflowIdstringNovu workflow identifier (required)
userIdstringRecipient user ID (required)
payloadobjectArbitrary JSON passed to the workflow template
overridesobjectPer-provider overrides passed through to Novu (e.g. FCM data payload)
transactionIdstringOptional idempotency/tracking key

Keep the transactionId you sent — it is the handle for cancelling and for checking delivery.

status comes from the delivery provider, not from us

On every send endpoint, acknowledged, status, transactionId and errors are passed through verbatim from Novu's trigger response — the platform does not normalise them. "processed" is the usual value, but treat the field as an opaque provider string and key your logic off acknowledged.

Send to Many Users

Up to 100 recipients per request. Each event carries its own workflow, payload and transaction ID, so a bulk call can mix workflows.

POST /api/v1/notifications/manage/send-bulk
{
"events": [
{
"workflowId": "push-notification",
"userId": "user-1",
"payload": {"title": "Update", "body": "New feature available"}
},
{
"workflowId": "push-notification",
"userId": "user-2",
"payload": {"title": "Update", "body": "New feature available"}
}
]
}

Response:

{
"results": [
{"acknowledged": true, "status": "processed", "transactionId": "txn_1"},
{"acknowledged": true, "status": "processed", "transactionId": "txn_2"}
]
}

Results are per-event: one recipient failing does not fail the others, so check each entry's acknowledged rather than the HTTP status alone.

Broadcast to Everyone

Not exposed on the public API

manage/broadcast has no route on api.travila.ai and returns 404. Broadcasting from the admin console works — it reaches the same handler through its own gateway — so this is about the public API only.

It is held back deliberately: management endpoints are not scope-gated at the gateway, so routing this would make "notify every subscriber in the tenant" reachable by anyone holding a valid key for that tenant.

Triggers the workflow for every subscriber in the tenant. There is no recipient list and no dry run — on staging that means every real beta tester.

POST /api/v1/notifications/manage/broadcast
{
"workflowId": "product-announcement",
"payload": {
"category": "product",
"title": "Scheduled maintenance",
"body": "The app will be briefly unavailable at 02:00 UTC."
},
"transactionId": "maintenance-2026-08-14"
}

Response:

{
"acknowledged": true,
"status": "processed",
"transactionId": "maintenance-2026-08-14"
}

payload.category is required and must be system or product — any other value is rejected. It exists so that subscribers who have muted product news still receive system messages.

To reach a defined group rather than everyone, use a topic instead.

Cancel a Pending Notification

Cancels a notification that has not been delivered yet — one waiting on a workflow delay step, a digest window, or the delivery queue. Already-delivered notifications cannot be recalled; the call succeeds with cancelled: false.

POST /api/v1/notifications/manage/cancel
{
"transactionId": "txn_abc123"
}

Response:

{
"cancelled": true,
"message": "Notification successfully cancelled"
}

When it was already delivered you get cancelled: false with "Notification could not be cancelled (may have already been delivered)" — a 200, not an error, so branch on cancelled rather than on the status code.

Scheduling and Delays

There is no send-at-a-time or send-after-a-delay endpoint on this API. Deferred delivery comes from one of two places:

  • Inside a workflow — add a delay step to the Novu workflow definition. Every trigger of that workflow then waits, and manage/cancel with the transaction ID stops it before it fires.
  • Outside the workflow — create a scheduled job that calls manage/send when it runs. Use this for calendar-shaped sends (0 9 * * 1-5, a one-off timestamp, a repeating interval) and anything a user can reschedule.

Digest / Batching

A digest collapses many events into one message. The window and grouping are configured in the workflow's digest step; this endpoint just feeds events into it.

POST /api/v1/notifications/manage/send-with-digest
{
"workflowId": "activity-digest",
"userId": "user-1",
"payload": {
"title": "Activity Update",
"body": "New activity in your coaching plan"
},
"transactionId": "digest-event-123"
}

Response:

{
"acknowledged": true,
"status": "processed",
"transactionId": "digest-event-123"
}

Remove a single event from a digest that has not yet been delivered. Once the digest has gone out this is a no-op rather than an error.

POST /api/v1/notifications/manage/cancel-digest-event
{
"transactionId": "digest-event-123"
}

Response:

{
"cancelled": true,
"message": "Digest event successfully cancelled"
}

As with manage/cancel, an already-processed digest returns cancelled: false and "Digest event could not be cancelled (may have already been processed)" rather than an error.