Skip to content

Core concepts

A notification is one message sent to one recipient on one channel. Sending either supplies the content inline or references a template by key.

A template is a reusable, per-tenant, runtime-editable message with per-channel bodies (email subject/HTML, SMS text, chat blocks). Templates render with the variables you pass at send time.

Every template has an editable draft plus a series of immutable, numbered published versions — sends and /render always use the latest published version, so a saved draft edit only goes live once you publish it (the dashboard’s Publish/Version-history/rollback controls, or POST /v1/templates/{key}/publish). A template also supports per-locale channel bodies with a send-time locale (falling back from an exact tag to a language-only match, then to the template’s default locale).

Notavia delivers on multiple channels: email, in_app (the in-app inbox), sms, and chat (slack, teams, discord). A single workflow can fan out across several channels.

Write endpoints accept an idempotency key so a retried request never double-sends. Repeat a request with the same key within 24 hours and you get the original response back without re-sending. Pass it per the SDK (idempotency_key / idempotencyKey) or the Idempotency-Key header on REST.

Every error response uses one consistent shape:

{
"error": {
"type": "usage_error",
"code": "usage_limit_exceeded",
"message": "Monthly send limit reached for plan 'starter'.",
"param": null
}
}

The code is stable and machine-readable; the message is for humans. Match on code, never on message. type is a broader category and is always present; param names the offending field on validation errors (otherwise null).

Requests are rate-limited per tenant and per key. When you exceed a limit you get 429 Too Many Requests with a Retry-After header — the SDKs honour it automatically with backoff.

The API is versioned in the URL (/v1/*) so an embedded integration never breaks silently. Breaking changes ship under a new version; the changelog records every change.