Skip to content

Send a notification

POST
/v1/notifications
curl --request POST \
--url https://your-notavia-host/v1/notifications \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "channel": "email", "recipient": { "address": "example", "name": "example", "external_user_id": "example", "endpoint": "example", "slack_user_id": "example", "slack_channel_id": "example", "teams_endpoint_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "discord_endpoint_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" }, "subject": "example", "html_body": "example", "text_body": "example", "template_key": "example", "template_data": {}, "action_url": "example", "category": "example", "attachments": [ { "filename": "example", "content_type": "example", "content_base64": "example" } ], "from_name": "example", "reply_to": "hello@example.com" }'

Persists the notification and dispatches it via the requested channel. Returns 202 Accepted on the first successful call. Returns 200 OK when the same Idempotency-Key is replayed within 24 hours.

Idempotency-Key
string

Client-generated key (UUID recommended). Repeat requests with the same key within 24 hours return the original response without re-sending.

Media type application/json
object
channel
required

Notification channel identifier.

string
Allowed values: email in_app webhook sms slack teams discord
recipient
required

Identifies the notification target. At most one typed field should be set; the server selects the correct field based on channel.

  • Email / SMS / In-app: use address (email address, phone number E.164, or opaque external user id).
  • Slack: use slack_user_id (for DMs) or slack_channel_id (for channel posts).
  • Teams / Discord: use endpoint (the endpoint key, e.g. "billing-alerts") or the legacy teams_endpoint_id / discord_endpoint_id (UUID of the configured endpoint).
  • external_user_id resolves the recipient via stored preference/inbox records.
  • name is used only for email To: display name and in-app display.
object
address
string
nullable
name
string
nullable
external_user_id
string
nullable
endpoint

The key of a Discord or Teams endpoint (e.g. "billing-alerts"). Preferred over the legacy UUID fields. When set, teams_endpoint_id / discord_endpoint_id are ignored.

string
nullable
slack_user_id

Slack user id (Uxxxxxxxx) for DM delivery. Mutually exclusive with slack_channel_id.

string
nullable
slack_channel_id

Slack channel id (Cxxxxxxxx) for channel-post delivery. Mutually exclusive with slack_user_id.

string
nullable
teams_endpoint_id

UUID of the TeamsWebhookEndpoint to send to. Legacy — prefer endpoint (the key).

string format: uuid
nullable
discord_endpoint_id

UUID of the DiscordWebhookEndpoint to send to. Legacy — prefer endpoint (the key).

string format: uuid
nullable
subject

Email subject line. Ignored for non-email channels.

string
nullable
html_body

Inline HTML body. Ignored when template_key is set. Email/in-app only.

string
nullable
text_body

Inline plain-text body. Email/SMS only.

string
nullable
template_key

Key of a stored template. Required for Slack, Teams, Discord channels.

string
nullable
template_data

Liquid template variables merged at render time.

object
key
additional properties
any
action_url

Optional CTA URL surfaced in in-app notifications.

string
nullable
category

Preference category key. Suppresses the send when the recipient has opted out.

string
nullable
attachments

File attachments for email notifications (email channel only). Maximum 10 files; maximum 15 MB per file and 15 MB total. File content must be base64-encoded. Bytes are stored ephemerally and deleted after delivery — only metadata is retained in the audit log.

Array<object>
nullable
object
filename
required

File name shown to the recipient, e.g. "statement.pdf".

string
<= 255 characters
content_type
required

MIME type of the file, e.g. "application/pdf".

string
<= 255 characters
content_base64
required

Base64-encoded file content.

string
from_name

Optional per-message sender display name (email channel only). Overrides the environment’s default display name; the From address itself is fixed by the environment’s sender identity. Must not contain <, >, or control characters. Ignored when the managed sender is operator-locked.

string
nullable <= 200 characters
reply_to

Optional per-message Reply-To address (email channel only). Must be a bare, valid email address.

string format: email
nullable <= 320 characters

Idempotent replay — previously accepted notification returned.

Media type application/json
object
id
string format: uuid
status
string
Allowed values: queued sending sent failed suppressed delivered bounced complained
channel

