Notifications API
Every Notifications action (20) and data model (7): endpoints, scopes, input, preconditions, events and examples.
Who is told about what — by email, SMS, WhatsApp or in the app.
Module code notifications · 20 actions · 7 data models · 18 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: notifications (everything), notifications:read (read only) or notifications:<capability>.
Resources
| Resource | Table | List and read | POST | PATCH | DELETE |
|---|---|---|---|---|---|
notification_channels | notification_channel | /api/v1/notification_channels | |||
notification_deliveries | notification_delivery | /api/v1/notification_deliveries | |||
notification_email_templates | notification_email_template | /api/v1/notification_email_templates | |||
notification_inboxes | notification_inbox | /api/v1/notification_inboxes | |||
notification_preferences | notification_preference | /api/v1/notification_preferences | |||
notification_rules | notification_rule | /api/v1/notification_rules | |||
notification_user_settings | notification_user_setting | /api/v1/notification_user_settings |
Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.
Actions
| Action | Needs | What it does |
|---|---|---|
notifications.create_channel | notifications:manage | Add a delivery channel |
notifications.create_rule | notifications:manage | Add a notification rule |
notifications.delete_channel | notifications:delete | Remove a delivery channel |
notifications.delete_rule | notifications:delete | Remove a notification rule |
notifications.mark_read | notifications:read | Mark notifications read |
notifications.purge_history | notifications:delete | Sweep delivery history |
notifications.queue_delivery | notifications:handle | Queue a notification |
notifications.record_site_email | notifications:handle | Record a site email |
notifications.reset_email_template | notifications:manage | Restore the default wording |
notifications.retry_delivery | notifications:manage | Retry a notification |
notifications.save_email_template | notifications:manage | Save a customer email |
notifications.send_customer_message | notifications:handle | Send a message to the customer |
notifications.send_email | notifications:handle | Send an email |
notifications.send_test | notifications:manage | Send a test notification |
notifications.send_test_email_template | notifications:manage | Send a test email |
notifications.set_preference | notifications:read | Set a notification preference |
notifications.set_rule_active | notifications:manage | Switch a rule on or off |
notifications.set_user_settings | notifications:read | Set my notification schedule |
notifications.settle_delivery | notifications:handle | Record a delivery outcome |
notifications.update_rule | notifications:manage | Edit a notification rule |
notifications.create_channel
Add a delivery channel — Where notifications go: a webhook, a set of addresses, a Slack channel or a push endpoint.
Needs notifications:manage · changes data
https://app.getera.io/api/v1/notification_channels/actions/create_channel- Canonical address:
POST /api/v1/actions/notifications.create_channel
Input
| Field | Type | Required | Notes |
|---|---|---|---|
type | string (enum) | yes | Channel · Allowed values: webhook, email, slack, push |
name | string | yes | Name · max 120 |
url | string | URL · Webhook and push channels. · max 2000 | |
recipients | string | Recipients · Email channels. Comma-separated. · max 2000 | |
config | string | Configuration · JSON. Slack channels carry the account and the channel id here. · max 8000 | |
credential_id | uuid | Credential · Holds the signing secret or the OAuth token. Never stored on the channel itself. |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
invalid_url | That does not look like a web address. |
insecure_url | The address must use https. |
url_required | A webhook or push channel needs a URL. |
recipients_required | An email channel needs at least one address. |
too_many_recipients | An email channel may carry at most ten addresses. |
invalid_config | The configuration must be a JSON object. |
name_taken | This workspace already has a channel of that type with that name. |
Events it publishes: notifications.channel_created
What it writes: notification_channel (insert) — Adds the channel, unverified until something has reached it
curl -X POST https://app.getera.io/api/v1/notification_channels/actions/create_channel \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"type":"webhook","name":"Name"}'{
"ok": true,
"result": "…",
"events": [
"notifications.channel_created"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationChannels.createChannel({
type: "webhook",
name: "Name"
})era notification_channels create_channel \
--type "webhook" \
--name "Name"{
"name": "era__notifications__create_channel",
"arguments": {
"type": "webhook",
"name": "Name"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 invalid_url, insecure_url, url_required, recipients_required, too_many_recipients, invalid_config, name_taken · 429 slow down
notifications.create_rule
Add a notification rule — Which events reach a channel or a person, in which words, and how often.
Needs notifications:manage · changes data
https://app.getera.io/api/v1/notification_rules/actions/create_rule- Canonical address:
POST /api/v1/actions/notifications.create_rule
Input
| Field | Type | Required | Notes |
|---|---|---|---|
channel_id | uuid | Channel · For a channel rule. · id of notification_channel | |
name | string | yes | Name · max 120 |
events | string | Events · Comma-separated. Leave empty for every event. · max 2000 | |
condition | string | Condition · JSON. Leave empty to fire on every matching event. · max 4000 | |
cooldown_minutes | number | Quiet period (minutes) | |
include_output | boolean | Include the result | |
include_trace | boolean | Include the trace · Webhook channels only — a trace is too large for email and Slack. | |
recipient | string (enum) | Who is told · A channel, or people found in the event (owner, assignee, mentioned…) or chosen here. · Allowed values: channel, owner, assignee, mentioned, recipient, member, role, capability, customer | |
recipient_user_id | uuid | Member · For “a specific member”. | |
recipient_role | string | Role · For “everyone with a role”: the role key. · max 80 | |
recipient_capability | string | Permission · For “everyone holding a permission”: module:capability. · max 80 | |
mediums | string | Reach them by · Comma-separated: in_app, email, sms, whatsapp. · max 200 | |
category | string | Category · What a person switches on or off. Empty means the event’s module. · max 41 | |
title_template | string | Title · Variables: {{event_label}}, {{recipient.name}}, {{workspace.name}}, or any payload key like {{person}}. · max 300 | |
body_template | string | Message · max 4000 | |
link_template | string | Link · A path in the app. Empty means the record the event is about. · max 500 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
channel_not_found | No such channel in this workspace. |
trace_needs_webhook | Only a webhook channel can carry a trace. |
invalid_condition | The condition must be a JSON object. |
cooldown_out_of_range | The quiet period must be between 0 minutes and 7 days. |
name_taken | This workspace already has a rule with that name. |
rule_limit_reached | This workspace already has the maximum number of rules on that channel. |
recipient_incomplete | The rule must say fully who it tells: a channel, or people and how to reach them. |
Events it publishes: notifications.rule_created
What it writes: notification_rule (insert) — Adds the rule, active
curl -X POST https://app.getera.io/api/v1/notification_rules/actions/create_rule \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name":"Name"}'{
"ok": true,
"result": "…",
"events": [
"notifications.rule_created"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationRules.createRule({
name: "Name"
})era notification_rules create_rule \
--name "Name"{
"name": "era__notifications__create_rule",
"arguments": {
"name": "Name"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 channel_not_found, trace_needs_webhook, invalid_condition, cooldown_out_of_range, name_taken, rule_limit_reached, recipient_incomplete · 429 slow down
notifications.delete_channel
Remove a delivery channel — Refused while a rule still points at it, so no rule is silently orphaned.
Needs notifications:delete · removes or cannot be undone · asks a person to confirm when Era runs it
https://app.getera.io/api/v1/notification_channels/actions/delete_channel- Canonical address:
POST /api/v1/actions/notifications.delete_channel
Input
| Field | Type | Required | Notes |
|---|---|---|---|
channel_id | uuid | yes | Channel |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
channel_not_found | No such channel in this workspace. |
channel_in_use | A rule still sends to that channel. |
Events it publishes: notifications.channel_deleted
What it writes: notification_channel (delete) — Removes the channel
curl -X POST https://app.getera.io/api/v1/notification_channels/actions/delete_channel \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"channel_id":"CHANNEL_ID"}'{
"ok": true,
"result": "…",
"events": [
"notifications.channel_deleted"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationChannels.deleteChannel({
channel_id: "CHANNEL_ID"
})era notification_channels delete_channel \
--channel-id "CHANNEL_ID"{
"name": "era__notifications__delete_channel",
"arguments": {
"channel_id": "CHANNEL_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:delete · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 channel_not_found, channel_in_use · 429 slow down
notifications.delete_rule
Remove a notification rule — Removes the rule and its delivery history. The channel stays.
Needs notifications:delete · removes or cannot be undone · asks a person to confirm when Era runs it
https://app.getera.io/api/v1/notification_rules/actions/delete_rule- Canonical address:
POST /api/v1/actions/notifications.delete_rule
Input
| Field | Type | Required | Notes |
|---|---|---|---|
rule_id | uuid | yes | Rule |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
rule_not_found | No such rule in this workspace. |
Events it publishes: notifications.rule_deleted
What it writes: notification_rule (delete) — Removes the rule; its deliveries cascade
curl -X POST https://app.getera.io/api/v1/notification_rules/actions/delete_rule \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"rule_id":"RULE_ID"}'{
"ok": true,
"result": "…",
"events": [
"notifications.rule_deleted"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationRules.deleteRule({
rule_id: "RULE_ID"
})era notification_rules delete_rule \
--rule-id "RULE_ID"{
"name": "era__notifications__delete_rule",
"arguments": {
"rule_id": "RULE_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:delete · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 rule_not_found · 429 slow down
notifications.mark_read
Mark notifications read — Marks some or all of your in-app notifications read (or one unread again).
Needs notifications:read · changes data
https://app.getera.io/api/v1/notification_inboxes/actions/mark_read- Canonical address:
POST /api/v1/actions/notifications.mark_read
Input
| Field | Type | Required | Notes |
|---|---|---|---|
ids | string | Notifications · Comma-separated ids. · max 8000 | |
all | boolean | All of them | |
unread | boolean | Mark unread instead |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
notification_not_found | None of those notifications are yours. |
Events it publishes: notifications.inbox_read
What it writes: notification_inbox (update) — Stamps read_at on your notifications
curl -X POST https://app.getera.io/api/v1/notification_inboxes/actions/mark_read \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"ids":"Notifications"}'{
"ok": true,
"result": "…",
"events": [
"notifications.inbox_read"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationInboxes.markRead({
ids: "Notifications"
})era notification_inboxes mark_read \
--ids "Notifications"{
"name": "era__notifications__mark_read",
"arguments": {
"ids": "Notifications"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:read · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 notification_not_found · 429 slow down
notifications.purge_history
Sweep delivery history — Removes finished deliveries older than the retention window. Pending ones are never touched.
Needs notifications:delete · removes or cannot be undone
https://app.getera.io/api/v1/notification_deliveries/actions/purge_history- Canonical address:
POST /api/v1/actions/notifications.purge_history
Input
| Field | Type | Required | Notes |
|---|---|---|---|
days | number | Keep for (days) · max 3650 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
retention_too_short | Retention must be at least one day. |
Events it publishes: notifications.history_purged
What it writes: notification_delivery (delete) — Removes delivered, failed and suppressed rows older than the window
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/purge_history \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"days":1}'{
"ok": true,
"result": "…",
"events": [
"notifications.history_purged"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.purgeHistory({
days: 1
})era notification_deliveries purge_history \
--days 1{
"name": "era__notifications__purge_history",
"arguments": {
"days": 1
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:delete · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 retention_too_short · 429 slow down
notifications.queue_delivery
Queue a notification — Writes the delivery, or writes why it was deliberately not sent.
Needs notifications:handle · changes data
https://app.getera.io/api/v1/notification_deliveries/actions/queue_delivery- Canonical address:
POST /api/v1/actions/notifications.queue_delivery
Input
| Field | Type | Required | Notes |
|---|---|---|---|
rule_id | uuid | yes | Rule |
event_name | string | yes | Event · max 120 |
source_id | string | Source · The event or execution this came from. · max 200 | |
recipient_user_id | uuid | Recipient · When the notification is aimed at one person, so their preference can be honoured. | |
payload | string | Payload · JSON. The event payload the message is written from. · max 100000 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
rule_not_found | No such rule in this workspace. |
event_not_matched | That rule does not cover this event. |
Events it publishes: notifications.queued, notifications.suppressed
What it writes: notification_delivery (insert) — Writes the delivery as pending, or as suppressed with a reason; notification_rule (update) — Stamps the rule’s quiet period when it fires; notification_inbox (insert) — Puts an in-app notification in each person’s bell
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/queue_delivery \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"rule_id":"RULE_ID","event_name":"Event"}'{
"ok": true,
"result": "…",
"events": [
"notifications.queued",
"notifications.suppressed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.queueDelivery({
rule_id: "RULE_ID",
event_name: "Event"
})era notification_deliveries queue_delivery \
--rule-id "RULE_ID" \
--event-name "Event"{
"name": "era__notifications__queue_delivery",
"arguments": {
"rule_id": "RULE_ID",
"event_name": "Event"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 rule_not_found, event_not_matched · 429 slow down
notifications.record_site_email
Record a site email — Machine-only: an email the website already sent to a customer, written into the delivery log.
Needs notifications:handle · changes data
403 machine_only).https://app.getera.io/api/v1/notification_deliveries/actions/record_site_email- Canonical address:
POST /api/v1/actions/notifications.record_site_email
Input
| Field | Type | Required | Notes |
|---|---|---|---|
to | string | yes | To · max 320 |
subject | string | yes | Subject · max 300 |
text | string | Message · max 20000 | |
html | string | HTML part · max 300000 | |
event_name | string | yes | Event · max 120 |
source_id | string | Source · max 200 | |
delivered | boolean | yes | Delivered |
error | string | Error · max 2000 | |
redacted | boolean | Body not kept |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
invalid_recipient | The address is an email address. |
What it writes: notification_delivery (insert) — Writes the delivered (or failed) email row
Errors: 401 no or expired credential · 403 the credential does not hold notifications:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 invalid_recipient · 429 slow down
notifications.reset_email_template
Restore the default wording — Drops this workspace’s wording of one customer email; the default applies again.
Needs notifications:manage · removes or cannot be undone · asks a person to confirm when Era runs it
https://app.getera.io/api/v1/notification_email_templates/actions/reset_email_template- Canonical address:
POST /api/v1/actions/notifications.reset_email_template
Input
| Field | Type | Required | Notes |
|---|---|---|---|
kind | string | yes | Email · max 40 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
unknown_email_template | The email must be one of the customer emails. |
Events it publishes: notifications.email_template_changed
What it writes: notification_email_template (delete) — Removes the workspace’s wording
curl -X POST https://app.getera.io/api/v1/notification_email_templates/actions/reset_email_template \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"kind":"Email"}'{
"ok": true,
"result": "…",
"events": [
"notifications.email_template_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationEmailTemplates.resetEmailTemplate({
kind: "Email"
})era notification_email_templates reset_email_template \
--kind "Email"{
"name": "era__notifications__reset_email_template",
"arguments": {
"kind": "Email"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 unknown_email_template · 429 slow down
notifications.retry_delivery
Retry a notification — Puts a failed delivery back on the queue, due now, with its attempts reset.
Needs notifications:manage · changes data
https://app.getera.io/api/v1/notification_deliveries/actions/retry_delivery- Canonical address:
POST /api/v1/actions/notifications.retry_delivery
Input
| Field | Type | Required | Notes |
|---|---|---|---|
delivery_id | uuid | yes | Delivery |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
delivery_not_found | No such delivery in this workspace. |
delivery_not_failed | Only a failed delivery can be retried. |
Events it publishes: notifications.delivery_retried
What it writes: notification_delivery (update) — Returns the delivery to pending, due now
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/retry_delivery \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"delivery_id":"DELIVERY_ID"}'{
"ok": true,
"result": "…",
"events": [
"notifications.delivery_retried"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.retryDelivery({
delivery_id: "DELIVERY_ID"
})era notification_deliveries retry_delivery \
--delivery-id "DELIVERY_ID"{
"name": "era__notifications__retry_delivery",
"arguments": {
"delivery_id": "DELIVERY_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 delivery_not_found, delivery_not_failed · 429 slow down
notifications.save_email_template
Save a customer email — Replaces the wording of one customer email for this workspace.
Needs notifications:manage · changes data
https://app.getera.io/api/v1/notification_email_templates/actions/save_email_template- Canonical address:
POST /api/v1/actions/notifications.save_email_template
Input
| Field | Type | Required | Notes |
|---|---|---|---|
kind | string | yes | Email · max 40 |
subject | string | yes | Subject · max 300 |
body | string | yes | Body · max 20000 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
unknown_email_template | The email must be one of the customer emails. |
Events it publishes: notifications.email_template_changed
What it writes: notification_email_template (upsert) — Writes the workspace’s wording
curl -X POST https://app.getera.io/api/v1/notification_email_templates/actions/save_email_template \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"kind":"Email","subject":"Subject","body":"Body"}'{
"ok": true,
"result": "…",
"events": [
"notifications.email_template_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationEmailTemplates.saveEmailTemplate({
kind: "Email",
subject: "Subject",
body: "Body"
})era notification_email_templates save_email_template \
--kind "Email" \
--subject "Subject" \
--body "Body"{
"name": "era__notifications__save_email_template",
"arguments": {
"kind": "Email",
"subject": "Subject",
"body": "Body"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 unknown_email_template · 429 slow down
notifications.send_customer_message
Send a message to the customer — Queues one message to one customer — WhatsApp or SMS through a connected inbox, email through the branded sender, or the best of the three.
Needs notifications:handle · reaches outside (sends, publishes or charges)
https://app.getera.io/api/v1/notification_deliveries/actions/send_customer_message- Canonical address:
POST /api/v1/actions/notifications.send_customer_message
Input
| Field | Type | Required | Notes |
|---|---|---|---|
customer_id | uuid | yes | Customer |
medium | string (enum) | yes | By · Allowed values: sms, whatsapp, email, auto |
text | string | yes | Message · max 1600 |
subject | string | Subject · max 300 | |
event_name | string | yes | Event · max 120 |
source_id | string | Source · max 200 |
Events it publishes: notifications.queued
What it writes: notification_delivery (insert) — Writes a pending delivery to one customer on one medium
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/send_customer_message \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"customer_id":"CUSTOMER_ID","medium":"sms","text":"Message","event_name":"Event"}'{
"ok": true,
"result": "…",
"events": [
"notifications.queued"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.sendCustomerMessage({
customer_id: "CUSTOMER_ID",
medium: "sms",
text: "Message",
event_name: "Event"
})era notification_deliveries send_customer_message \
--customer-id "CUSTOMER_ID" \
--medium "sms" \
--text "Message" \
--event-name "Event"{
"name": "era__notifications__send_customer_message",
"arguments": {
"customer_id": "CUSTOMER_ID",
"medium": "sms",
"text": "Message",
"event_name": "Event"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 429 slow down
notifications.send_email
Send an email — Queues one message to one address through an email channel and the real sender.
Needs notifications:handle · reaches outside (sends, publishes or charges)
https://app.getera.io/api/v1/notification_deliveries/actions/send_email- Canonical address:
POST /api/v1/actions/notifications.send_email
Input
| Field | Type | Required | Notes |
|---|---|---|---|
to | string | yes | To · max 320 |
subject | string | yes | Subject · max 300 |
text | string | yes | Message · max 20000 |
html | string | HTML part · max 300000 | |
event_name | string | yes | Event · max 120 |
source_id | string | Source · max 200 | |
channel_id | uuid | Channel · id of notification_channel | |
from_connection | string | Send from · mine = the Run-as person’s own Gmail/Outlook · workspace = the company one · or a connection id. Empty = the platform sender. · max 64 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
invalid_recipient | The address is not an email address. |
no_email_channel | No active email channel exists to send from. |
bad_connection | Send from is mine, workspace or a connection id. |
Events it publishes: notifications.queued
What it writes: notification_delivery (insert) — Writes a pending delivery addressed to one recipient
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/send_email \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"to":"To","subject":"Subject","text":"Message","event_name":"Event"}'{
"ok": true,
"result": "…",
"events": [
"notifications.queued"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.sendEmail({
to: "To",
subject: "Subject",
text: "Message",
event_name: "Event"
})era notification_deliveries send_email \
--to "To" \
--subject "Subject" \
--text "Message" \
--event-name "Event"{
"name": "era__notifications__send_email",
"arguments": {
"to": "To",
"subject": "Subject",
"text": "Message",
"event_name": "Event"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 invalid_recipient, no_email_channel, bad_connection · 429 slow down
notifications.send_test
Send a test notification — Queues one message to the channel through the real sender and records the outcome.
Needs notifications:manage · reaches outside (sends, publishes or charges)
https://app.getera.io/api/v1/notification_deliveries/actions/send_test- Canonical address:
POST /api/v1/actions/notifications.send_test
Input
| Field | Type | Required | Notes |
|---|---|---|---|
channel_id | uuid | yes | Channel · id of notification_channel |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
channel_not_found | No such channel in this workspace. |
Events it publishes: notifications.test_queued
What it writes: notification_delivery (insert) — Writes a pending test delivery
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/send_test \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"channel_id":"NOTIFICATION_CHANNEL_ID"}'{
"ok": true,
"result": "…",
"events": [
"notifications.test_queued"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.sendTest({
channel_id: "NOTIFICATION_CHANNEL_ID"
})era notification_deliveries send_test \
--channel-id "NOTIFICATION_CHANNEL_ID"{
"name": "era__notifications__send_test",
"arguments": {
"channel_id": "NOTIFICATION_CHANNEL_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 channel_not_found · 429 slow down
notifications.send_test_email_template
Send a test email — Sends one customer email, filled with sample values, to an address you choose.
Needs notifications:manage · reaches outside (sends, publishes or charges)
https://app.getera.io/api/v1/notification_deliveries/actions/send_test_email_template- Canonical address:
POST /api/v1/actions/notifications.send_test_email_template
Input
| Field | Type | Required | Notes |
|---|---|---|---|
kind | string | yes | Email · max 40 |
to | string | yes | Send to · max 320 |
subject | string | Subject · max 300 | |
body | string | Body · max 20000 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
unknown_email_template | The email must be one of the customer emails. |
invalid_recipient | The address is not an email address. |
no_email_channel | No active email channel exists to send from. |
Events it publishes: notifications.test_queued
What it writes: notification_delivery (insert) — Writes a pending test delivery to one address
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/send_test_email_template \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"kind":"Email","to":"Send to"}'{
"ok": true,
"result": "…",
"events": [
"notifications.test_queued"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.sendTestEmailTemplate({
kind: "Email",
to: "Send to"
})era notification_deliveries send_test_email_template \
--kind "Email" \
--to "Send to"{
"name": "era__notifications__send_test_email_template",
"arguments": {
"kind": "Email",
"to": "Send to"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 unknown_email_template, invalid_recipient, no_email_channel · 429 slow down
notifications.set_preference
Set a notification preference — Whether someone is told, on which channel type, and until when they are muted.
Needs notifications:read · changes data
https://app.getera.io/api/v1/notification_preferences/actions/set_preference- Canonical address:
POST /api/v1/actions/notifications.set_preference
Input
| Field | Type | Required | Notes |
|---|---|---|---|
user_id | uuid | Person · Leave empty to change your own. | |
channel_type | string (enum) | yes | Channel · Allowed values: webhook, email, slack, push, in_app |
event_name | string | Event or category · Leave empty to cover every event on that channel type; a key without a dot is a category. · max 120 | |
enabled | boolean | yes | Tell me |
muted_until | date-time | Muted until · A snooze. Clears itself. |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_your_preference | Changing someone else’s preferences needs the manage capability. |
not_a_member | That person is not a member of this workspace. |
mute_in_past | The mute already expires in the past. |
Events it publishes: notifications.preference_changed
What it writes: notification_preference (upsert) — Writes the person’s preference for that channel type and event
curl -X POST https://app.getera.io/api/v1/notification_preferences/actions/set_preference \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"channel_type":"webhook","enabled":true}'{
"ok": true,
"result": "…",
"events": [
"notifications.preference_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationPreferences.setPreference({
channel_type: "webhook",
enabled: true
})era notification_preferences set_preference \
--channel-type "webhook" \
--enabled true{
"name": "era__notifications__set_preference",
"arguments": {
"channel_type": "webhook",
"enabled": true
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:read · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_your_preference, not_a_member, mute_in_past · 429 slow down
notifications.set_rule_active
Switch a rule on or off — A rule that is off matches nothing and queues nothing.
Needs notifications:manage · changes data
https://app.getera.io/api/v1/notification_rules/actions/set_rule_active- Canonical address:
POST /api/v1/actions/notifications.set_rule_active
Input
| Field | Type | Required | Notes |
|---|---|---|---|
rule_id | uuid | yes | Rule |
active | boolean | yes | Active |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
rule_not_found | No such rule in this workspace. |
no_change | The rule is already in that state. |
Events it publishes: notifications.rule_enabled, notifications.rule_disabled
What it writes: notification_rule (update) — Flips the active flag and clears the quiet period
curl -X POST https://app.getera.io/api/v1/notification_rules/actions/set_rule_active \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"rule_id":"RULE_ID","active":true}'{
"ok": true,
"result": "…",
"events": [
"notifications.rule_enabled",
"notifications.rule_disabled"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationRules.setRuleActive({
rule_id: "RULE_ID",
active: true
})era notification_rules set_rule_active \
--rule-id "RULE_ID" \
--active true{
"name": "era__notifications__set_rule_active",
"arguments": {
"rule_id": "RULE_ID",
"active": true
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 rule_not_found, no_change · 429 slow down
notifications.set_user_settings
Set my notification schedule — Timezone, language, quiet hours and email digest for one person.
Needs notifications:read · changes data
https://app.getera.io/api/v1/notification_user_settings/actions/set_user_settings- Canonical address:
POST /api/v1/actions/notifications.set_user_settings
Input
| Field | Type | Required | Notes |
|---|---|---|---|
user_id | uuid | Person · Leave empty to change your own. | |
timezone | string | Timezone · IANA name, e.g. Europe/Istanbul. Empty means the workspace’s. · max 64 | |
locale | string | Language · max 16 | |
quiet_start | string | Quiet from · HH:MM. Empty for no quiet hours. · max 5 | |
quiet_end | string | Quiet until · max 5 | |
digest | string (enum) | Email digest · Allowed values: off, hourly, daily | |
digest_hour | number | Daily digest at (hour) · min 0 · max 23 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
not_your_preference | Changing someone else’s settings needs the manage capability. |
not_a_member | That person is not a member of this workspace. |
invalid_timezone | The timezone must be an IANA name like Europe/Istanbul. |
invalid_quiet_hours | Quiet hours need both a start and an end, as HH:MM, and they must differ. |
Events it publishes: notifications.settings_changed
What it writes: notification_user_setting (upsert) — Writes the person’s schedule
curl -X POST https://app.getera.io/api/v1/notification_user_settings/actions/set_user_settings \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"user_id":"USER_ID"}'{
"ok": true,
"result": "…",
"events": [
"notifications.settings_changed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationUserSettings.setUserSettings({
user_id: "USER_ID"
})era notification_user_settings set_user_settings \
--user-id "USER_ID"{
"name": "era__notifications__set_user_settings",
"arguments": {
"user_id": "USER_ID"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:read · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_your_preference, not_a_member, invalid_timezone, invalid_quiet_hours · 429 slow down
notifications.settle_delivery
Record a delivery outcome — Marks a delivery done, or schedules the next attempt.
Needs notifications:handle · changes data
https://app.getera.io/api/v1/notification_deliveries/actions/settle_delivery- Canonical address:
POST /api/v1/actions/notifications.settle_delivery
Input
| Field | Type | Required | Notes |
|---|---|---|---|
delivery_id | uuid | yes | Delivery |
success | boolean | yes | Succeeded |
response_status | number | Response status · min 100 · max 599 | |
error_message | string | Error · max 2000 | |
duration_ms | number | Duration (ms) · min 0 | |
response_body | string | Provider response · max 2000 | |
permanent | boolean | Do not retry · The sender knows retrying cannot help — no provider configured, unsupported channel. |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
delivery_not_found | No such delivery in this workspace. |
delivery_already_settled | That delivery has already finished. |
Events it publishes: notifications.delivered, notifications.delivery_failed
What it writes: notification_delivery (update) — Records the outcome and, on a retryable failure, when to try again; notification_channel (update) — Stamps verified_at the first time something reaches the channel
curl -X POST https://app.getera.io/api/v1/notification_deliveries/actions/settle_delivery \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"delivery_id":"DELIVERY_ID","success":true}'{
"ok": true,
"result": "…",
"events": [
"notifications.delivered",
"notifications.delivery_failed"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationDeliveries.settleDelivery({
delivery_id: "DELIVERY_ID",
success: true
})era notification_deliveries settle_delivery \
--delivery-id "DELIVERY_ID" \
--success true{
"name": "era__notifications__settle_delivery",
"arguments": {
"delivery_id": "DELIVERY_ID",
"success": true
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 delivery_not_found, delivery_already_settled · 429 slow down
notifications.update_rule
Edit a notification rule — Changes a rule’s events, recipients, wording or quiet period.
Needs notifications:manage · changes data
https://app.getera.io/api/v1/notification_rules/{id}/actions/update_rule- Canonical address:
POST /api/v1/actions/notifications.update_rule
Input
| Field | Type | Required | Notes |
|---|---|---|---|
rule_id | uuid | yes | Filled from the path {id} · Rule · id of notification_rule |
name | string | Name · max 120 | |
channel_id | uuid | Channel · id of notification_channel | |
events | string | Events · max 2000 | |
cooldown_minutes | number | Quiet period (minutes) | |
recipient | string (enum) | Who is told · A channel, or people found in the event (owner, assignee, mentioned…) or chosen here. · Allowed values: channel, owner, assignee, mentioned, recipient, member, role, capability, customer | |
recipient_user_id | uuid | Member · For “a specific member”. | |
recipient_role | string | Role · For “everyone with a role”: the role key. · max 80 | |
recipient_capability | string | Permission · For “everyone holding a permission”: module:capability. · max 80 | |
mediums | string | Reach them by · Comma-separated: in_app, email, sms, whatsapp. · max 200 | |
category | string | Category · What a person switches on or off. Empty means the event’s module. · max 41 | |
title_template | string | Title · Variables: {{event_label}}, {{recipient.name}}, {{workspace.name}}, or any payload key like {{person}}. · max 300 | |
body_template | string | Message · max 4000 | |
link_template | string | Link · A path in the app. Empty means the record the event is about. · max 500 |
Preconditions
The action is refused with 409 and one of these codes:
| Code | Refused when |
|---|---|
rule_not_found | No such rule in this workspace. |
channel_not_found | No such channel in this workspace. |
name_taken | This workspace already has a rule with that name. |
cooldown_out_of_range | The quiet period must be between 0 minutes and 7 days. |
recipient_incomplete | The rule must say fully who it tells. |
Events it publishes: notifications.rule_updated
What it writes: notification_rule (update) — Rewrites the rule’s events, recipients and wording
curl -X POST https://app.getera.io/api/v1/notification_rules/NOTIFICATION_RULE_ID/actions/update_rule \
-H "Authorization: Bearer $ERA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"name":"Name"}'{
"ok": true,
"result": "…",
"events": [
"notifications.rule_updated"
]
}import { createEra } from "@getera/sdk"
const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.notificationRules.updateRule("NOTIFICATION_RULE_ID", {
name: "Name"
})era notification_rules update_rule NOTIFICATION_RULE_ID \
--name "Name"{
"name": "era__notifications__update_rule",
"arguments": {
"rule_id": "NOTIFICATION_RULE_ID",
"name": "Name"
}
}Errors: 401 no or expired credential · 403 the credential does not hold notifications:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 rule_not_found, channel_not_found, name_taken, cooldown_out_of_range, recipient_incomplete · 429 slow down
Data models
NotificationChannel
Table notification_channel · Resource notification_channels
GET /api/v1/notification_channelsGET /api/v1/notification_channels/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
type | string · notification_channel_type | webhook, email, slack, push, in_app | ||
name | string · text | |||
config | object · jsonb | |||
active | boolean · bool | |||
verified_at | string (date-time) · timestamptz | yes | ||
created_by | string (uuid) · uuid | yes | app_user | |
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Unique: workspace_id, type, name
NotificationDelivery
Table notification_delivery · Resource notification_deliveries
GET /api/v1/notification_deliveriesGET /api/v1/notification_deliveries/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
rule_id | string (uuid) · uuid | yes | notification_rule | |
channel_id | string (uuid) · uuid | yes | notification_channel | |
event_name | string · text | |||
source_id | string · text | yes | ||
state | string · notification_delivery_state | pending, in_progress, delivered, failed, suppressed | ||
attempts | integer · int4 | |||
last_attempt_at | string (date-time) · timestamptz | yes | ||
next_attempt_at | string (date-time) · timestamptz | yes | ||
response_status | integer · int4 | yes | ||
error_message | string · text | yes | ||
suppressed_reason | string · text | yes | ||
duration_ms | integer · int4 | yes | ||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz | |||
payload | object · jsonb | |||
response_body | string · text | yes | ||
is_test | boolean · bool | |||
recipient_user_id | string (uuid) · uuid | yes | app_user | |
medium | string · text | channel, in_app, email, sms, whatsapp | ||
digest | boolean · bool |
Primary key: id
Checks:
CHECK (((attempts >= 0) AND (attempts <= 10)))CHECK (((medium <> 'channel'::text) OR (channel_id IS NOT NULL)))CHECK (((rule_id IS NOT NULL) OR is_test OR (payload ? 'to'::text) OR (payload ? 'customerId'::text)))CHECK (((response_status IS NULL) OR ((response_status >= 100) AND (response_status < 600))))CHECK (((state = 'suppressed'::os.notification_delivery_state) = (suppressed_reason IS NOT NULL)))
NotificationEmailTemplate
Table notification_email_template · Resource notification_email_templates
GET /api/v1/notification_email_templatesGET /api/v1/notification_email_templates/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
kind | string · text | order_confirmed, fulfilment_created, tracking_updated, invoice, gift_card, quote, appointment_reminder | ||
subject | string · text | |||
body | string · text | |||
updated_by_user_id | string (uuid) · uuid | yes | app_user | |
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Unique: workspace_id, kind
Checks:
CHECK (((length(body) >= 1) AND (length(body) <= 20000)))CHECK (((length(subject) >= 1) AND (length(subject) <= 300)))
NotificationInbox
Table notification_inbox · Resource notification_inboxes
GET /api/v1/notification_inboxesGET /api/v1/notification_inboxes/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
user_id | string (uuid) · uuid | app_user | ||
delivery_id | string (uuid) · uuid | yes | notification_delivery | |
rule_id | string (uuid) · uuid | yes | notification_rule | |
event_name | string · text | |||
category | string · text | |||
title | string · text | |||
body | string · text | yes | ||
link | string · text | yes | ||
read_at | string (date-time) · timestamptz | yes | ||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
NotificationPreference
Table notification_preference · Resource notification_preferences
GET /api/v1/notification_preferencesGET /api/v1/notification_preferences/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
user_id | string (uuid) · uuid | app_user | ||
channel_type | string · notification_channel_type | webhook, email, slack, push, in_app | ||
event_name | string · text | |||
enabled | boolean · bool | |||
muted_until | string (date-time) · timestamptz | yes | ||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Unique: workspace_id, user_id, channel_type, event_name
NotificationRule
Table notification_rule · Resource notification_rules
GET /api/v1/notification_rulesGET /api/v1/notification_rules/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
channel_id | string (uuid) · uuid | yes | notification_channel | |
name | string · text | |||
events | string[] · text[] | |||
condition | object · jsonb | yes | ||
include_output | boolean · bool | |||
include_trace | boolean · bool | |||
include_rate_limits | boolean · bool | |||
include_usage | boolean · bool | |||
cooldown_minutes | integer · int4 | |||
last_fired_at | string (date-time) · timestamptz | yes | ||
active | boolean · bool | |||
created_by | string (uuid) · uuid | yes | app_user | |
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz | |||
recipient | string · text | channel, owner, assignee, mentioned, recipient, member, role, capability, customer | ||
recipient_user_id | string (uuid) · uuid | yes | app_user | |
recipient_role | string · text | yes | ||
recipient_capability | string · text | yes | ||
mediums | string[] · text[] | |||
category | string · text | |||
title_template | string · text | yes | ||
body_template | string · text | yes | ||
link_template | string · text | yes |
Primary key: id
Unique: workspace_id, name
Checks:
CHECK (((category = ''::text) OR (category ~ '^[a-z][a-z0-9_]{1,40}$'::text)))CHECK (((recipient = 'channel'::text) = (channel_id IS NOT NULL)))CHECK (((cooldown_minutes >= 0) AND (cooldown_minutes <= 10080)))CHECK ((mediums <@ ARRAY['in_app'::text, 'email'::text, 'sms'::text, 'whatsapp'::text]))
NotificationUserSetting
Table notification_user_setting · Resource notification_user_settings
GET /api/v1/notification_user_settingsGET /api/v1/notification_user_settings/{id}
| Column | Type | Nullable | Allowed values | References |
|---|---|---|---|---|
id | string (uuid) · uuid | |||
organization_id | string (uuid) · uuid | organization | ||
workspace_id | string (uuid) · uuid | workspace | ||
user_id | string (uuid) · uuid | app_user | ||
timezone | string · text | yes | ||
locale | string · text | yes | ||
quiet_start | string (time) · time | yes | ||
quiet_end | string (time) · time | yes | ||
digest | string · text | |||
digest_hour | integer · int4 | |||
created_at | string (date-time) · timestamptz | |||
updated_at | string (date-time) · timestamptz |
Primary key: id
Unique: workspace_id, user_id
Checks:
CHECK (((digest = ANY (ARRAY['off'::text, 'hourly'::text, 'daily'::text])) AND ((digest_hour >= 0) AND (digest_hour <= 23))))CHECK (((quiet_start IS NULL) = (quiet_end IS NULL)))
Events
Workflows and webhooks react to these events.
| Event | What happens | Payload |
|---|---|---|
notifications.channel_created | A delivery channel was added. | channel_id, type |
notifications.channel_deleted | A delivery channel was removed. | channel_id |
notifications.delivered | A notification reached its channel. | delivery_id, response_status |
notifications.delivery_failed | A notification could not be delivered. | delivery_id, error |
notifications.delivery_retried | A failed notification was put back on the queue by hand. | delivery_id |
notifications.email_template_changed | A customer email was reworded or restored to its default. | kind, customised |
notifications.history_purged | Finished deliveries were swept. | days, removed |
notifications.inbox_read | Someone marked notifications in their inbox as read. | user_id, count |
notifications.preference_changed | Someone changed what they want to be told about. | user_id, channel_type, enabled |
notifications.queued | A notification was queued for delivery. | delivery_id, rule_id |
notifications.rule_created | A notification rule was added. | rule_id, channel_id |
notifications.rule_deleted | A notification rule was removed. | rule_id |
notifications.rule_disabled | A notification rule was switched off. | rule_id |
notifications.rule_enabled | A notification rule was switched on. | rule_id |
notifications.rule_updated | A notification rule’s events, recipients or wording changed. | rule_id |
notifications.settings_changed | Someone changed their timezone, quiet hours or digest. | user_id |
notifications.suppressed | A notification was deliberately not sent. | delivery_id, reason |
notifications.test_queued | A test notification was queued for a channel. | delivery_id, channel_id |