Notification channel identifier.

string
Allowed values: email in_app webhook sms slack teams discord
recipient
object
address
string
nullable
name
string
nullable
subject
string
nullable
html_body
string
nullable
text_body
string
nullable
template_key
string
nullable
template_data
object
key
additional properties
any
idempotency_key
string
nullable
action_url
string
nullable
attempt_count
integer
created_at
string format: date-time
events
Array<object>
object
type

A step in the message’s life: Queued, Sending, Sent, Retrying, Failed, Delivered, Bounced, Complained, DeliveryDelayed, Opened, Clicked, FailedOver, AttemptFailed. FailedOver means a provider refused the message and the next provider in your chain was tried; AttemptFailed means a provider refused it and there was nowhere left to go. Deliberately an open string, not an enum — new values are added over time and must not break a generated client.

string
occurred_at
string format: date-time
detail
string
nullable
suppression_reason
string
nullable
attachments

Metadata for files that were attached to this email notification. Bytes are purged after delivery; the purged flag indicates whether this has occurred. Omitted when the notification had no attachments.

Array<object>
object
filename

Original file name.

string
content_type

MIME type of the file.

string
size_bytes

File size in bytes.

integer format: int64
purged

True when the attachment bytes have been deleted from ephemeral storage after delivery. The metadata fields (filename, content_type, size_bytes) are always retained.

boolean
Example
{
"status": "queued",
"channel": "email",
"events": [
{
"type": "FailedOver"
}
]
}

Notification accepted and queued for dispatch.

Media type application/json
object
id
string format: uuid
status
string
Allowed values: queued sending sent failed suppressed delivered bounced complained
channel

Notification channel identifier.

string
Allowed values: email in_app webhook sms slack teams discord
recipient
object
address
string
nullable
name
string
nullable
subject
string
nullable
html_body
string
nullable
text_body
string
nullable
template_key
string
nullable
template_data
object
key
additional properties
any
idempotency_key
string
nullable
action_url
string
nullable
attempt_count
integer
created_at
string format: date-time
events
Array<object>
object
type

A step in the message’s life: Queued, Sending, Sent, Retrying, Failed, Delivered, Bounced, Complained, DeliveryDelayed, Opened, Clicked, FailedOver, AttemptFailed. FailedOver means a provider refused the message and the next provider in your chain was tried; AttemptFailed means a provider refused it and there was nowhere left to go. Deliberately an open string, not an enum — new values are added over time and must not break a generated client.

string
occurred_at
string format: date-time
detail
string
nullable
suppression_reason
string
nullable
attachments

Metadata for files that were attached to this email notification. Bytes are purged after delivery; the purged flag indicates whether this has occurred. Omitted when the notification had no attachments.

Array<object>
object
filename

Original file name.

string
content_type

MIME type of the file.

string
size_bytes

File size in bytes.

integer format: int64
purged

True when the attachment bytes have been deleted from ephemeral storage after delivery. The metadata fields (filename, content_type, size_bytes) are always retained.

boolean
Example
{
"status": "queued",
"channel": "email",
"events": [
{
"type": "FailedOver"
}
]
}

Validation or request error.

Media type application/json
object
error
required
object
type
required
string
code
required
string
message
required
string
param
string
nullable
Example generated
{
"error": {
"type": "example",
"code": "example",
"message": "example",
"param": "example"
}
}

Missing or invalid credentials.

Media type application/json
object
error
required
object
type
required
string
code
required
string
message
required
string
param
string
nullable
Example generated
{
"error": {
"type": "example",
"code": "example",
"message": "example",
"param": "example"
}
}

Credentials do not have the required scope.

Media type application/json
object
error
required
object
type
required
string
code
required
string
message
required
string
param
string
nullable
Example generated
{
"error": {
"type": "example",
"code": "example",
"message": "example",
"param": "example"
}
}

Conflict (e.g. duplicate key, idempotency collision).

Media type application/json
object
error
required
object
type
required
string
code
required
string
message
required
string
param
string
nullable
Example generated
{
"error": {
"type": "example",
"code": "example",
"message": "example",
"param": "example"
}
}