# Dashboard MCP
Source: https://docs.sendrealm.com/agent-skills/dashboard
Use the Sendrealm MCP server to work with dashboard resources through an API key.
The Sendrealm MCP endpoint is available at:
```text theme={null}
https://mcp.sendrealm.com/mcp
```
Connect with a SendRealm API key through the `Authorization` header:
```text theme={null}
Authorization: Bearer your_sendrealm_api_key
```
The server is API-key scoped and does not persist credentials.
## MCP Features
| Area | Available capabilities |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Project | Inspect the project and capabilities assigned to the API key. |
| Domains | List domains and inspect verification state, DNS records, sending settings, and tracking settings without refreshing or mutating provider state. |
| Audiences | Create, list, retrieve, and update audiences and audience properties. |
| Contacts | Create, list, retrieve, and update contacts; look up or upsert by email; attach or remove audience membership; update topic subscriptions. |
| Topics | Create, list, retrieve, and update subscription topics. |
| Templates | List and retrieve dashboard-authored email or push templates and inspect version history. |
| Automations | Create and edit drafts, validate definitions, inspect runs, cancel or retry eligible runs, and test drafts with synthetic events and virtual time. |
| Events | Ingest customer events with contact resolution, idempotency, and optional correlation data. |
| Email campaigns | Create, list, retrieve, and update email campaign drafts and inspect readiness and delivery summaries. |
| Push apps | Create, list, retrieve, and rename push apps; inspect redacted FCM, APNs, and Web Push readiness and notification channels. |
| Push devices | Find registered devices and inspect permission, subscription, SDK, environment, activity, and provider-error diagnostics without exposing device tokens. |
| Push delivery | List push notification records and inspect provider and client event timelines. |
| Push campaigns | Create, list, retrieve, and update drafts and preview reachable devices by platform. |
| Push tests | Send one real test to one explicitly selected device, poll its delivery trace, and start, update, or end a single-device Live Activity test. |
## Not Exposed Through MCP
* Email or push campaign scheduling and production launch.
* Broad direct email or push sends.
* Push provider credential upload or replacement.
* Domain creation, transfer, deletion, or settings changes.
* Campaign deletion, asset uploads, and email campaign test sends.
* Template authoring, publishing, restoring, and archiving.
These operations require an explicit human handoff to the SendRealm dashboard or
trusted backend code using the public API.
For recovery workflows, agents should use contact lookup/upsert, put a stable
business identifier in event correlation, validate the automation, and run the
draft through the no-send test-run tools before publishing. Live run cancellation
and retry are explicit, audited operations; campaign scheduling and sending stay
in the dashboard.
Campaign scheduling and sending are intentionally unavailable through MCP. Agents should complete the draft, inspect readiness, and leave final scheduling and delivery approval to the SendRealm dashboard.
For push integration testing, agents can inspect provider readiness, find a
registered device, send one explicit test, and poll its provider/client event
trace. MCP does not expose broad direct push sends. Provider credential upload
and campaign launch stay in the dashboard.
# Sendrealm Email Skill
Source: https://docs.sendrealm.com/agent-skills/email
Help AI agents build Sendrealm email integrations.
Use `sendrealm-email` when an agent needs to add, review, or debug outbound email with Sendrealm. The skill is modeled after concise email-provider skills, but follows Sendrealm's SDK and API reference behavior.
## What It Covers
* Installing and using `@sendrealm/sdk` from trusted backend code.
* Storing `SENDREALM_API_KEY` server-side.
* Sending email with API-required `from`, `to`, `subject`, and `text`.
* Adding optional `html`, `cc`, `bcc`, `reply_to`, `attachments`, `headers`, and `tags`.
* Selecting dashboard-authored Sendrealm email templates for broadcasts and automations.
* Handling typed SDK errors such as `APIError` and `RateLimitError`.
* Avoiding Resend-specific patterns that Sendrealm does not expose.
## Use It
```text theme={null}
Use $sendrealm-email to add a transactional welcome email with Sendrealm.
```
The skill should ask for missing sending-domain, sender, recipient, copy, and credential-storage details instead of inventing them.
## Guardrails
* Never put `SENDREALM_API_KEY` in browser or mobile code.
* Do not copy Resend's Node pattern of returning `{ data, error }`; Sendrealm throws typed SDK errors.
* Do not claim direct email sends support email idempotency keys unless the installed SDK or API reference exposes that feature.
* Do not invent direct-send `template_id` behavior. Direct sends use body content; templates are reusable assets for Sendrealm workflows.
## Source Docs
* [JavaScript SDK](/sdks/javascript)
* [Send Email API](/api-reference/endpoint/create)
* [Templates](/tutorials/templates)
* [List Templates API](/api-reference/endpoint/list-templates)
* [API Keys](/tutorials/api-keys)
* [Domains](/tutorials/domains)
# Agent Skills
Source: https://docs.sendrealm.com/agent-skills/overview
Use Sendrealm skills with AI coding agents.
Sendrealm agent skills give coding agents focused instructions for building Sendrealm email and push integrations. They are guidance-first: agents use them to write and review integration code, not to send production messages or manage your Sendrealm account directly.
## Install
Install the Sendrealm skills package in agents that support the Agent Skills format:
```bash theme={null}
npx skills add sendrealm/skills
```
Source: [sendrealm/skills](https://github.com/sendrealm/skills)
The package includes:
* `sendrealm-email` for outbound email sends and email templates.
* `sendrealm-push` for backend push sends, device SDK setup, and delivery troubleshooting.
* `sendrealm-dashboard` for API-key-scoped dashboard workflows through the Sendrealm MCP server.
## What The Skills Do
Add transactional email sends, templates, tags, headers, attachments, and safe error handling with `@sendrealm/sdk`.
Add push registration and backend notification sends across Web, React Native, Android, and iOS.
Manage audiences, contacts, templates, automations, campaign drafts, and safe push integration tests through MCP.
## Safety Model
* API keys stay in trusted backend code through `SENDREALM_API_KEY`.
* Browser and mobile apps use public Sendrealm Push App IDs, never Sendrealm API keys.
* The skills point agents back to Sendrealm docs and API reference pages before generating integration code.
* MCP supports dashboard resource workflows with API keys, but campaign scheduling and sends remain dashboard-only.
## Related Pages
* [JavaScript SDK](/sdks/javascript)
* [SDK Overview](/sdks/overview)
* [Send Email API](/api-reference/endpoint/create)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
# Sendrealm Push Skill
Source: https://docs.sendrealm.com/agent-skills/push
Help AI agents build Sendrealm push integrations.
Use `sendrealm-push` when an agent needs to add, review, or debug Sendrealm push notifications. The skill covers both sides of push: device registration in apps and backend sends from trusted code.
## What It Covers
* Choosing the right SDK for Web, React Native Expo, React Native bare, Android, or iOS.
* Configuring Firebase, APNs, or Web Push provider settings in Sendrealm.
* Initializing device SDKs with public Sendrealm Push App IDs.
* Requesting permission from a user action and linking users with `login`.
* Sending notifications from trusted backend code with `@sendrealm/sdk`.
* Using exactly one target style per send: `tokens`, `web_subscriptions`, `device_ids`, `contact_ids`, `external_ids`, `emails`, or `audiences`.
* Debugging registration, environment, credentials, diagnostics, and delivery issues.
* Testing through MCP or the API by discovering a real device, sending one explicit test, and polling provider/client events.
## Use It
```text theme={null}
Use $sendrealm-push to add Sendrealm Web Push to my Vite app and send from my backend.
```
The skill should ask for the Sendrealm Push App ID, app environment, provider setup status, target identity, and final notification copy before generating production code.
## Guardrails
* Never expose `SENDREALM_API_KEY`, Firebase service account JSON, or APNs `.p8` keys in browser or mobile code.
* Distinguish Sendrealm `development` or `production` devices from iOS APNs `sandbox` or `production`.
* Treat audience sends as queued and direct device/contact/user sends as immediate.
* Do not promise device display. Provider accepted or sent counts are not proof that a notification appeared on the device.
* Use diagnostics before changing backend targeting logic.
* Use the MCP `push_test_send` tool only with one device selected from `push_devices_list`; broad push sends and campaign launch are intentionally unavailable through MCP.
## Source Docs
* [SDK Overview](/sdks/overview)
* [JavaScript SDK](/sdks/javascript)
* [React Web Push SDK](/sdks/react)
* [React Native Expo SDK](/sdks/react-native-expo)
* [React Native Bare SDK](/sdks/react-native-bare)
* [Android SDK](/sdks/android)
* [iOS SDK](/sdks/ios)
* [Mobile Push Credentials](/tutorials/mobile-push-credentials)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
* [Push Apps And Providers](/api-reference/endpoint/push-apps)
* [Push Devices](/api-reference/endpoint/push-devices)
* [Push Tests](/api-reference/endpoint/push-tests)
* [Push Delivery Diagnostics](/api-reference/endpoint/push-delivery-diagnostics)
# Advance Automation Test Run
Source: https://docs.sendrealm.com/api-reference/endpoint/advance-automation-test-run
api-reference/openapi.json POST /automation-test-runs/{runId}/advance
# Attach Contact to Audience
Source: https://docs.sendrealm.com/api-reference/endpoint/attach-contact-to-audience
api-reference/openapi.json POST /contacts/{contact_id}/audiences/{audience_id}
# Automation Reliability
Source: https://docs.sendrealm.com/api-reference/endpoint/automation-reliability
api-reference/openapi.json POST /automations/validate
Validate definitions, control failed runs, and test waits without delivery.
## Validate before publish
`POST /automations/validate` accepts `{ "definition": { ... } }` and returns
`valid`, human-readable `errors`, and structured validation `issues`.
`wait_for_event` supports a canonical `timeout_seconds` value. Legacy
`timeout: { amount, unit }` definitions are normalized for compatibility, but
new definitions should always use seconds.
## Correlated waits
Define a trigger correlation key and use the same key on a wait:
```json theme={null}
{
"trigger": {
"event_name": "checkout.started",
"correlation": {
"key": "checkout_id",
"duplicate_policy": "ignore_active"
}
},
"steps": [
{
"key": "wait_for_checkout",
"type": "wait_for_event",
"config": {
"event_name": "checkout.completed",
"timeout_seconds": 3600,
"correlation": { "key": "checkout_id" }
}
}
]
}
```
Use `end_automation` as a terminal step for an explicit successful branch.
## Run controls
* `POST /automation-runs/:runId/cancel`
* `POST /automation-runs/:runId/retry`
Both accept an optional `{ "reason": "..." }`, are project-scoped and audited,
and require a Sendrealm API key. Cancellation cannot retract a delivery that
has already started.
## Test runs
Test a saved draft without delivery or production mutations:
* `POST /automations/:id/test-runs`
* `GET /automation-test-runs/:runId`
* `POST /automation-test-runs/:runId/events`
* `POST /automation-test-runs/:runId/advance`
Test runs record simulated actions, use isolated synthetic events, and advance
delays or wait timeouts with a virtual clock.
# Retrieve And Update Campaign
Source: https://docs.sendrealm.com/api-reference/endpoint/campaign
api-reference/openapi.json GET /campaigns/{id}
Read campaign readiness and update an email campaign draft.
## Endpoints
* `GET /campaigns/:id`
* `PATCH /campaigns/:id`
Only drafts can be updated. Assigning `from.address` requires a verified domain in the current project; assigning audiences and a template version also requires them to belong to that project.
## Update request
```json theme={null}
{
"subject": "A closer look at July",
"from": {
"name": "Sendrealm",
"address": "hello@example.com"
},
"audience_ids": ["018f4a28-29f0-7a2e-86c3-6a8f1b6dd294"],
"tracking": {
"open_tracking": true,
"click_tracking": true
},
"content": {
"type": "doc",
"content": []
}
}
```
The response includes readiness reasons, selected-audience subscriber counts, and delivery analytics. A draft can be reviewed and scheduled from the SendRealm dashboard after it is ready.
# Create And List Campaigns
Source: https://docs.sendrealm.com/api-reference/endpoint/campaigns
api-reference/openapi.json POST /campaigns
Create email campaign drafts and list existing campaigns.
## Endpoints
* `POST /campaigns`
* `GET /campaigns`
Campaigns created through the public API always begin as drafts. The API does not schedule, approve, or send them.
## Create request
```json theme={null}
{
"name": "July product update"
}
```
# Cancel Automation Run
Source: https://docs.sendrealm.com/api-reference/endpoint/cancel-automation-run
api-reference/openapi.json POST /automation-runs/{runId}/cancel
# Look Up Or Upsert Contacts
Source: https://docs.sendrealm.com/api-reference/endpoint/contact-lookup-upsert
api-reference/openapi.json POST /contacts/lookup
Resolve contacts by email without exposing email addresses in URLs.
## Look up by email
`POST /contacts/lookup`
```json theme={null}
{ "email": "olivia@example.com" }
```
The response is `200 OK` with `data: null` when no active contact exists.
## Upsert by email
`POST /contacts/upsert`
```json theme={null}
{
"email": "olivia@example.com",
"fields": {
"first_name": "Olivia",
"plan": "pro"
}
}
```
Upsert merges provided fields, validates declared audience properties, and returns
the contact with `created: true` or `created: false`. Email is normalized per
project and concurrent requests resolve to one active contact.
# Update Contact Topic Subscription
Source: https://docs.sendrealm.com/api-reference/endpoint/contact-topic-subscription
api-reference/openapi.json PUT /contacts/{contact_id}/topics/{topic_id}
Subscribe or unsubscribe a contact from a topic.
## Endpoint
`PUT /contacts/:contact_id/topics/:topic_id`
## Request body
```json theme={null}
{
"is_subscribed": true
}
```
## Response
```json theme={null}
{
"data": {
"id": "0df0fc92-89f2-4f23-a9e6-e9da2f3c1685",
"contact_id": "c671f89b-3ec1-4c58-9ad2-4ef8c2917cda",
"topic_id": "8c3c4d0e-f7f3-4d7f-92ae-b1498f6a2fa9",
"is_subscribed": true,
"subscribed_at": "2026-06-08T15:12:00.000Z",
"unsubscribed_at": null
}
}
```
Successful updates also emit `sendrealm.topic.subscribed` or `sendrealm.topic.unsubscribed`.
# Send Email
Source: https://docs.sendrealm.com/api-reference/endpoint/create
api-reference/openapi.json POST /emails
Send emails
# Create Audience
Source: https://docs.sendrealm.com/api-reference/endpoint/create-audience
api-reference/openapi.json POST /audiences
Create an audience in the API key's project.
# Create Audience Property
Source: https://docs.sendrealm.com/api-reference/endpoint/create-audience-property
api-reference/openapi.json POST /audiences-properties
Audience properties define server-owned contact data that can be used for
audience targeting and personalization.
Properties are authoritative by default. Set `sdk_writable: true` only when the
mobile SDK is allowed to manage that value as a client-sourced tag. Keep account,
billing, lifecycle, compliance, and verified profile data server-owned.
# Create Automation
Source: https://docs.sendrealm.com/api-reference/endpoint/create-automation
api-reference/openapi.json POST /automations
Create an automation draft.
## Create request
```json theme={null}
{
"name": "Post Purchase Journey",
"description": "Follow up after a completed order.",
"definition": {
"trigger": {
"event_name": "order.completed"
},
"steps": [
{
"key": "send_receipt",
"type": "send_email_template",
"config": {
"template_version_id": "tpl_ver_email_123",
"domain_id": "dom_123"
}
}
],
"connections": [
{
"from": "trigger",
"to": "send_receipt",
"branch": "next"
}
]
},
"editor_layout": {
"viewport": {
"x": 0,
"y": 0,
"zoom": 1
},
"nodes": [
{
"id": "trigger",
"position": {
"x": 120,
"y": 180
}
}
]
}
}
```
# Create Contact
Source: https://docs.sendrealm.com/api-reference/endpoint/create-contact
api-reference/openapi.json POST /contacts
# Create Push App
Source: https://docs.sendrealm.com/api-reference/endpoint/create-push-app
api-reference/openapi.json POST /push/apps
Create a push app and default Android, iOS, and Web providers. Provider credentials remain dashboard-only.
# Create Topic
Source: https://docs.sendrealm.com/api-reference/endpoint/create-topic
api-reference/openapi.json POST /topics
Create a reusable topic definition.
## Create request
```json theme={null}
{
"name": "weekly-digest",
"description": "Long-form weekly product and marketing updates."
}
```
# Delete Audience
Source: https://docs.sendrealm.com/api-reference/endpoint/delete-audience
api-reference/openapi.json DELETE /audiences/{id}
# Delete Automation
Source: https://docs.sendrealm.com/api-reference/endpoint/delete-automation
api-reference/openapi.json DELETE /automations/{id}
Archive an automation.
Deletion archives the automation instead of removing its historical runs.
# Delete Contact
Source: https://docs.sendrealm.com/api-reference/endpoint/delete-contact
api-reference/openapi.json DELETE /contacts/{id}
# Delete Topic
Source: https://docs.sendrealm.com/api-reference/endpoint/delete-topic
api-reference/openapi.json DELETE /topics/{id}
Delete a topic.
Topic deletion is a soft delete so historical subscription and automation activity stays auditable.
# Get Domain
Source: https://docs.sendrealm.com/api-reference/endpoint/domain
api-reference/openapi.json GET /domains/{id}
Read a sending domain's DNS records and tracking settings without changing it.
Use this endpoint to inspect the DNS records that must be configured and to confirm tracking settings before assigning the domain to an email campaign.
Domain creation, transfer, deletion, and settings changes remain dashboard-only operations.
# List Domains
Source: https://docs.sendrealm.com/api-reference/endpoint/domains
api-reference/openapi.json GET /domains
List the sending domains available to an API-key project.
`GET /domains` returns stored domain verification state, region, and timestamps. It does not request a fresh verification result from the sending provider and does not mutate domain state.
Use the `after` cursor from the response metadata to request the next page.
# Event Ingest
Source: https://docs.sendrealm.com/api-reference/endpoint/events
api-reference/openapi.json POST /events
Submit customer events and understand reserved system event rules.
## Endpoint
`POST /events`
## Request body
```json theme={null}
{
"event": "order.completed",
"contact_id": "c671f89b-3ec1-4c58-9ad2-4ef8c2917cda",
"payload": {
"order_id": "ord_123",
"total": 4900
},
"correlation": {
"key": "order_id",
"value": "ord_123"
},
"occurred_at": "2026-06-08T14:15:00.000Z",
"idempotency_key": "evt_order_completed_ord_123"
}
```
You can also identify a contact with `external_id` or `email`.
Use `correlation` when an identity can have more than one active business flow.
For checkout recovery, send the same `checkout_id` with both `checkout.started`
and `checkout.completed`; a correlated wait resumes only its matching checkout.
To create or merge an email contact while ingesting an event, opt in explicitly:
```json theme={null}
{
"event": "checkout.started",
"email": "olivia@example.com",
"contact": {
"mode": "upsert",
"fields": {
"first_name": "Olivia"
}
}
}
```
Without `contact.mode: "upsert"`, event ingestion resolves existing contacts only.
Identity resolution order is:
1. `contact_id`
2. `external_id`
3. normalized `email`
## Successful response
```json theme={null}
{
"data": {
"id": "4d978da0-4504-42e3-9d71-e9b9a2f9082d",
"event": "order.completed",
"resolved_identity_type": "contact_id",
"resolved_identity_value": "c671f89b-3ec1-4c58-9ad2-4ef8c2917cda",
"occurred_at": "2026-06-08T14:15:00.000Z"
}
}
```
New customer events currently return `202 Accepted`.
## Idempotent replay response
If you reuse the same `idempotency_key`, Sendrealm returns the existing event instead of creating a new one:
```json theme={null}
{
"data": {
"id": "4d978da0-4504-42e3-9d71-e9b9a2f9082d",
"event": "order.completed",
"deduplicated": true,
"occurred_at": "2026-06-08T14:15:00.000Z"
}
}
```
## Reserved namespace
Customer-submitted events must not start with `sendrealm.`.
Examples of Sendrealm system events:
* `sendrealm.mail.delivery`
* `sendrealm.push.open`
* `sendrealm.contact.updated`
* `sendrealm.topic.subscribed`
## Guarantees and limits
* Event ingest is at-least-once.
* Idempotency is enforced by `project_id + idempotency_key`.
* Payload size is capped by the project's configured event payload limit.
* Processing retries use exponential backoff before a dead-letter handoff.
* Ordering across separate events is not guaranteed.
## Retention
* Default event retention is 90 days.
* Retention windows can be adjusted through backoffice-managed project automation settings.
# Inject Automation Test Event
Source: https://docs.sendrealm.com/api-reference/endpoint/inject-automation-test-event
api-reference/openapi.json POST /automation-test-runs/{runId}/events
# List Audience Properties
Source: https://docs.sendrealm.com/api-reference/endpoint/list-audience-properties
api-reference/openapi.json GET /audiences-properties
# List Audiences
Source: https://docs.sendrealm.com/api-reference/endpoint/list-audiences
api-reference/openapi.json GET /audiences
List audiences in the API key's project.
# List Automation Runs
Source: https://docs.sendrealm.com/api-reference/endpoint/list-automation-runs
api-reference/openapi.json GET /automations/{id}/runs
List runs for an automation.
## Run list includes
* Trigger event
* Resolved identity
* Per-step timeline
* Wait states
* Timeout path
* Linked sent email and push records
* Last error
# List Automations
Source: https://docs.sendrealm.com/api-reference/endpoint/list-automations
api-reference/openapi.json GET /automations
List existing automations.
Use filters like `status` and `search`.
`GET /automations?status=active&search=post`
# List Campaigns
Source: https://docs.sendrealm.com/api-reference/endpoint/list-campaigns
api-reference/openapi.json GET /campaigns
List email campaigns in the API key project.
# List Contacts
Source: https://docs.sendrealm.com/api-reference/endpoint/list-contacts
api-reference/openapi.json GET /contacts
# List Push App Providers
Source: https://docs.sendrealm.com/api-reference/endpoint/list-push-app-providers
api-reference/openapi.json GET /push/apps/{id}/providers
Return FCM, APNs, and Web Push readiness and public identifiers without secret credentials.
# List Push Campaigns
Source: https://docs.sendrealm.com/api-reference/endpoint/list-push-campaigns
api-reference/openapi.json GET /push/campaigns
List project push campaigns. Test-only delivery records are excluded.
# List Push Notification Channels
Source: https://docs.sendrealm.com/api-reference/endpoint/list-push-notification-channels
api-reference/openapi.json GET /push/apps/{id}/notification-channels
List notification channels synchronized for a push app.
# List Push Notifications
Source: https://docs.sendrealm.com/api-reference/endpoint/list-push-notifications
api-reference/openapi.json GET /push/notifications
List direct, campaign, automation, and test notification records with redacted provider state.
# List Template Versions
Source: https://docs.sendrealm.com/api-reference/endpoint/list-template-versions
api-reference/openapi.json GET /templates/{id}/versions
List template version history.
# List Templates
Source: https://docs.sendrealm.com/api-reference/endpoint/list-templates
api-reference/openapi.json GET /templates
List template drafts and published templates.
Use query params like `channel`, `status`, and `search`.
`GET /templates?channel=email&status=active&search=cart`
# List Topics
Source: https://docs.sendrealm.com/api-reference/endpoint/list-topics
api-reference/openapi.json GET /topics
List reusable topic definitions.
`GET /topics?search=digest`
# Pause Automation
Source: https://docs.sendrealm.com/api-reference/endpoint/pause-automation
api-reference/openapi.json POST /automations/{id}/pause
Pause an active automation.
# Preview Push Campaign Audience
Source: https://docs.sendrealm.com/api-reference/endpoint/preview-push-campaign-audience
api-reference/openapi.json GET /push/campaigns/{id}/audience-preview
Count reachable subscribed devices by platform without sending.
# Get API Key Project
Source: https://docs.sendrealm.com/api-reference/endpoint/project
api-reference/openapi.json GET /project
Identify the project and safe dashboard capabilities associated with an API key.
Use this endpoint before creating dashboard resources when an integration needs to confirm its API-key scope.
The response includes the current project, team ID, and MCP-safe capability flags. API keys are scoped to one project, so no project ID is supplied in the request.
# Publish Automation
Source: https://docs.sendrealm.com/api-reference/endpoint/publish-automation
api-reference/openapi.json POST /automations/{id}/publish
Publish an automation draft.
## Publish validation
* Exactly one trigger
* Reachable graph
* No cycles in v1
* Published template versions only
* Valid branches for `condition` and `wait_for_event`
## Example publish response
```json theme={null}
{
"data": {
"id": "aut_123",
"status": "active",
"current_published_version": {
"id": "aut_ver_456",
"version_number": 2,
"state": "published"
}
}
}
```
# Push Apps And Providers
Source: https://docs.sendrealm.com/api-reference/endpoint/push-apps
api-reference/openapi.json GET /push/apps
Create push apps and inspect redacted provider readiness.
## Endpoints
* `GET /push/apps`
* `POST /push/apps`
* `GET /push/apps/:id`
* `PATCH /push/apps/:id`
* `GET /push/apps/:id/providers`
* `GET /push/apps/:id/notification-channels`
Create a push app to obtain the public app ID used by Web, React Native,
Android, and iOS SDKs. Provider responses include readiness, missing setup
fields, public package/bundle identifiers, and the Web Push public key. Secret
FCM service accounts, APNs keys, VAPID private keys, and raw device tokens are
never returned.
Provider credential setup remains in the SendRealm dashboard.
# Push Campaign Drafts
Source: https://docs.sendrealm.com/api-reference/endpoint/push-campaigns
api-reference/openapi.json POST /push/campaigns
Create, edit, preview, and single-device test push campaign drafts.
## Endpoints
* `POST /push/campaigns`
* `GET /push/campaigns`
* `GET /push/campaigns/:id`
* `PATCH /push/campaigns/:id`
* `GET /push/campaigns/:id/audience-preview`
Public API campaigns are draft-only. Update localized messages, platforms,
audience inclusion/exclusion, a published push template version, Android
configuration, buttons, and optional Live Activity content.
Audience preview counts reachable subscribed devices with a provider
registration. To prove content on a device, pass the campaign ID to the push
test endpoint. Scheduling, launch, deletion, and broad campaign test sends are
not exposed in this API version.
# Push Delivery Diagnostics
Source: https://docs.sendrealm.com/api-reference/endpoint/push-delivery-diagnostics
api-reference/openapi.json GET /push/notifications/{id}
List push sends and inspect provider and client event timelines.
## Endpoints
* `GET /push/notifications`
* `GET /push/notifications/:id`
Delivery records cover direct sends, automations, campaigns, and one-device
tests. Filter by push app, platform, environment, or status. A detail response
includes the provider message ID and chronological provider/client events,
including the reporting device and provider name.
Use this trace together with push device diagnostics. A provider send event can
still be followed by a stale-token failure, OS suppression, foreground-handler
behavior, or missing client instrumentation.
# Push Devices
Source: https://docs.sendrealm.com/api-reference/endpoint/push-devices
api-reference/openapi.json GET /push/devices
Find registered devices and inspect app-side integration state.
## Endpoints
* `GET /push/devices`
* `GET /push/devices/:id`
Filter devices by `app_id`, platform, environment, subscription state, or a
device/external ID search. Responses include permission state, SDK/app/OS
versions, registration presence, recent activity, contact linkage, and the
latest provider error without exposing APNs, FCM, or Web Push credentials.
Device initialization, provider registration, permission changes, login, tags,
and client events continue to use the app-facing Push API through the device
SDKs. These API-key routes are diagnostic and read-only.
# Push Tests
Source: https://docs.sendrealm.com/api-reference/endpoint/push-tests
api-reference/openapi.json POST /push/test-notifications
Send one real push test to one selected device and inspect its trace.
## Endpoints
* `POST /push/test-notifications`
* `GET /push/test-notifications/:id`
An ad hoc test requires a public app ID, one device ID, a title, and a body:
```json theme={null}
{
"app_id": "push_app_public_id",
"device_id": "device_installation_id",
"title": "SendRealm test",
"body": "Push registration is working"
}
```
To test a saved draft, replace title/body with `campaign_id`. The API clones
the draft into a test-only delivery and still targets only the selected device.
Poll the returned test ID until a notification record appears. Inspect its
provider and client events before treating the integration as successful.
Provider acceptance alone does not prove that the OS displayed a notification.
# Remove Contact from Audience
Source: https://docs.sendrealm.com/api-reference/endpoint/remove-contact-from-audience
api-reference/openapi.json DELETE /contacts/{contact_id}/audiences/{audience_id}
# Resume Automation
Source: https://docs.sendrealm.com/api-reference/endpoint/resume-automation
api-reference/openapi.json POST /automations/{id}/resume
Resume a paused automation.
# Retrieve Audience
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-audience
api-reference/openapi.json GET /audiences/{id}
# Retrieve Audience Property
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-audience-property
api-reference/openapi.json GET /audiences-properties/{id}
# Retrieve Automation
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-automation
api-reference/openapi.json GET /automations/{id}
Retrieve a single automation.
# Retrieve Automation Run
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-automation-run
api-reference/openapi.json GET /automation-runs/{runId}
Inspect a single automation run.
## Operational notes
* Run execution uses at-least-once semantics.
* Step retries are protected with step-level idempotency, so a previously completed step is not re-sent on resume.
* `wait_for_event` timeout handling is scheduler based and near-real-time, not a hard real-time guarantee.
* If a wait times out first, a later matching event does not reopen that completed branch.
# Retrieve Automation Test Run
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-automation-test-run
api-reference/openapi.json GET /automation-test-runs/{runId}
# Retrieve Contact
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-contact
api-reference/openapi.json GET /contacts/{id}
# Retrieve Push App
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-push-app
api-reference/openapi.json GET /push/apps/{id}
# Retrieve Push Campaign
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-push-campaign
api-reference/openapi.json GET /push/campaigns/{id}
# Retrieve Push Device
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-push-device
api-reference/openapi.json GET /push/devices/{id}
Return one device and recent registration, permission, and client events without raw provider tokens.
# Retrieve Push Test
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-push-test
api-reference/openapi.json GET /push/test-notifications/{id}
Poll a queued test and inspect provider and client events.
# Retrieve Template
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-template
api-reference/openapi.json GET /templates/{id}
Retrieve a single template.
# Retrieve Topic
Source: https://docs.sendrealm.com/api-reference/endpoint/retrieve-topic
api-reference/openapi.json GET /topics/{id}
Retrieve a single topic.
# Retry Automation Run
Source: https://docs.sendrealm.com/api-reference/endpoint/retry-automation-run
api-reference/openapi.json POST /automation-runs/{runId}/retry
# Send Push Live Activity Notification
Source: https://docs.sendrealm.com/api-reference/endpoint/send-push-live-activity-notification
api-reference/openapi.json POST /push/live-activities/{activity_id}/notifications
Send an update or end event to an existing Live Activity session.
Send an update or end event to an existing Live Activity session.
```json theme={null}
{
"app_id": "push_app_short_id",
"event": "update",
"title": "Delivery",
"status": "Driver nearby",
"progress": 0.75,
"eta": "2026-06-21T21:05:00.000Z",
"buttons": [
{
"id": "open",
"text": "Open",
"launch_url": "myapp://orders/123"
}
]
}
```
Use `"event": "end"` to close the Live Activity. End events may include a final
`status`, `body`, and `dismiss_at` timestamp.
# Send Push Notification
Source: https://docs.sendrealm.com/api-reference/endpoint/send-push-notification
api-reference/openapi.json POST /push/notifications
Send a push notification to a direct device target or to contact aliases.
Send a push notification to Sendrealm push devices, contacts, external IDs,
email addresses, raw push tokens, or audiences.
## Targeting
Use one Sendrealm targeting style per request:
* `tokens`: raw Android FCM or iOS APNs push tokens with their platform.
* `web_subscriptions`: raw browser `PushSubscription.toJSON()` objects for direct Web Push sends.
* `device_ids`: Sendrealm push device IDs created by the SDK.
* `contact_ids`: Sendrealm contact IDs.
* `external_ids`: stable IDs set with SDK login or the server API.
* `emails`: contact email addresses.
* `audiences`: audience IDs for queued or scheduled audience sends.
Use `excluded_audiences` with contact, external ID, email, or audience sends to
remove contacts that belong to specific audiences. Use `platforms` to limit
delivery to `android`, `ios`, or `web`. Web devices registered by the React SDK
can be targeted through device, contact, external ID, email, audience, or
`platforms: ["web"]` filters.
Set `environment` to `development` to target devices registered by development
SDK builds. Omit it, or set `production`, for production devices. This is
separate from iOS `apns_environment`.
Audience sends are queued through the push broadcast delivery pipeline. Direct
device, token, contact, external ID, and email sends are delivered immediately.
## Body
```json theme={null}
{
"app_id": "push_app_short_id",
"environment": "development",
"audiences": ["018f5b8d-2e2d-7a9b-9000-1c24e8a3b2c1"],
"excluded_audiences": ["018f5b91-8f46-7f1d-a111-df39fd4b98a0"],
"platforms": ["ios", "android"],
"scheduled_at": "2026-06-21T20:30:00.000Z",
"notification": {
"title": "Order update",
"body": "Your order is ready.",
"launch_url": "myapp://orders/123",
"image_url": "https://example.com/order.png"
},
"buttons": [
{
"id": "view_order",
"text": "View order",
"launch_url": "myapp://orders/123"
}
],
"data": {
"order_id": "123"
},
"ios": {
"sound": "default",
"badge": 1,
"apns_environment": "sandbox"
},
"android": {
"channel_id": "orders",
"sound": "default",
"ttl": "3600"
}
}
```
For direct browser sends, pass browser subscriptions separately from mobile
tokens:
```json theme={null}
{
"app_id": "push_app_short_id",
"web_subscriptions": [
{
"endpoint": "https://fcm.googleapis.com/fcm/send/...",
"expirationTime": null,
"keys": {
"p256dh": "base64url-key",
"auth": "base64url-secret"
}
}
],
"notification": {
"title": "New message",
"body": "Open the inbox."
}
}
```
Use `buttons` to attach up to three notification actions. Android renders the
button text directly. iOS sends Sendrealm's default action category and includes
the button payload for SDK action tracking and deep-link handling.
For localized messages, send `messages` with locale codes:
```json theme={null}
{
"app_id": "push_app_short_id",
"contact_ids": ["018f5b8d-2e2d-7a9b-9000-1c24e8a3b2c1"],
"messages": [
{
"code": "en-US",
"label": "English",
"title": "Welcome back",
"body": "You have a new update."
},
{
"code": "pt-BR",
"label": "Portuguese",
"title": "Bem-vindo de volta",
"body": "Voce tem uma nova atualizacao."
}
],
"notification": {
"title": "Welcome back",
"body": "You have a new update."
}
}
```
## Tags And Contact Properties
SDK tags are client-sourced key/value data used for app behavior, preferences,
audience targeting, and personalization. They are useful for values the app can
observe directly, such as onboarding status, selected interests, locale, or app
version.
Server contact properties are authoritative backend data. Use the Contacts API
for account, billing, compliance, lifecycle, verified profile, and CRM values.
SDK tag writes cannot overwrite server-owned or system-owned contact
properties.
Protected SDK tag keys include identity and Sendrealm/system fields. Keys that
start with `sendrealm_`, `sys_`, `billing_`, `security_`, or `account_` are
reserved. Audience properties are server-owned by default; set
`sdk_writable: true` on an audience property only when the mobile app is allowed
to manage that value.
## Reporting
Each send records push notification rows and events for provider accepted sends,
failures, opens, clicks, and SDK-tracked custom events. Provider accepted means
the push provider accepted the request; it is not the same as confirmed display
on the physical device.
# Start Automation Test Run
Source: https://docs.sendrealm.com/api-reference/endpoint/start-automation-test-run
api-reference/openapi.json POST /automations/{id}/test-runs
# Start Push Live Activity
Source: https://docs.sendrealm.com/api-reference/endpoint/start-push-live-activity
api-reference/openapi.json POST /push/live-activities
Start a Live Activity session for targeted push devices.
Start a Live Activity session for matching push devices. iOS delivery uses
ActivityKit push-to-start tokens registered by the SDK. Android delivery uses
ongoing notifications with the same live activity payload shape.
```json theme={null}
{
"app_id": "push_app_short_id",
"activity_id": "order-123",
"device_ids": ["push_device_id"],
"title": "Delivery",
"status": "Preparing order",
"progress": 0.25,
"launch_url": "myapp://orders/123",
"buttons": [
{
"id": "track",
"text": "Track",
"launch_url": "myapp://orders/123/track"
}
],
"data": {
"order_id": "123"
}
}
```
Targeting supports the same identifiers as push notification sends: `tokens`,
`device_ids`, `contact_ids`, `external_ids`, `emails`, and `audiences`.
# Update Audience
Source: https://docs.sendrealm.com/api-reference/endpoint/update-audience
api-reference/openapi.json PATCH /audiences/{id}
# Update Audience Property
Source: https://docs.sendrealm.com/api-reference/endpoint/update-audience-property
api-reference/openapi.json PATCH /audiences-properties/{id}
Update an audience property's key, type, or SDK write policy.
Use `sdk_writable: true` for app-observed values such as preferences or
onboarding state. Leave it false for authoritative server contact properties.
# Update Automation
Source: https://docs.sendrealm.com/api-reference/endpoint/update-automation
api-reference/openapi.json PATCH /automations/{id}
Update an automation draft.
## Update request
```json theme={null}
{
"name": "Post Purchase Journey",
"description": "Follow up after a completed order.",
"definition": {
"trigger": {
"event_name": "order.completed"
},
"steps": [
{
"key": "send_receipt",
"type": "send_email_template",
"config": {
"template_version_id": "tpl_ver_email_123",
"domain_id": "dom_123"
}
},
{
"key": "wait_for_open",
"type": "wait_for_event",
"config": {
"event_name": "sendrealm.mail.open",
"timeout_seconds": 86400
}
}
],
"connections": [
{
"from": "trigger",
"to": "send_receipt",
"branch": "next"
},
{
"from": "send_receipt",
"to": "wait_for_open",
"branch": "next"
}
]
},
"editor_layout": {
"viewport": {
"x": 0,
"y": 0,
"zoom": 1
},
"nodes": []
}
}
```
# Update Campaign
Source: https://docs.sendrealm.com/api-reference/endpoint/update-campaign
api-reference/openapi.json PATCH /campaigns/{id}
Update metadata, sender, audiences, a published template version, tracking, or editor content. Only draft campaigns are editable; a sender must use a verified project domain.
# Update Contact
Source: https://docs.sendrealm.com/api-reference/endpoint/update-contact
api-reference/openapi.json PATCH /contacts/{id}
# Update Push App
Source: https://docs.sendrealm.com/api-reference/endpoint/update-push-app
api-reference/openapi.json PATCH /push/apps/{id}
Rename a push app without changing provider credentials.
# Update Push Campaign
Source: https://docs.sendrealm.com/api-reference/endpoint/update-push-campaign
api-reference/openapi.json PATCH /push/campaigns/{id}
Update content, platforms, audiences, template selection, and platform configuration. Scheduling and launch are not accepted.
# Update Topic
Source: https://docs.sendrealm.com/api-reference/endpoint/update-topic
api-reference/openapi.json PATCH /topics/{id}
Update a topic.
## Update request
```json theme={null}
{
"name": "weekly-digest",
"description": "Weekly product updates and long-form educational content."
}
```
# Upsert Contact
Source: https://docs.sendrealm.com/api-reference/endpoint/upsert-contact
api-reference/openapi.json POST /contacts/upsert
# Introduction
Source: https://docs.sendrealm.com/api-reference/introduction
General introduction for the Sendrealm API
The Sendrealm API lets you send emails and push notifications, manage contacts, organize your contacts with audiences and topics, store versioned templates, run event-driven automations, and build campaign drafts.
## Base URL
```text theme={null}
https://api.sendrealm.com
```
## Authentication
All API endpoints are authenticated using API keys. Create an API key from the Sendrealm dashboard, then include it in the `Authorization` header for each request.
```bash theme={null}
Authorization: Bearer {apiKey}
```
Project API keys are permanently limited to their owning project. Team API keys can be limited to selected projects, and every key can be limited by permission. For a team key that can access multiple projects, requests use its default project unless you provide an authorized project explicitly:
```bash theme={null}
X-Sendrealm-Project-Id: {projectId}
```
An invalid API key returns `401`. A valid key without access to the selected project or action returns `403`.
## Resources
Send transactional or product emails through the API.
Send notifications to push devices, contacts, external IDs, or audiences.
Inspect apps and devices, send one-device tests, and trace delivery events.
Confirm the project and capabilities assigned to an API key.
Inspect sending domains, DNS records, verification state, and tracking settings.
Create and edit email campaign drafts for dashboard review.
Create, preview, and test push campaign drafts without launching them.
Create, list, update, and delete audiences.
Define custom fields for contact and audience data.
Create, list, update, and delete contacts.
Add contacts to audiences or remove them.
Ingest customer events and react to Sendrealm system events.
Create, publish, restore, and reuse email or push templates.
Create automation drafts, publish them, and inspect their runs.
Manage reusable topic subscriptions for audience preferences.
## Status codes
The Sendrealm API uses HTTP status codes to indicate the result of each request.
| Status Code | Description |
| ----------- | ------------------------------------------- |
| 200 | Successful request. |
| 201 | Resource created or notification sent. |
| 400 | Invalid request parameters. |
| 401 | API key was missing or invalid. |
| 403 | API key lacks project access or permission. |
| 404 | Resource was not found. |
| 409 | Resource conflict. |
| 422 | Request could not be processed. |
## Automation platform guarantees
* Event ingest and automation execution use at-least-once delivery semantics.
* Reuse `idempotency_key` on `POST /events` whenever your source system can retry.
* Wait timeouts are scheduler-based and should be treated as approximate, not millisecond exact.
* Event ordering is best effort and should not be treated as a strict serial log.
* Retention windows for events, runs, and waits are controlled at the project policy level.
* Plan limits and metered usage may apply to event ingest, automation runs, waits, template tests, and send actions.
# Introduction
Source: https://docs.sendrealm.com/introduction
Welcome to the Sendrealm documentation
Sendrealm gives you a single platform for transactional email, push notifications, reusable templates, customer events, and cross-channel automations.
Learn how you can use Sendrealm.
Learn how to implement Sendrealm API in your software.
Install Sendrealm in JavaScript, Android, iOS, and React Native apps.
Give AI coding agents Sendrealm email and push integration guidance.
Design event-driven journeys with the dashboard builder.
## What you can build
* Trigger automations from customer events like `order.completed` and `billing.payment_failed`.
* Reuse published email and push templates in broadcasts and automations.
* Track platform activity through reserved `sendrealm.*` system events.
* Manage topics and audience-driven preferences from the API or the dashboard.
## Start here
Create reusable email and push content with version history.
Build event-triggered journeys across email, push, audiences, and topics.
Send customer events and understand Sendrealm system event names.
Upload Firebase and APNs credentials for Android and iOS push.
Manage topic subscriptions for audience preferences and automation actions.
# Android SDK
Source: https://docs.sendrealm.com/sdks/android
Install and initialize the Sendrealm Android SDK.
Use the Sendrealm Android SDK to receive mobile push notifications in native Kotlin or Java Android apps.
If your app uses React Native, start with [React Native Bare SDK](/sdks/react-native-bare) or [React Native Expo SDK](/sdks/react-native-expo).
## Requirements
* Android API 27 or newer.
* Google Play services on the target device or emulator.
* A Sendrealm app ID from the dashboard.
* Firebase Cloud Messaging configured for the same Android package name.
* `google-services.json` added to your Android app.
* Firebase service account JSON uploaded in Sendrealm.
See [Mobile Push Credentials](/tutorials/mobile-push-credentials) for Firebase setup.
## Install
Add the SDK dependency to your app module:
```kotlin theme={null}
dependencies {
implementation("com.sendrealm:sendrealm-android:0.1.2")
}
```
Make sure the Google Services Gradle plugin is applied to your Android app if it is not already:
```kotlin theme={null}
plugins {
id("com.google.gms.google-services")
}
```
## Add `google-services.json`
Download `google-services.json` from Firebase and place it in your app module:
```text theme={null}
app/google-services.json
```
The Firebase Android package name must match your app `applicationId`.
## Initialize
Initialize once during app startup:
```kotlin theme={null}
import android.os.Bundle
import androidx.activity.ComponentActivity
import com.sendrealm.sdk.Sendrealm
import com.sendrealm.sdk.SendrealmConfig
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val config = SendrealmConfig()
.setEnvironment("development")
.setAutoRequestPermission(false)
Sendrealm.initialize(
context = this,
appId = "YOUR_SENDREALM_APP_ID",
config = config
)
}
}
```
Use `development` for test builds you want to target separately. Omit `setEnvironment` for production.
Most apps should keep `setAutoRequestPermission(false)` and ask for notification permission after an in-app explanation.
## Ask For Permission
Ask for permission from a user action:
```kotlin theme={null}
Sendrealm.requestPermission(this)
```
Check permission state:
```kotlin theme={null}
val allowed = Sendrealm.hasNotificationPermission(this)
```
Android 13 and newer show a runtime notification permission prompt. Android 12 and older do not have a runtime prompt, but users can still disable notifications in system settings.
## Handle Notification Opens
Forward new launch intents to Sendrealm so notification taps can be tracked and routed:
```kotlin theme={null}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
Sendrealm.handleNotificationOpen(intent)
}
```
Configure your Android intent filters for any app links or deep links you want notifications to open.
## Link A Signed-In User
Call `login` after the user signs in:
```kotlin theme={null}
Sendrealm.login("user-123", "user@example.com")
```
Call `logout` when the user signs out:
```kotlin theme={null}
Sendrealm.logout()
```
## Tags
Use tags for app-observed preferences, state, and behavior:
```kotlin theme={null}
Sendrealm.addTags(
mapOf(
"plan" to "pro",
"onboardingComplete" to true
)
)
```
Do not use SDK tags for authoritative account, billing, security, compliance, or verified profile data. Update those values from your backend.
## Custom Events
Track app events for segmentation, analytics, or automations:
```kotlin theme={null}
Sendrealm.trackEvent(
"checkout_started",
mapOf(
"product_id" to "sku_123",
"price" to 29
)
)
```
Use stable event names and avoid sending sensitive data unless your team intentionally wants that data stored in Sendrealm.
## Notification Channels
Android 8 and newer use notification channels for sound, vibration, importance, and visibility. Create separate channel IDs for materially different notification behavior, such as `orders`, `promotions`, or `account_alerts`.
Android may keep the original behavior for a channel after it is created. If you need to change sound or importance in a way users should notice, use a new channel ID.
## Diagnostics
Use diagnostics while testing:
```kotlin theme={null}
val diagnostics = Sendrealm.getDiagnostics(this)
Log.d("Sendrealm", diagnostics.toString())
```
Confirm diagnostics show:
* A device ID.
* Token presence.
* Expected permission status.
* Subscribed state unless the user opted out.
* No unexpected SDK error.
## Troubleshooting
| Symptom | What to check |
| --------------------------------- | ------------------------------------------------------------------------------------------------ |
| Token is missing | Use a Google Play device or emulator and verify Firebase setup. |
| Notifications do not display | Check notification permission, Android channel settings, and notification icon resources. |
| Notifications are delayed | Check Android power settings, FCM priority, device connectivity, and user notification settings. |
| Sound does not change | Android may be keeping the original channel behavior. Use a new channel ID. |
| Deep link does not open | Verify the notification URL and Android intent filters. |
| Tags fail with `ContactNotLinked` | Call `login(userId, email)` before setting user tags. |
## Related Pages
* [Mobile Push Credentials](/tutorials/mobile-push-credentials)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
* [React Native Bare SDK](/sdks/react-native-bare)
# iOS SDK
Source: https://docs.sendrealm.com/sdks/ios
Install and initialize the Sendrealm iOS SDK.
Use the Sendrealm iOS SDK to receive mobile push notifications in native Swift or Objective-C iOS apps.
If your app uses React Native, start with [React Native Bare SDK](/sdks/react-native-bare) or [React Native Expo SDK](/sdks/react-native-expo).
## Requirements
* iOS 13.4 or newer.
* A Sendrealm app ID from the dashboard.
* Push Notifications enabled for the Apple App ID.
* Push Notifications enabled on the Xcode target.
* APNs credentials uploaded in Sendrealm.
* A physical iOS device for end-to-end push testing.
Use `sandbox` for development builds installed from Xcode. Use `production` for TestFlight and App Store builds.
See [Mobile Push Credentials](/tutorials/mobile-push-credentials) for APNs setup.
## Install With Swift Package Manager
In Xcode:
1. Open your project.
2. Choose File, then Add Package Dependencies.
3. Enter the Sendrealm iOS SDK repository URL.
4. Add the `SendrealmIOS` product to your app target.
```text theme={null}
https://github.com/sendrealm/ios.git
```
## Install With CocoaPods
Add the pod to your `Podfile`:
```ruby theme={null}
pod "SendrealmIOS"
```
Then install pods:
```bash theme={null}
pod install
```
Open the generated `.xcworkspace` after installing pods.
## Enable iOS Capabilities
In Xcode:
1. Open your app target.
2. Open Signing & Capabilities.
3. Add Push Notifications.
4. Confirm the Team and Bundle Identifier match the app configured in Sendrealm.
If your app sends background updates, add Background Modes and check Remote notifications.
If your app sends rich image notifications, add a Notification Service Extension target.
## Initialize
Configure and initialize during app startup:
```swift theme={null}
import SendrealmIOS
Sendrealm.configure()
Sendrealm.shared.initialize([
"appId": "YOUR_SENDREALM_APP_ID",
"environment": "development",
"apnsEnvironment": "sandbox",
"autoRequestPermission": false
]) { result, error in
print(result as Any, error as Any)
}
```
Use `environment: "development"` for test devices you want to target separately. Omit it for production.
Set `apnsEnvironment` based on the build:
| Build type | APNs environment |
| --------------------------------------- | ---------------- |
| Xcode debug or development-signed build | `sandbox` |
| TestFlight | `production` |
| App Store | `production` |
| Production-signed ad hoc build | `production` |
Most apps should set `autoRequestPermission` to `false` and ask for permission after explaining the value of notifications.
## Register For Push
Add the standard app delegate callback so Sendrealm can complete iOS push registration:
```swift theme={null}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Sendrealm.didRegisterForRemoteNotifications(withDeviceToken: deviceToken)
}
```
## Ask For Permission
Ask for permission from a user action:
```swift theme={null}
Sendrealm.shared.requestPermission { granted, error in
print(granted?.boolValue == true, error as Any)
}
```
Read permission status:
```swift theme={null}
Sendrealm.shared.getPermissionStatus { status in
print(status as Any)
}
```
iOS users can deny notifications, change alert style, disable sounds, disable badges, or use Focus settings. Permission status helps you decide what to show in your app UI.
## Foreground Display
Configure foreground presentation when notifications should appear while the app is open:
```swift theme={null}
Sendrealm.shared.setForegroundPresentation([
"banner": true,
"list": true,
"sound": true,
"badge": true
]) { success in
print(success.boolValue)
}
```
## Link A Signed-In User
Call `login` after the user signs in:
```swift theme={null}
Sendrealm.shared.login("user-123", email: "user@example.com") { error in
print(error as Any)
}
```
Call `logout` when the user signs out.
## Tags
Use tags for app-observed preferences, state, and behavior:
```swift theme={null}
Sendrealm.shared.addTags([
"plan": "pro",
"onboardingComplete": true
]) { success, error in
print(success.boolValue)
print(error as Any)
}
```
Do not use SDK tags for authoritative account, billing, security, compliance, or verified profile data. Update those values from your backend.
## Custom Events
Track app events for segmentation, analytics, or automations:
```swift theme={null}
Sendrealm.shared.trackEvent("checkout_started", properties: [
"product_id": "sku_123",
"price": 29
]) { success, error in
print(success.boolValue)
print(error as Any)
}
```
Use stable event names and avoid sending sensitive data unless your team intentionally wants that data stored in Sendrealm.
## Rich Notifications
Rich image notifications require a Notification Service Extension. In the extension target, call the Sendrealm helper:
```swift theme={null}
SendrealmNotificationServiceHelper.enrich(
request: request,
bestAttemptContent: bestAttemptContent,
completion: contentHandler
)
```
If the image cannot be downloaded in time, iOS should still display the notification without the image.
## Silent Pushes
Silent pushes require Background Modes with Remote notifications enabled. Delivery is best effort and can be throttled by iOS.
Do not rely on silent pushes as the only path for critical user-visible work.
## Diagnostics
Use diagnostics while testing:
```swift theme={null}
Sendrealm.shared.getDiagnostics { diagnostics in
print(diagnostics as Any)
}
```
Confirm diagnostics show:
* A device ID.
* Token presence.
* Expected APNs environment.
* Expected permission status.
* Subscribed state unless the user opted out.
* No unexpected SDK error.
## Troubleshooting
| Symptom | What to check |
| ---------------------------------- | -------------------------------------------------------------------------------------------------- |
| Token is missing | Test on a physical device and confirm Push Notifications are enabled in Apple Developer and Xcode. |
| Development push fails | Confirm `apnsEnvironment` is `sandbox` and the build is development-signed. |
| TestFlight or App Store push fails | Confirm `apnsEnvironment` is `production`. |
| Signing fails after enabling push | Refresh automatic signing or regenerate the provisioning profile. |
| Notifications are delayed | Check APNs priority, device connectivity, Focus settings, and notification settings. |
| Silent pushes are inconsistent | This is expected under iOS power policy; use silent pushes only for best-effort refresh work. |
| Rich images do not attach | Confirm the Notification Service Extension is included in the app build. |
| Tags fail with `ContactNotLinked` | Call `login(userId, email)` before setting user tags. |
## Related Pages
* [Mobile Push Credentials](/tutorials/mobile-push-credentials)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
* [React Native Bare SDK](/sdks/react-native-bare)
# JavaScript SDK
Source: https://docs.sendrealm.com/sdks/javascript
Use the JavaScript and TypeScript SDK from trusted backend code.
Use the Sendrealm JavaScript SDK from trusted server-side or edge environments to call the Sendrealm API.
This SDK uses a Sendrealm API key. Do not use it to register browsers or mobile devices for push. Use the Android, iOS, React Native, or React Web Push SDK for device registration.
Do not expose a Sendrealm API key in browser JavaScript or mobile app code. API keys are server-side secrets.
## Runtime Support
The SDK uses native `fetch` and has no runtime dependencies.
* Node.js 18 or newer.
* Cloudflare Workers.
* Deno.
* Bun.
* Vercel Edge Runtime.
* Other runtimes with `fetch`, `Headers`, `Request`, and `Response`.
## Install
```bash theme={null}
npm install @sendrealm/sdk
```
## Create An API Key
Create an API key in the Sendrealm dashboard and store it in your secret manager or environment variables.
```bash theme={null}
SENDREALM_API_KEY=sk_...
```
See [API Keys](/tutorials/api-keys) for dashboard setup.
## Create A Client
```ts theme={null}
import Sendrealm from "@sendrealm/sdk";
const client = new Sendrealm({
apiKey: process.env.SENDREALM_API_KEY,
projectId: process.env.SENDREALM_PROJECT_ID,
});
```
If `SENDREALM_API_KEY` is set, the client can read it automatically:
```ts theme={null}
import Sendrealm from "@sendrealm/sdk";
const client = new Sendrealm();
```
## Client Options
Use client options for custom timeouts, retries, headers, or fetch behavior:
```ts theme={null}
const client = new Sendrealm({
apiKey: process.env.SENDREALM_API_KEY,
timeout: 60_000,
maxRetries: 2,
fetch: customFetch,
defaultHeaders: {
"X-App": "my-service",
},
});
```
Important options:
* `apiKey`: required unless `SENDREALM_API_KEY` is set.
* `projectId`: optional project selector; defaults to `SENDREALM_PROJECT_ID`, then to the API key's default project.
* `timeout`: request timeout in milliseconds.
* `maxRetries`: number of automatic retries for retryable failures.
* `fetch`: custom fetch implementation.
* `defaultHeaders`: headers sent with every request.
* `defaultQuery`: query parameters sent with every request.
`apiKey` may also be an async function if your service rotates credentials.
## Send Email
```ts theme={null}
const email = await client.emails.send({
from: "hello@example.com",
to: ["user@example.com"],
subject: "Welcome",
text: "Hello from Sendrealm",
html: "
Hello from Sendrealm
",
});
```
Before sending production email, make sure the sending domain is verified in Sendrealm.
## Send Push
Send push notifications to registered devices:
```ts theme={null}
await client.push.notifications.send({
app_id: "app_123",
emails: ["user@example.com"],
notification: {
title: "Your order shipped",
body: "Track it now",
launch_url: "https://example.com/orders/123",
},
});
```
Push sending requires device setup first:
* Android devices use the Android or React Native SDK.
* iOS devices use the iOS or React Native SDK.
* Web browsers use the React Web Push SDK.
* Firebase, APNs, or Web Push provider settings must be configured in Sendrealm.
## Test And Diagnose Push
Use API-key resources from trusted backend code to inspect setup and prove one
device end to end:
```ts theme={null}
const apps = await client.push.apps.list();
const app = apps[0];
const providers = await client.push.apps.listProviders(app.public_id);
const devices = await client.push.devices.list({
app_id: app.public_id,
environment: "development",
subscribed: true,
});
const test = await client.push.tests.create({
app_id: app.public_id,
device_id: devices.data[0].device_id,
title: "Sendrealm test",
body: "Push registration is working",
});
const trace = await client.push.tests.retrieve(test.id);
```
Raw APNs, FCM, and Web Push credentials are not returned by app or device
resources. Push campaign SDK methods create and edit drafts, preview reachable
devices, and test a draft on one device; they do not schedule or launch it.
## Ingest Events
```ts theme={null}
await client.events.ingest({
event: "order.completed",
email: "user@example.com",
payload: {
order_id: "order_123",
total: 42,
},
idempotency_key: "order_123_completed",
});
```
Each event should include one identity, such as `contact_id`, `external_id`, or `email`.
Use an `idempotency_key` when your system might retry the same event.
For correlated journeys such as checkout recovery, pass the business identifier
on every related event:
```ts theme={null}
await client.events.ingest({
event: "checkout.started",
email: "user@example.com",
correlation: { key: "checkout_id", value: "checkout_123" },
contact: { mode: "upsert", fields: { first_name: "Olivia" } },
});
```
Avoid putting sensitive personal data in event data unless your team intentionally wants that data in Sendrealm.
## Work With Contacts
List contacts with cursor pagination:
```ts theme={null}
for await (const contact of client.contacts.list({ limit: 100 })) {
console.log(contact.email);
}
```
Create a contact:
```ts theme={null}
const contact = await client.contacts.create({
email: "user@example.com",
fields: {
first_name: "Olivia",
plan: "pro",
},
});
```
Update a contact:
```ts theme={null}
await client.contacts.update(contact.id, {
fields: {
plan: "enterprise",
},
});
```
Look up or upsert a contact by email:
```ts theme={null}
const existing = await client.contacts.getByEmail("user@example.com");
const contact = await client.contacts.upsert({
email: "user@example.com",
fields: { plan: "enterprise" },
});
```
Use backend-owned contact fields for authoritative customer data such as billing plan, account status, compliance flags, and verified profile data.
## Dashboard Resources
Use API-key-scoped resources to inspect the current project, choose a verified domain, and create campaign drafts:
```ts theme={null}
const project = await client.project.retrieve();
const domains = await client.domains.list();
const verifiedDomain = domains.data.find(domain => domain.status === "verified");
if (!verifiedDomain) {
throw new Error("A verified sending domain is required.");
}
const campaign = await client.campaigns.create({
name: "July product update",
});
await client.campaigns.update(campaign.id, {
subject: "What changed in July",
from: {
name: "Sendrealm",
address: `hello@${verifiedDomain?.name}`,
},
audience_ids: ["018f4a28-29f0-7a2e-86c3-6a8f1b6dd294"],
content: {
type: "doc",
content: [],
},
});
```
Campaign APIs create and update drafts only. Review readiness and schedule or send the campaign from the SendRealm dashboard.
## Automations
Validate drafts before publishing, inspect runs, and use no-send test runs for
waits and timeout paths:
```ts theme={null}
const validation = await client.automations.validate(definition);
const testRun = await client.automations.tests.create(automationId, {
event: "checkout.started",
email: "user@example.com",
correlation: { key: "checkout_id", value: "checkout_123" },
});
await client.automations.tests.advance(testRun.id, 3600);
await client.automations.runs.cancel(runId, {
reason: "Customer completed checkout elsewhere",
});
```
## Pagination
Some list endpoints return cursor pages. Consume every item with `for await`:
```ts theme={null}
for await (const contact of client.contacts.list({ limit: 100 })) {
console.log(contact.email);
}
```
Or inspect pages manually:
```ts theme={null}
let page = await client.contacts.list({ limit: 20 });
while (page.hasNextPage()) {
page = await page.getNextPage();
}
```
## Errors
Non-2xx responses throw typed errors:
```ts theme={null}
import Sendrealm, { APIError, RateLimitError } from "@sendrealm/sdk";
try {
await client.contacts.retrieve("missing");
} catch (error) {
if (error instanceof RateLimitError) {
console.log(error.headers.get("retry-after"));
}
if (error instanceof APIError) {
console.log(error.status, error.code, error.message);
}
}
```
Common error categories:
* Authentication errors: check the API key.
* Permission errors: check key scope and project access.
* Validation errors: check required fields and request shape.
* Rate limits: retry after the server-provided delay when available.
* Connection errors: check network and runtime fetch behavior.
## Edge Runtime Examples
Cloudflare Workers:
```ts theme={null}
import Sendrealm from "@sendrealm/sdk";
export default {
async fetch(_request: Request, env: Env) {
const client = new Sendrealm({
apiKey: env.SENDREALM_API_KEY,
});
await client.events.ingest({
event: "worker.received",
external_id: "visitor_123",
});
return new Response("ok");
},
};
```
Deno:
```ts theme={null}
import Sendrealm from "npm:@sendrealm/sdk";
const client = new Sendrealm({
apiKey: Deno.env.get("SENDREALM_API_KEY"),
});
```
Bun:
```ts theme={null}
import Sendrealm from "@sendrealm/sdk";
const client = new Sendrealm({
apiKey: Bun.env.SENDREALM_API_KEY,
});
```
## Production Checklist
* API key is stored in a secret manager or environment variable.
* API key is never sent to browser or mobile code.
* Sending domains are verified for email.
* Device SDKs are installed before backend push sends target app users.
* Event names are stable.
* Event submissions use `idempotency_key` where retries are possible.
* Errors are logged with status, code, and message.
* Rate limit responses are handled.
## Related Pages
* [API Keys](/tutorials/api-keys)
* [Events](/tutorials/events)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
# SDK Overview
Source: https://docs.sendrealm.com/sdks/overview
Choose the right Sendrealm SDK for your app.
Sendrealm provides SDKs for apps that receive push notifications and for trusted backend code that calls the Sendrealm API.
## Which SDK Should I Use?
| If you are building | Use this SDK |
| ------------------------------------------------------- | ------------------------------------------------ |
| Native Android app | [Android SDK](/sdks/android) |
| Native iOS app | [iOS SDK](/sdks/ios) |
| Bare React Native app | [React Native Bare SDK](/sdks/react-native-bare) |
| Expo app with prebuild, `expo run`, or EAS builds | [React Native Expo SDK](/sdks/react-native-expo) |
| React, Vite, or Next.js web app | [React Web Push SDK](/sdks/react) |
| Backend, worker, queue consumer, or serverless function | [JavaScript SDK](/sdks/javascript) |
Expo Go is not supported for mobile push because Sendrealm uses native Android and iOS code. Use an Expo development build or a production build.
## Device SDKs
Use a device SDK when your app needs to receive push notifications.
Device SDKs help your app:
* Register the current app install with Sendrealm.
* Ask for notification permission at the right time.
* Link the device to a signed-in user.
* Store app-sourced tags.
* Track app events for segmentation and automations.
* Handle notification opens.
Device SDKs use a Sendrealm app ID from the dashboard. They do not use Sendrealm API keys.
Never put a Sendrealm API key in a mobile app or browser app. API keys belong in trusted server-side code.
## Server SDK
Use the JavaScript SDK from trusted code when you need to call the Sendrealm API.
Common backend tasks include:
* Sending email.
* Sending push notifications.
* Creating or updating contacts.
* Ingesting events.
* Managing audiences, topics, templates, and automations.
The JavaScript SDK uses a Sendrealm API key. Store the key in your secret manager or environment variables.
## Recommended Setup Order
For mobile push, use this order:
1. Create or select your Sendrealm app in the dashboard.
2. Configure the push provider credentials for your platform.
3. Install the SDK.
4. Initialize the SDK once during app startup.
5. Ask for notification permission after explaining the value to the user.
6. Call `login` after the user signs in.
7. Send a test push to a real target device.
8. Check SDK diagnostics if delivery does not work as expected.
## What You Need From The Dashboard
Device SDKs need a Sendrealm app ID.
Mobile push providers also need platform credentials:
* Android: Firebase service account JSON and matching Android package name.
* iOS: APNs `.p8` key, Key ID, Team ID, Bundle ID, and APNs environment.
* Web Push: Web provider enabled in Sendrealm.
See [Mobile Push Credentials](/tutorials/mobile-push-credentials) for the credential walkthrough.
## Delivery Expectations
Push notifications are best effort. Sendrealm can accept a send request and hand it to Firebase, APNs, or the browser push service, but final delivery and display still depend on the device, operating system, browser, user settings, battery state, app state, network connectivity, and platform policies.
Design your app so important state is available when the user opens it, even if a push notification is delayed or not displayed.
## Where To Go Next
* [Android SDK](/sdks/android)
* [iOS SDK](/sdks/ios)
* [React Native Bare SDK](/sdks/react-native-bare)
* [React Native Expo SDK](/sdks/react-native-expo)
* [React Web Push SDK](/sdks/react)
* [JavaScript SDK](/sdks/javascript)
# React Web Push SDK
Source: https://docs.sendrealm.com/sdks/react
Use @sendrealm/react to register browser Web Push subscriptions.
Use the Sendrealm React SDK to receive Web Push notifications in React, Vite, and Next.js apps.
This SDK runs in the browser and uses a Sendrealm app ID. It does not use a Sendrealm API key.
Never put a Sendrealm API key in browser JavaScript. Use `@sendrealm/react` for browser push registration and `@sendrealm/sdk` from trusted backend code to send notifications.
## Requirements
* React 18 or newer.
* A Sendrealm Push App with the Web provider active.
* HTTPS in production.
* The Sendrealm service worker served from the same origin as your app.
* A notification permission prompt triggered from a user action.
iOS Web Push only works for installed Home Screen web apps with a valid web app manifest.
## Install
```bash theme={null}
npm install @sendrealm/react
```
Copy the service worker into your public root:
```bash theme={null}
npx @sendrealm/react setup
```
Web Push service workers must be served from the same origin as the page. The default SDK path is `/sendrealm-service-worker.js` with scope `/`.
If you prefer to copy it manually:
```bash theme={null}
cp node_modules/@sendrealm/react/sendrealm-service-worker.js public/sendrealm-service-worker.js
```
## Initialize In React Or Vite
Call `init()` from browser code:
```tsx theme={null}
import { useEffect } from "react";
import { init, useSendrealmSubscription } from "@sendrealm/react";
const sendrealmAppId = "YOUR_SENDREALM_PUSH_APP_ID";
function NotificationButton() {
const { subscribed, optIn, optOut } = useSendrealmSubscription();
return (
);
}
export function App() {
useEffect(() => {
void init({
appId: sendrealmAppId,
autoRequestPermission: false,
});
}, []);
return ;
}
```
## Initialize In Next.js
Put initialization in a Client Component:
```tsx theme={null}
"use client";
import { useEffect } from "react";
import { init } from "@sendrealm/react";
export function SendrealmInit() {
useEffect(() => {
void init({
appId: process.env.NEXT_PUBLIC_SENDREALM_PUSH_APP_ID!,
autoRequestPermission: false,
});
}, []);
return null;
}
```
Render `` once near your app shell, and put `sendrealm-service-worker.js` in `public/`.
## Initialization Options
```ts theme={null}
init({
appId: "YOUR_SENDREALM_PUSH_APP_ID",
environment: "production",
autoRequestPermission: false,
serviceWorkerPath: "/sendrealm-service-worker.js",
serviceWorkerScope: "/",
externalUserId: "user_123",
userEmail: "user@example.com",
});
```
| Option | Description |
| ----------------------- | ---------------------------------------------------------------------------------------------------------- |
| `appId` | Sendrealm Push App ID from the dashboard. |
| `environment` | Use `development` for test devices you want to target separately. Omit or use `production` for production. |
| `autoRequestPermission` | Whether initialization asks for notification permission immediately. Most apps should keep this false. |
| `serviceWorkerPath` | Same-origin URL for the service worker file. |
| `serviceWorkerScope` | Service worker scope. Use `/` unless your app intentionally isolates push to a subpath. |
| `externalUserId` | Optional user ID to link during initialization. You can also call `login` after sign-in. |
| `userEmail` | Optional email to link during initialization. |
## Service Worker Diagnostics
The SDK checks the configured service worker path before subscribing the browser.
Diagnostics include a `serviceWorkerCheck` object that reports common setup
issues such as missing files, HTML fallbacks, cross-origin worker URLs, or an old
worker file after an SDK upgrade.
```ts theme={null}
const diagnostics = await getSendrealmClient().getDiagnostics();
console.log(diagnostics.serviceWorkerCheck);
```
Run the setup command again after package upgrades:
```bash theme={null}
npx @sendrealm/react setup
```
You cannot register a GitHub or CDN URL directly as the Web Push service
worker. Browser service-worker registration requires the worker script to be
served from your application origin. You can use GitHub Releases as a download
source for the file, but deploy it into your app's public directory.
## Permission And Subscription UI
Browsers expect notification prompts to happen after a user action. Show your own explanation first, then call `optIn()` from a button click.
```tsx theme={null}
import { useSendrealmPermission, useSendrealmSubscription } from "@sendrealm/react";
export function PushSettings() {
const { permissionStatus, requestPermission } = useSendrealmPermission();
const { subscribed, optIn, optOut } = useSendrealmSubscription();
return (
Permission: {permissionStatus}
Subscribed: {subscribed ? "yes" : "no"}
);
}
```
## Link A Signed-In User
```ts theme={null}
import { getSendrealmClient } from "@sendrealm/react";
const sendrealm = getSendrealmClient();
await sendrealm.login("user_123", "user@example.com");
```
Call `logout` when the user signs out:
```ts theme={null}
await sendrealm.logout();
```
## Tags And Events
Use tags for client-observed preferences, state, and behavior:
```ts theme={null}
await sendrealm.addTags({
plan: "pro",
onboarding_complete: true,
locale: "en-US",
});
```
Track app events:
```ts theme={null}
await sendrealm.trackEvent("checkout_started", {
cart_id: "cart_123",
total: 42,
});
```
Use backend-owned contact properties for authoritative account, billing, compliance, and verified profile data.
## Notification Events
Use listeners when your app needs to react to notification opens or actions:
```tsx theme={null}
import { useEffect } from "react";
import { useSendrealm } from "@sendrealm/react";
export function NotificationEvents() {
const { client } = useSendrealm();
useEffect(() => {
const opened = client.addNotificationClickListener(event => {
console.log("opened", event.launchUrl, event.notificationId);
});
return () => opened.remove();
}, [client]);
return null;
}
```
Read the notification that opened the page:
```ts theme={null}
const initialOpen = await getSendrealmClient().getInitialNotification();
```
## Send To Web Devices
Once a browser is registered, send web push from trusted backend code with the JavaScript SDK:
```ts theme={null}
await client.push.notifications.send({
app_id: "push_app_short_id",
external_ids: ["user_123"],
platforms: ["web"],
notification: {
title: "Hello from Sendrealm",
body: "This targets the user's registered web browsers.",
launch_url: "https://app.example.com",
},
});
```
## Diagnostics
Use diagnostics to confirm browser support, device ID, permission status, subscription state, service worker path, and the latest SDK error.
```ts theme={null}
const diagnostics = await getSendrealmClient().getSupportDiagnostics();
console.log(diagnostics);
```
## Hooks
| Hook | Returns |
| ---------------------------- | ----------------------------------------------------------------- |
| `useSendrealm()` | `{ client, state, initializing, error }`. |
| `useSendrealmPermission()` | `{ permissionStatus, permissionGranted, requestPermission }`. |
| `useSendrealmSubscription()` | `{ subscribed, token, optIn, optOut, refreshRegistrationToken }`. |
## Troubleshooting
| Symptom | What to check |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Initialization runs during server rendering | Move `init()` to a Client Component or browser-only effect. |
| Permission prompt does not appear | Trigger opt-in from a user action and confirm the browser has not blocked notifications for the site. |
| Subscription fails | Use a full browser with push support and confirm the service worker file is served from the same origin. |
| Notifications do not open the expected URL | Confirm the notification has a launch URL and the browser allows the service worker to open it. |
| Images do not appear | Use HTTPS image URLs and expect browser support to vary. |
## Related Pages
* [Web Push Setup](/tutorials/web-push)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
* [JavaScript SDK](/sdks/javascript)
# React Native Bare SDK
Source: https://docs.sendrealm.com/sdks/react-native-bare
Install and initialize Sendrealm in a bare React Native app.
Use the Sendrealm React Native SDK in React Native apps that own their native `android` and `ios` projects.
If you use Expo prebuild or EAS builds, use [React Native Expo SDK](/sdks/react-native-expo).
## Requirements
* React 18 or newer.
* React Native 0.76 or newer.
* Android device or emulator with Google Play services.
* Physical iOS device for APNs testing.
* A Sendrealm app ID from the dashboard.
* Firebase credentials uploaded for Android delivery.
* APNs credentials uploaded for iOS delivery.
* Push Notifications enabled for the iOS App ID and Xcode target.
Expo Go is not supported because mobile push requires native code.
## Setup Order
1. Upload Firebase and APNs credentials in Sendrealm.
2. Install `@sendrealm/react-native`.
3. Add Android `google-services.json`.
4. Enable iOS Push Notifications capabilities.
5. Forward iOS AppDelegate notification callbacks.
6. Rebuild Android and iOS.
7. Initialize Sendrealm from JavaScript.
8. Ask for notification permission after explaining the value to the user.
9. Call `login` when the user signs in.
10. Send test pushes on Android and iOS.
## Install
```bash theme={null}
npm install @sendrealm/react-native
```
Rebuild the native apps after installing:
```bash theme={null}
npx react-native run-android
npx react-native run-ios
```
If your iOS project uses CocoaPods directly:
```bash theme={null}
cd ios
pod install
```
## Android Setup
Android push uses Firebase Cloud Messaging.
Before testing Android:
* Add `android/app/google-services.json`.
* Apply the Google Services Gradle plugin if your app does not already use it.
* Confirm the Firebase Android package name matches your React Native Android `applicationId`.
* Upload the Firebase service account JSON in Sendrealm.
* Test on a device or emulator with Google Play services.
See [Mobile Push Credentials](/tutorials/mobile-push-credentials) for the Firebase walkthrough.
## iOS Setup
Before testing iOS:
* Enable Push Notifications for the Apple App ID.
* Enable Push Notifications on the Xcode app target.
* Use a Bundle ID that matches the app configured in Sendrealm.
* Upload the APNs `.p8` key, Key ID, Team ID, Bundle ID, and environment in Sendrealm.
* Test on a physical iOS device.
If your app sends background updates, enable Background Modes with Remote notifications.
If your app sends rich image notifications, add a Notification Service Extension target.
Autolinking installs the iOS native module, but bare apps still need to forward APNs callbacks from `AppDelegate.swift`:
```swift theme={null}
import SendrealmReactNative
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
SendrealmModule.configure()
return true
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
SendrealmModule.didRegisterForRemoteNotifications(withDeviceToken: deviceToken)
}
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
SendrealmModule.didReceiveRemoteNotification(userInfo)
completionHandler(.newData)
}
```
If your app sets `UNUserNotificationCenter.current().delegate` after Sendrealm is configured, forward notification responses from that delegate so open and action events are tracked:
```swift theme={null}
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
SendrealmModule.didReceiveNotificationResponse(response)
completionHandler()
}
```
See [Mobile Push Credentials](/tutorials/mobile-push-credentials) for the APNs walkthrough.
## Initialize
Initialize once near app startup:
```tsx theme={null}
import { useEffect } from "react";
import Sendrealm from "@sendrealm/react-native";
export default function App() {
useEffect(() => {
void Sendrealm.initialize({
appId: "YOUR_SENDREALM_APP_ID",
environment: "development",
autoRequestPermission: false,
apnsEnvironment: "sandbox",
});
}, []);
return null;
}
```
Use `environment: "development"` for test devices you want to target separately. Omit it for production.
Use `apnsEnvironment: "sandbox"` for development-signed iOS builds and `production` for TestFlight or App Store builds.
Most apps should keep `autoRequestPermission: false` and ask permission after an in-app explanation.
## Ask For Permission
```tsx theme={null}
await Sendrealm.requestPermission();
```
Check status:
```tsx theme={null}
const status = await Sendrealm.getPermissionStatus();
const allowed = await Sendrealm.hasNotificationPermission();
```
Android 13 and newer show a runtime notification prompt. iOS shows the alert, badge, and sound authorization prompt.
## Link A Signed-In User
```tsx theme={null}
await Sendrealm.login("user-123", "user@example.com");
```
Call `logout` when the user signs out:
```tsx theme={null}
await Sendrealm.logout();
```
## Tags
Use tags for app-observed preferences, state, and behavior:
```tsx theme={null}
await Sendrealm.addTags({
plan: "pro",
onboardingComplete: true,
});
```
Do not use SDK tags for authoritative account, billing, security, compliance, or verified profile data. Send those from your backend.
## Custom Events
Track app events for segmentation, analytics, or automations:
```tsx theme={null}
await Sendrealm.trackEvent("checkout_started", {
product_id: "sku_123",
price: 29,
});
```
Use stable event names and avoid sending sensitive data unless your team intentionally wants that data stored in Sendrealm.
## Notification Opens
Listen for notification opens when your app needs to route the user:
```tsx theme={null}
const sub = Sendrealm.addNotificationClickListener((event) => {
console.log(event.notificationId, event.launchUrl);
});
sub.remove();
```
Read the notification that opened the app from a cold start:
```tsx theme={null}
const initial = await Sendrealm.getInitialNotification();
```
## Android Notification Channels
Create Android notification channels when your app needs explicit sound, vibration, or importance behavior:
```tsx theme={null}
await Sendrealm.createNotificationChannel({
id: "orders",
name: "Orders",
importance: "high",
soundName: "order_update",
});
```
Android remembers channel behavior after a channel is created. Use a new channel ID for materially different sound or importance behavior.
## Diagnostics
Collect support-safe diagnostics during setup:
```tsx theme={null}
const diagnostics = await Sendrealm.getSupportDiagnostics();
console.log(JSON.stringify(diagnostics, null, 2));
```
Confirm diagnostics show:
* A device ID.
* Token presence.
* Expected permission status.
* Subscribed state unless the user opted out.
* SDK version.
* No unexpected SDK error.
## Troubleshooting
| Symptom | What to check |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Expo Go fails to load the package | Use a development build or bare app because native code is required. |
| Android token is missing | Use a Google Play device or emulator and verify Firebase package name setup. |
| iOS push does not arrive | Use a physical device and verify APNs environment, Bundle ID, Team ID, Key ID, and `.p8` key in Sendrealm. |
| iOS entitlement is missing | Enable Push Notifications in Apple Developer and on the Xcode app target. |
| Notifications are delayed | Check Android power management, FCM priority, iOS APNs priority, Focus settings, and notification permissions. |
| Some pushes are missing | Check stale tokens, disabled channels, offline devices, and provider diagnostics. |
| Tags return `ContactNotLinked` | Call `login(userId, email)` before tags. |
| Notification opens app but not the expected screen | Check the notification launch URL and your app's deep link configuration. |
## Related Pages
* [React Native Expo SDK](/sdks/react-native-expo)
* [Mobile Push Credentials](/tutorials/mobile-push-credentials)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
# React Native Expo SDK
Source: https://docs.sendrealm.com/sdks/react-native-expo
Use Sendrealm with Expo development builds, prebuild, and EAS.
Use the Sendrealm React Native SDK in Expo apps that can include native code. That means Expo prebuild, `expo run`, EAS development builds, and production builds.
Expo Go is not supported because mobile push requires native code.
If your React Native app already owns native `android` and `ios` projects without Expo prebuild, use [React Native Bare SDK](/sdks/react-native-bare).
## Requirements
* Expo project using development builds or prebuild.
* Android device or emulator with Google Play services.
* Physical iOS device for APNs testing.
* A Sendrealm app ID from the dashboard.
* Firebase credentials uploaded for Android delivery.
* APNs credentials uploaded for iOS delivery.
* Push Notifications enabled for the iOS Bundle ID in Apple Developer.
## Setup Order
1. Upload Firebase and APNs credentials in Sendrealm.
2. Install `@sendrealm/react-native`.
3. Add the Sendrealm Expo plugin to `app.json` or `app.config.js`.
4. Add Android `google-services.json`.
5. Configure iOS push capabilities.
6. Run Expo prebuild or create an EAS build.
7. Initialize Sendrealm from JavaScript.
8. Ask for notification permission after explaining the value to the user.
9. Call `login` when the user signs in.
10. Send test pushes on Android and iOS.
## Install
```bash theme={null}
npx expo install @sendrealm/react-native
```
## Configure The Plugin
Add the Sendrealm plugin to `app.json` or `app.config.js`:
```json theme={null}
{
"expo": {
"plugins": [
[
"@sendrealm/react-native",
{
"android": {
"googleServicesFile": "./google-services.json",
"notificationIcon": "ic_stat_sendrealm",
"notificationColor": "#111827"
},
"ios": {
"apnsEnvironment": "sandbox",
"enableBackgroundRemoteNotifications": true,
"notificationServiceExtension": true
}
}
]
],
"extra": {
"sendrealmAppId": "YOUR_SENDREALM_APP_ID",
"sendrealmPushEnvironment": "development",
"sendrealmApnsEnvironment": "sandbox"
}
}
}
```
Do not put Sendrealm API keys, Firebase service account JSON, or APNs `.p8` files in Expo config. Provider private keys belong in the Sendrealm dashboard.
## Android Setup
Generate `google-services.json` from Firebase and save it in your Expo project. Point the plugin at the file:
```json theme={null}
{
"android": {
"googleServicesFile": "./google-services.json"
}
}
```
During prebuild, the plugin copies it into the Android app.
Make sure the Firebase Android package name matches the package Expo builds, usually `expo.android.package`.
## iOS Setup
In Apple Developer:
1. Open Certificates, Identifiers & Profiles.
2. Open Identifiers.
3. Select the App ID for the Bundle ID in your Expo config.
4. Enable Push Notifications.
5. Save the App ID changes.
In Expo config:
* Set `ios.apnsEnvironment` to `sandbox` for development builds or `production` for TestFlight and App Store builds.
* Set `ios.enableBackgroundRemoteNotifications` to `true` only if you send silent/background pushes.
* Set `ios.notificationServiceExtension` to `true` if you send rich image notifications.
Then rerun prebuild or create a new EAS build.
See [Mobile Push Credentials](/tutorials/mobile-push-credentials) for Firebase and APNs setup.
## Prebuild And Run
Generate native projects and run locally:
```bash theme={null}
npx expo prebuild --platform android
npx expo run:android
npx expo prebuild --platform ios
npx expo run:ios --device
```
Use `--device` for iOS push testing.
## Build With EAS
Build development clients with EAS:
```bash theme={null}
npx eas build --profile development --platform android
npx eas build --profile development --platform ios
```
## Initialize
Read values from Expo config and initialize once:
```tsx theme={null}
import Constants from "expo-constants";
import { useEffect } from "react";
import Sendrealm from "@sendrealm/react-native";
export default function App() {
useEffect(() => {
const extra = Constants.expoConfig?.extra ?? {};
void Sendrealm.initialize({
appId: extra.sendrealmAppId,
environment: extra.sendrealmPushEnvironment ?? "development",
autoRequestPermission: false,
apnsEnvironment: extra.sendrealmApnsEnvironment ?? "sandbox",
});
}, []);
return null;
}
```
Use `production` for production-targeted app builds.
Most apps should keep `autoRequestPermission: false` and ask permission after an in-app explanation.
## Ask For Permission
```tsx theme={null}
await Sendrealm.requestPermission();
```
Check status:
```tsx theme={null}
const status = await Sendrealm.getPermissionStatus();
const allowed = await Sendrealm.hasNotificationPermission();
```
## Link A Signed-In User
```tsx theme={null}
await Sendrealm.login("user-123", "user@example.com");
```
## Tags And Events
Use tags for app-observed preferences, state, and behavior:
```tsx theme={null}
await Sendrealm.addTags({
plan: "pro",
onboardingComplete: true,
});
```
Track app events:
```tsx theme={null}
await Sendrealm.trackEvent("checkout_started", {
product_id: "sku_123",
price: 29,
});
```
Call `login` before setting user tags.
## Rich iOS Media
Rich image notifications require a Notification Service Extension. Enable it in the plugin:
```json theme={null}
{
"ios": {
"notificationServiceExtension": true
}
}
```
Then rerun prebuild or create a new EAS build.
## Android Notification Icons
Android status bar icons should be simple drawable resources, usually monochrome. If you set:
```json theme={null}
{
"android": {
"notificationIcon": "ic_stat_sendrealm"
}
}
```
The native Android project must contain a matching drawable resource such as `res/drawable/ic_stat_sendrealm.xml`.
## Diagnostics
Use support diagnostics while testing:
```tsx theme={null}
const diagnostics = await Sendrealm.getSupportDiagnostics();
console.log(JSON.stringify(diagnostics, null, 2));
```
Confirm diagnostics show:
* A device ID.
* Token presence.
* Expected permission status.
* Subscribed state unless the user opted out.
* SDK version.
* No unexpected SDK error.
## Troubleshooting
| Symptom | What to check |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| Expo Go does not work | Build a development client or production app because native code is required. |
| Android token is missing | Use a Google Play device or emulator and verify the Firebase Android package name. |
| iOS push does not arrive | Use a physical device and verify APNs environment, Bundle ID, Team ID, Key ID, and `.p8` key in Sendrealm. |
| iOS entitlement is missing | Enable Push Notifications on the Apple Developer App ID, rerun prebuild, and rebuild the app. |
| Plugin changes do not appear | Rerun `expo prebuild` or create a fresh EAS build. |
| Notifications are delayed | Check Android power management, FCM priority, iOS APNs priority, Focus settings, and notification permissions. |
| Some pushes are missing | Check stale tokens, disabled channels, offline devices, and provider diagnostics. |
| Rich images do not attach | Confirm `notificationServiceExtension` is enabled and the app has been rebuilt. |
| Tags return `ContactNotLinked` | Call `login(userId, email)` before tags. |
## Related Pages
* [React Native Bare SDK](/sdks/react-native-bare)
* [Mobile Push Credentials](/tutorials/mobile-push-credentials)
* [Send Push Notification API](/api-reference/endpoint/send-push-notification)
# API Keys
Source: https://docs.sendrealm.com/tutorials/api-keys
Create and manage team-wide and project-scoped API keys
## How API keys work
API keys are team-bound tokens used to authenticate API, SDK, MCP, and SMTP requests. Project API keys are permanently limited to their owning project. Team API keys can authorize selected projects or every current and future project in their team. Every key can also be limited to sending, read-only, or custom permissions. Treat every key as a secret.
## Create a team API key
Use a team API key when an integration needs access to every current and future project in one team:
1. Navigate to **Settings → Team API Keys**.
2. Click **Create Team API Key**.
3. Give your API key a name.
4. Choose the default project used when an integration does not select one explicitly.
5. Choose Full access, Sending, Read-only, or Custom permissions.
## Create a project API key
Use a project API key when credentials should be permanently limited to one project:
1. Select the project in the dashboard.
2. Navigate to **Project API Keys**.
3. Click **Create Project API Key**.
4. Choose Full access, Sending, Read-only, or Custom permissions.
You can edit a project key's name and permissions later without rotating the secret, but its owning project cannot be changed and additional projects cannot be added. Team keys are managed in Settings and should be used for cross-project access. Existing keys retain full access across their team and continue using their original project by default.
| Permission | Access |
| ----------------- | ---------------------------------------------- |
| `email.send` | REST and SMTP email sending |
| `push.send` | Push notifications, tests, and Live Activities |
| `events.ingest` | Production event ingestion |
| `resources.read` | Read project resources |
| `resources.write` | Create, update, and delete project resources |
| `*` | Full access |
## Select a project
REST requests and the JavaScript SDK use the key's default project unless `X-Sendrealm-Project-Id` is supplied. The selected project must belong to the key's team and be authorized for that key.
```bash theme={null}
curl https://api.sendrealm.com/v1/project \
-H "Authorization: Bearer $SENDREALM_API_KEY" \
-H "X-Sendrealm-Project-Id: PROJECT_ID"
```
The project header is optional, so existing integrations and older SDK versions continue to use the key's default project unchanged.
# Automation Builder
Source: https://docs.sendrealm.com/tutorials/automation-builder
Create, validate, test, and publish event-driven customer journeys from the dashboard.
The Automation Builder lets you turn customer events into email, push, and data workflows without writing the automation definition by hand.
A journey starts with an event, follows the connections between steps, and ends when there are no more steps to run or it reaches an `end_automation` step.
## Before you begin
Prepare the resources your journey will use:
* Publish any email or push templates you plan to send.
* Verify the sending domain used by email steps.
* Configure a push app before adding push steps.
* Create any audiences or topics the automation will update.
## Build a journey
1. Create an automation and give it a clear name and description.
2. Choose the event that starts the journey, such as `user.created` or `order.completed`.
3. Add the actions, waits, and conditions the customer should move through.
4. Connect each step to the next step. Conditions and event waits can lead to different branches.
5. Save the draft, then validate it before publishing.
For example, an onboarding journey could:
1. Start when `user.created` is received.
2. Send a welcome email.
3. Wait for `user.activated` for up to two days.
4. Send a getting-started push when the event arrives.
5. Send a reminder email when the wait times out.
## Configure the trigger
The trigger event name must match the event sent to Sendrealm. You can also add filters when only some occurrences should start the automation.
Use correlation when later events must be matched to the same order, checkout, subscription, or other business object. A correlated `wait_for_event` step should use the same correlation key as the trigger.
## Choose the right steps
* Use `delay` to continue after a fixed amount of time.
* Use `wait_for_event` when the next path depends on customer behavior. Configure both the matched and timeout paths.
* Use `condition` to branch using contact or event data.
* Use email and push template steps for messages. These steps reference published templates rather than copying message content into the automation.
* Use audience, topic, and contact steps to keep customer data and preferences in sync.
* Use `end_automation` when you want a branch to finish explicitly.
Give every step a descriptive, stable key. Step keys appear in validation results and run timelines, which makes a journey much easier to troubleshoot.
## Validate and test
Validation checks that the journey has one trigger, valid connections, reachable steps, no cycles, complete branches, and valid resource references.
Fix every validation issue before publishing. Saving a draft does not activate the journey.
Use a test run to exercise the current draft without sending messages or changing production data. Test runs let you inject synthetic events and advance virtual time, making it possible to verify event waits, delays, and timeout branches without waiting in real time.
## Publish and operate
Publishing creates the version used for new production runs. Future edits remain in the draft until you validate and publish again.
After publishing, use the Runs page to inspect the path taken by each customer, step status, waits, linked messages, and errors. Pausing prevents new runs from starting; it does not cancel runs already in progress. Resume the automation when it is ready to accept new events again.
## How it maps to the API
The builder and API use the same automation model:
* `definition`: executable trigger, steps, and connections
* `editor_layout`: node positions and viewport metadata
Only `definition` affects execution. `editor_layout` preserves the visual arrangement for future editing.
## Best practices
* Start with one customer outcome and keep each journey focused.
* Always provide a timeout path for `wait_for_event` steps.
* Test both successful and timeout branches before publishing.
* Review referenced templates, audiences, topics, domains, and push apps when moving a journey between projects.
* Publish a new version after changing behavior; saving the draft alone does not update production runs.
## Related pages
* [Automations](/tutorials/automations)
* [Automation Reliability](/api-reference/endpoint/automation-reliability)
* [Automation Runs API](/api-reference/endpoint/automation-runs)
# Automations
Source: https://docs.sendrealm.com/tutorials/automations
Create event-driven journeys with templates, waits, conditions, and topic actions.
Automations are DAG-based journeys with one trigger, reusable steps, and explicit branches.
## Supported step types
* `delay`
* `condition`
* `wait_for_event`
* `send_email_template`
* `send_push_template`
* `contact_update`
* `add_to_audience`
* `remove_from_audience`
* `set_topic_subscription`
## Trigger shape
```json theme={null}
{
"trigger": {
"event_name": "order.completed",
"filters": {
"amount_gte": 1000
}
}
}
```
## Common journey
1. Trigger on `order.completed`
2. Send a published email template
3. Wait for `sendrealm.mail.open`
4. If the event arrives, send a push template
5. If it times out, add the contact to a follow-up audience
## Publish requirements
* Exactly one trigger
* Reachable graph
* No cycles in v1
* Published template versions only
* Valid topic, audience, domain, and push app references
## Runtime guarantees
* Automation runs are processed with at-least-once semantics.
* Step execution is protected with step-level idempotency keys so retries do not resend the same step when a send already succeeded.
* `wait_for_event` and timeout paths use run and wait locks to avoid double-resume races.
* If a worker crashes, maintenance sweepers recover stale runs, replay due events, and advance expired waits.
## Retry and timeout behavior
* Event processing retries use exponential backoff.
* Final failures move to the dead-letter queue for replay from backoffice tooling.
* `wait_for_event` timeout handling is minute-level scheduler based, so timeout execution is near the requested delay but not hard real-time.
* If a matching event arrives after the timeout branch already executed, the late event does not reopen that wait state or rerun the completed branch.
## Billing and metering
* Usage can be metered by event ingest, automation runs, wait creation, template test sends, and delivery actions.
* Plan enforcement should be treated as separate from idempotency: a retried request may deduplicate, while accepted usage still counts against the relevant quota or metered line item.
## Retention
* Runs default to 180 days of retention.
* Wait states default to 30 days of retention.
* Template and automation versions remain immutable, but project retention may archive old non-current versions that are no longer referenced by sends, runs, or broadcasts.
## Related pages
* [Automation Builder](/tutorials/automation-builder)
* [Automations API](/api-reference/endpoint/automations)
* [Automation Runs API](/api-reference/endpoint/automation-runs)
# Domains
Source: https://docs.sendrealm.com/tutorials/domains
How to use custom domains to send emails
## Configuring domain
### DNS records
After adding your custom domain to Sendrealm, you’ll need to configure the DNS records with your DNS provider. Once this step is completed, you may need to wait up to 24 hours for the DNS changes to propagate.
#### SPF records
SPF (Sender Policy Framework) is an email authentication method designed to prevent spammers from sending messages on behalf of your domain. It allows the domain owner to specify which mail servers are permitted to send email on behalf of their domain.
#### DKIM records
DKIM (DomainKeys Identified Mail) is an email authentication method designed to detect email spoofing. It allows the receiver to check that an email claiming to come from a specific domain was indeed authorized by the owner of that domain. DKIM uses cryptographic authentication to verify the email's integrity and authenticity.
#### DMARC
DMARC, or Domain-based Message Authentication, Reporting, and Conformance, is an email authentication protocol that helps organizations protect their email domains from being used for phishing and spoofing attacks. It works by allowing domain owners to set policies that specify how receiving email servers should handle emails that claim to be from their domain.
## Domain settings
You can use domain settings to adjust and customize your open tracking, click tracking, and mail content privacy settings. Tailor these aspects precisely to suit your preferences and requirements, ensuring a seamless and secure email experience tailored to your needs.
### Open tracking
Open tracking involves embedding an invisible image in every email sent. When a recipient opens the email, the image is loaded, signaling that the email has been opened. However, this method can lead to unreliable data, as some email clients block images by default, preventing the tracking pixel from loading. Additionally, frequent use of open tracking can negatively impact deliverability rates, as some email providers may flag emails with tracking pixels as spam.
### Click tracking
Click tracking modifies every link within the HTML body of an email to monitor clicks. When recipients click on a link, they are first directed to our server, which logs the click, before being redirected to the intended URL. This allows us to track engagement with the email content.
### Mail-content privacy
Mail-content privacy gives you the option to archive emails for record-keeping and compliance purposes. By default, this option is enabled, ensuring that all sent emails are stored for future reference. However, if data privacy is a concern, you can choose not to save the content of emails, enhancing data privacy for both the sender and the recipients. Disabling content saving ensures that no email content is stored on our servers, providing an additional layer of security and privacy.
# Events
Source: https://docs.sendrealm.com/tutorials/events
Send customer events, understand system events, and trigger automations.
Sendrealm supports two event categories:
* Customer events that you submit, like `order.completed`
* Reserved system events under the `sendrealm.` namespace
## Customer event rules
* Must not start with `sendrealm.`
* Must use lowercase dot-separated names
* Each audience may include underscores
Examples:
* `order.completed`
* `billing.payment_failed`
* `user.onboarded`
## System events
Examples of platform-generated events:
* `sendrealm.mail.send`
* `sendrealm.mail.delivery`
* `sendrealm.mail.open`
* `sendrealm.push.send`
* `sendrealm.push.open`
* `sendrealm.contact.created`
* `sendrealm.audience.entered`
* `sendrealm.topic.subscribed`
## Event identity resolution
When Sendrealm receives an event, it resolves the contact identity in this order:
1. `contact_id`
2. `external_id`
3. normalized `email`
That same identity resolution is used when matching `wait_for_event` automation steps.
## Example request
```bash theme={null}
curl https://api.sendrealm.com/events \
-X POST \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event": "order.completed",
"email": "olivia@example.com",
"payload": {
"order_id": "ord_123",
"amount": 4900,
"currency": "USD"
},
"occurred_at": "2026-06-08T14:15:00.000Z",
"idempotency_key": "evt_order_completed_ord_123"
}'
```
New customer events are accepted with `202 Accepted`. If you resend the same `idempotency_key`, Sendrealm returns the existing event instead of creating a duplicate.
## Delivery guarantees
* Event ingest is at-least-once, not exactly-once.
* Sendrealm deduplicates by `project_id + idempotency_key`.
* Retries use exponential backoff before an event is moved to the dead-letter queue.
* Event ordering is best effort only. Do not assume two separate events arrive or execute in strict sequence.
## Payload and governance
* Event payloads are limited by the project policy `event_payload_limit_bytes`.
* Sendrealm stores schema hints and redacted example payloads in the event catalog for debugging.
* The dashboard lets project owners review the event catalog, inspect example payloads, and confirm which events are currently flagged for likely PII.
* Backoffice tooling can filter the event catalog by event name, source, and PII detection to investigate schema drift faster.
* Backoffice observability also tracks average event-processing latency so you can distinguish queue lag from bad payloads.
* Reserved `sendrealm.*` system events are emitted by the platform and cannot be submitted by customers.
## Retention
* Event retention is controlled per project.
* The default window is 90 days unless your project policy overrides it.
## Related pages
* [Events API](/api-reference/endpoint/events)
* [Automations](/tutorials/automations)
# Mobile Push Credentials
Source: https://docs.sendrealm.com/tutorials/mobile-push-credentials
Create Firebase and APNs credentials and upload them to the Sendrealm dashboard.
Sendrealm needs provider credentials before it can send mobile push notifications for your app. These credentials prove to Firebase and Apple that Sendrealm is allowed to send notifications for your Android and iOS apps.
There are two separate provider setups:
* Android uses Firebase Cloud Messaging, often called FCM.
* iOS uses Apple Push Notification service, usually called APNs.
You only need the provider that matches the platform you are shipping. If your app ships on both Android and iOS, configure both.
One Sendrealm Push App identity maps to one Android package name and/or one iOS Bundle ID. If you ship separate app identities, such as `com.example.app` and `com.example.app.dev`, configure the provider for the exact identity that will initialize the SDK and receive notifications.
Firebase service account JSON files and APNs `.p8` files are sensitive production credentials. Upload them only in the Sendrealm dashboard, store backups in a secure secret manager, and rotate them if you suspect exposure.
## What Goes Where
It is easy to confuse the different Firebase and Apple files. Use this table as the quick map:
| Item | Platform | Where it goes | What it is for |
| ----------------------------------------- | -------- | --------------------------- | ----------------------------------------------------------------------- |
| Firebase service account JSON private key | Android | Sendrealm dashboard | Lets Sendrealm send Android push through FCM. |
| Android package name | Android | Sendrealm dashboard and app | Identifies the Android app package Sendrealm accepts for this Push App. |
| `google-services.json` | Android | Your app project | Required app-side Firebase Android configuration. |
| APNs `.p8` private key | iOS | Sendrealm dashboard | Lets Sendrealm send iOS push through APNs. |
| APNs Key ID | iOS | Sendrealm dashboard | Identifies the Apple private key. |
| Apple Team ID | iOS | Sendrealm dashboard | Identifies your Apple developer team. |
| iOS Bundle ID | iOS | Sendrealm dashboard and app | Identifies the iOS app topic APNs sends to. |
Android apps need `google-services.json` in the app and a Firebase service account private key JSON in Sendrealm. The two files are not interchangeable.
## Before You Start
You need:
* A Sendrealm project and app in the dashboard.
* Firebase project owner or admin access for Android setup.
* Apple Developer Account Holder or Admin access for iOS setup.
* Android application ID, for example `com.example.app`.
* iOS bundle ID, for example `com.example.app`.
* A real Android device or Google Play emulator for Android testing.
* A physical iOS device for APNs testing.
## Android: Create The Firebase Key
Use this section for Android push delivery through Firebase Cloud Messaging.
### Step 1: Open The Firebase Project
1. Open the [Firebase console](https://console.firebase.google.com/).
2. Select the Firebase project for your Android app.
Use the same Firebase project that owns the Android app package you ship to users.
### Step 2: If You Start From Google Cloud, Add Firebase First
If your project already exists in Google Cloud but not Firebase, open the Firebase console and choose Add Firebase to Google Cloud project. Select the existing Google Cloud project and complete the Firebase setup.
After Firebase is added, continue with the Android app registration steps below. `google-services.json` is generated from the Firebase Android app registration flow, not directly from the regular Google Cloud console.
### Step 3: Register The Android App
If the Android app is not registered in Firebase yet:
1. From the Firebase project overview, add an Android app.
2. Enter the exact Android package name used by your app.
3. Complete the app registration flow.
The package name is usually your native Android `applicationId`, for example `com.example.app`. It is case-sensitive and must match the app that users install.
### Step 4: Download `google-services.json`
Firebase offers `google-services.json` during Android app setup. Download it and keep it in your app project.
Where the file goes depends on your app type:
| App type | Where to put `google-services.json` |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Native Android | `app/google-services.json` |
| React Native Bare | `android/app/google-services.json` |
| React Native Expo | Save it in the Expo project, then set `android.googleServicesFile` so prebuild copies it to `android/app/google-services.json`. |
Make sure the file name is exactly `google-services.json`. If your browser downloads `google-services (1).json`, rename it before using it.
This file is not enough for Sendrealm server-side push. Continue to the next step to create the private key Sendrealm needs.
### Step 5: Generate The Service Account Private Key
1. In Firebase, open Project settings.
2. Open the Service accounts tab.
3. Click Generate new private key.
4. Confirm the download.
5. Save the downloaded JSON file securely.
This JSON file contains service account credentials. Sendrealm uses it to authorize FCM HTTP v1 send requests.
### Step 6: Upload The Firebase Key To Sendrealm
In Sendrealm:
1. Open your project.
2. Open **Push Notifications** from the project navigation, next to Domains.
3. Choose Android or Firebase provider settings.
4. Upload the Firebase service account JSON file.
5. Enter the Android package name that matches the app Gradle `applicationId`.
6. Save the provider.
After saving, send a test push to an initialized Android device.
## Android Values To Check
Before testing Android push, confirm:
* Firebase project matches the app you ship.
* Android package name in Firebase exactly matches your app `applicationId`.
* Android package name in Sendrealm exactly matches your app `applicationId`.
* Package name casing is identical.
* Firebase service account belongs to the same Firebase project.
* The uploaded file is a full JSON private key file.
* `google-services.json` is present in the Android app.
* The Google Services Gradle plugin is applied for native Android and React Native Bare apps.
* The Android device or emulator has Google Play services.
* The app has initialized the Sendrealm Android or React Native SDK.
* Android 13 and newer devices have notification permission granted.
## Android Common Mistakes
| Mistake | Result |
| ---------------------------------------------------------------- | ----------------------------------------------------------------- |
| Uploading `google-services.json` instead of service account JSON | Sendrealm cannot authorize server-side FCM sends. |
| Forgetting to add `google-services.json` to the Android app | The app may not have the Firebase Android configuration it needs. |
| Firebase package name does not match app package name | Device token registration or delivery can fail. |
| Testing on emulator without Google Play services | FCM token may never be created. |
| Forgetting Android 13 notification permission | Token may register, but notifications may not display. |
| Using an old deleted service account key | Sendrealm send attempts fail authorization. |
## iOS: Create The APNs Key
Use this section for iOS push delivery through Apple Push Notification service.
### Step 1: Confirm The App ID And Bundle ID
1. Open [Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources/).
2. Open Identifiers.
3. Select the App ID for your app.
4. Confirm the Bundle ID matches your Xcode target.
The Bundle ID is the APNs topic Sendrealm sends to. It must match the app that receives the token.
If you do not have an App ID yet, create an explicit App ID with the same Bundle ID used by the app. Do not use a wildcard App ID for push setup.
Where to check the Bundle ID:
| App type | Where the Bundle ID normally lives |
| ----------------- | ----------------------------------------------------------- |
| Native iOS | Xcode app target, Signing & Capabilities, Bundle Identifier |
| React Native Bare | `ios/.xcworkspace`, app target, Signing & Capabilities |
| React Native Expo | `expo.ios.bundleIdentifier` in Expo config |
### Step 2: Enable Push Notifications On The App ID
Apple must allow the Bundle ID to use APNs.
1. In Certificates, Identifiers & Profiles, open Identifiers.
2. Select the App ID for your Bundle ID.
3. Click Edit.
4. Enable Push Notifications.
5. Save and confirm the change.
Apple requires the Account Holder or Admin role to manage App ID capabilities. If you do not see the controls, ask an Apple Developer Account Holder or Admin on your team to do this step.
When an App ID capability changes, provisioning profiles that include that App ID can become invalid. If signing starts failing later, refresh automatic signing, regenerate the provisioning profile, or rebuild through EAS with updated credentials.
### Step 3: Enable Capabilities In The App
The Apple Developer App ID is the server-side permission. The app target also needs the matching entitlement at build time.
For native iOS and React Native Bare:
1. Open the app project or workspace in Xcode.
2. Select the main iOS app target.
3. Open Signing & Capabilities.
4. Add Push Notifications.
5. Confirm the Team and Bundle Identifier match the App ID from Step 1.
For React Native Expo:
1. Confirm `expo.ios.bundleIdentifier` matches the App ID.
2. Configure the Sendrealm Expo plugin.
3. Run `npx expo prebuild --platform ios` or create a new EAS build.
4. If the generated native project is committed, open `ios/*.xcworkspace` and verify the main app target has Push Notifications under Signing & Capabilities.
If your app sends silent pushes or background update notifications, enable background remote notifications:
* Native iOS and React Native Bare: add Background Modes in Xcode and check Remote notifications.
* React Native Expo: set `ios.enableBackgroundRemoteNotifications` to `true` in the Sendrealm Expo plugin, then rebuild.
If your app sends rich image notifications, add a Notification Service Extension:
* Native iOS and React Native Bare: add or configure a Notification Service Extension target.
* React Native Expo: set `ios.notificationServiceExtension` to `true`, run prebuild, and rebuild.
### Step 4: Create The APNs Private Key
1. In Certificates, Identifiers & Profiles, open Keys.
2. Click the add button.
3. Enter a clear key name, for example `Sendrealm Push`.
4. Select Apple Push Notification service.
5. Click Configure next to Apple Push Notification service.
6. Choose the environment configuration and key type.
7. Review the configuration.
8. Click Confirm.
9. Download the private key immediately.
Apple saves the private key as a `.p8` file. You can only download that same private key once. If you lose it, create a new APNs key and update Sendrealm.
The APNs key must have Apple Push Notification service selected. A key created only for another Apple service cannot send notifications through APNs. Apple requires the Account Holder or Admin role to create keys.
### Step 5: Choose Team Scoped Or Topic Specific
Apple may let you choose between Team Scoped and Topic Specific APNs keys.
* Team Scoped is simpler for most teams and can be used across apps owned by the same Apple team.
* Topic Specific restricts the key to selected bundle IDs.
Use Topic Specific if your security policy requires tighter app-level restriction. If you choose Topic Specific, select the exact Bundle ID from Step 1. Use Team Scoped if you want the simplest setup.
### Step 6: Find The APNs Key ID
1. Open Certificates, Identifiers & Profiles.
2. Open Keys.
3. Select the APNs key.
4. Copy the key identifier shown below the key name.
This is the Key ID value required by Sendrealm.
### Step 7: Find The Apple Team ID
Open your Apple Developer account membership details and copy the Team ID for the team that owns the app Bundle ID.
The Team ID must belong to the same Apple developer team that owns:
* The App ID
* The Bundle ID
* The APNs key
### Step 8: Upload APNs Values To Sendrealm
In Sendrealm:
1. Open your project.
2. Open **Push Notifications** from the project navigation, next to Domains.
3. Choose iOS or APNs provider settings.
4. Upload the `.p8` file.
5. Enter the Key ID.
6. Enter the Team ID.
7. Enter the Bundle ID.
8. Select the APNs environment.
9. Save the provider.
After saving, initialize the iOS SDK on a physical device and send a test push.
## APNs Sandbox vs Production
APNs has separate sandbox and production environments. The environment must match the build that created the APNs token.
| Build type | APNs environment |
| --------------------------------------- | ---------------- |
| Xcode debug or development-signed build | `sandbox` |
| Production-signed ad hoc build | `production` |
| TestFlight | `production` |
| App Store | `production` |
If the environment is wrong, the app can successfully register a token, but APNs may reject sends for that token.
## iOS Values To Check
Before testing iOS push, confirm:
* Bundle ID in Sendrealm matches the Xcode app target.
* Bundle ID in Sendrealm matches `expo.ios.bundleIdentifier` for Expo apps.
* App ID has Push Notifications enabled in Apple Developer.
* Xcode app target has Push Notifications enabled under Signing & Capabilities.
* Background Modes includes Remote notifications if you send silent/background pushes.
* A Notification Service Extension is present if you send rich image notifications.
* Team ID belongs to the team that owns the Bundle ID.
* Key ID belongs to the uploaded `.p8` key.
* APNs key has Apple Push Notification service enabled.
* Topic Specific APNs key includes this Bundle ID, if you used Topic Specific.
* APNs environment matches the build type.
* The app is running on a physical device.
* The iOS app is installed on a physical device and has completed SDK initialization.
* The user has granted notification permission.
## iOS Common Mistakes
| Mistake | Result |
| -------------------------------------------------------- | --------------------------------------------------------------------------------- |
| Using `sandbox` for TestFlight | APNs rejects production tokens. |
| Using `production` for Xcode debug builds | APNs rejects sandbox tokens. |
| Wrong Bundle ID | APNs sends to the wrong topic and delivery fails. |
| Wrong Team ID | Provider authentication fails. |
| Push Notifications not enabled on the App ID | The app may not receive the proper push entitlement. |
| Push Notifications not enabled in Xcode | The built app is missing the push notification entitlement. |
| Provisioning profile not refreshed after enabling push | Signing can fail or the app can be built without the expected entitlement. |
| APNs key created without Apple Push Notification service | Sendrealm cannot authenticate APNs sends with that key. |
| Topic Specific key does not include the Bundle ID | APNs sends for that app are not authorized by the key. |
| Missing Background Modes, Remote notifications | Silent/background pushes may not be delivered to the app for background handling. |
| Missing Notification Service Extension | Rich images cannot be downloaded and attached before display. |
| Losing the `.p8` file | You must create a new key and update Sendrealm. |
| Testing on simulator | End-to-end APNs testing is unreliable. Use a physical device. |
## Upload In Sendrealm
The exact dashboard labels may vary, but the provider setup follows this shape:
1. Open your Sendrealm project.
2. Open **Push Notifications** from the project navigation, next to Domains.
3. Add or edit the Android provider.
4. Upload the Firebase service account JSON and enter the Android package name.
5. Add or edit the iOS provider.
6. Upload the APNs `.p8` file and enter Key ID, Team ID, iOS Bundle ID, and environment.
7. Save the provider settings.
8. Send a test notification to a development device.
If Sendrealm shows validation errors, check that the files were not renamed into unsupported formats and that pasted IDs do not include extra spaces.
## Test The Full Flow
Credentials are only one half of push setup. The app must also register a token.
For Android:
1. Install the app on a Google Play device or emulator.
2. Initialize the Android or React Native SDK.
3. Request notification permission on Android 13 or newer.
4. Confirm diagnostics show token presence.
5. Send a test push from Sendrealm.
For iOS:
1. Install the app on a physical device.
2. Initialize the iOS or React Native SDK.
3. Request notification permission.
4. Confirm diagnostics show token presence.
5. Send a test push from Sendrealm.
## Delivery Timing Is Best Effort
Credentials let Sendrealm authenticate with Firebase and APNs. They do not guarantee that every notification appears instantly on every device.
After Sendrealm sends a push, final delivery is still affected by:
* Device network connectivity.
* Android Doze and App Standby.
* Android battery optimization and manufacturer-specific background restrictions.
* Android notification channel settings.
* FCM priority and throttling behavior.
* iOS APNs priority.
* iOS Focus, notification summary, and notification settings.
* iOS background update throttling.
* Stale or inactive device tokens.
This means a valid setup can still produce notifications that are delayed, dropped, throttled, collapsed, or hidden by user settings. Test on real devices, check SDK diagnostics, and make sure the app can fetch important state when it opens.
## Rotate Credentials
Rotate provider credentials when a key is exposed, when team access changes, or as part of your security policy.
For Firebase:
1. Generate a new service account private key.
2. Upload the new JSON file to Sendrealm.
3. Send a test push.
4. Delete the old service account key in Google Cloud or Firebase once the new key works.
For APNs:
1. Create and download a new APNs key.
2. Upload the new `.p8`, Key ID, Team ID, Bundle ID, and environment to Sendrealm.
3. Send a test push.
4. Revoke the old APNs key after traffic has moved to the new key.
Do not revoke the old key before confirming the new key works, unless the old key is actively compromised and must be disabled immediately.
## Security Notes
* Never commit Firebase service account private keys.
* Never commit APNs `.p8` files.
* Do not send provider private keys through chat, email, or tickets unless your company has an approved secure process.
* Limit dashboard access to people who need to manage push providers.
* Rotate credentials after employee offboarding if your policy requires it.
* Keep a record of which Firebase project and Apple team belong to each Sendrealm app.
## Official References
* [Firebase Admin SDK service account setup](https://firebase.google.com/docs/admin/setup)
* [Firebase Android app setup](https://firebase.google.com/docs/android/setup)
* [FCM HTTP v1 authorization](https://firebase.google.com/docs/cloud-messaging/send/v1-api#authorize-http-v1-send-requests)
* [Apple APNs authentication tokens](https://developer.apple.com/help/account/capabilities/communicate-with-apns-using-authentication-tokens)
* [Create an Apple private key](https://developer.apple.com/help/account/keys/create-a-private-key)
* [Get an Apple key identifier](https://developer.apple.com/help/account/keys/get-a-key-identifier)
## Related Pages
* [Android SDK](/sdks/android)
* [iOS SDK](/sdks/ios)
* [React Native Expo SDK](/sdks/react-native-expo)
# Push Templates
Source: https://docs.sendrealm.com/tutorials/push-templates
Create localized push templates for broadcasts and automations.
Push templates let you save localized message variants and reuse them in both the dashboard and automation steps.
Push template authoring and lifecycle management are available in the
dashboard. The public API exposes templates for read-only selection and
inspection.
## What a push template stores
* Default locale
* Localized `messages[]`
* Per-locale `title`
* Per-locale `message`
* Optional `launch_url` and `image_url`
## Good uses
* Product announcement broadcasts
* Transactional follow-ups after email or event steps
* Multi-language lifecycle notifications
## Example request
```json theme={null}
{
"name": "Order Delivered Push",
"channel": "push",
"default_locale": "en",
"messages": [
{
"locale": "en",
"title": "Your order arrived",
"message": "Tap to see delivery details.",
"launch_url": "https://app.sendrealm.com/orders/{{order_id}}",
"image_url": ""
},
{
"locale": "pt-BR",
"title": "Seu pedido chegou",
"message": "Toque para ver os detalhes da entrega.",
"launch_url": "https://app.sendrealm.com/orders/{{order_id}}",
"image_url": ""
}
]
}
```
## Related pages
* [List Templates API](/api-reference/endpoint/list-templates)
* [Automations](/tutorials/automations)
# SMTP
Source: https://docs.sendrealm.com/tutorials/smtp
Send email through Sendrealm using SMTP credentials
## SMTP Credentials
* **Host**: smtp.sendrealm.com
* **Port**: 587 (STARTTLS) or 465 (SMTPS)
* **Username**: `smtp` or `smtp:PROJECT_ID`
* **Password**: your API key
With username `smtp`, Sendrealm automatically selects the project that owns the envelope sender (`MAIL FROM`) domain. To select a project explicitly, use `smtp:PROJECT_ID` as the username.
In both modes, the API key must include `email.send`, the key must have access to the resolved project, and the sender domain must belong to that project. Missing, unauthorized, or ambiguously assigned domains are rejected. Existing `smtp` credentials remain valid and require no changes.
# Templates
Source: https://docs.sendrealm.com/tutorials/templates
Create reusable email templates in the dashboard with the visual editor or existing HTML.
Email templates are channel-specific reusable assets that you can use in broadcasts and automations.
## What a template stores
* Name and description
* Draft and published versions
* Subject template and preview text
* Visual editor content or imported HTML, plus rendered HTML/text
## Dashboard workflow
1. Open `Templates > Emails`.
2. Choose **Visual editor** to start from a blank canvas, or **Import HTML** to paste or drop an existing `.html` email template.
3. Continue in the same editor. Imported markup opens as an HTML block with **Preview** and **HTML** views so the original document remains intact and editable.
4. Publish when the template is ready for broadcasts or automations.
5. Restore older versions into a new draft if you want to roll forward from history.
Template authoring, publishing, restoring, and archiving are dashboard-only.
The public API and MCP expose templates as read-only resources so trusted
backends and agents can select published versions without authoring content.
## Related pages
* [Push Templates](/tutorials/push-templates)
* [List Templates API](/api-reference/endpoint/list-templates)
* [List Template Versions API](/api-reference/endpoint/list-template-versions)
# Topics
Source: https://docs.sendrealm.com/tutorials/topics
Manage reusable audience preference topics and subscription actions.
Topics are reusable subscription groups that let you manage preferences separately from audiences.
## Use topics when
* A contact can opt in or out without leaving an audience
* You want automations to subscribe or unsubscribe users from a preference
* You need a stable API resource for notification categories
## Common examples
* `product-updates`
* `weekly-digest`
* `shipping-alerts`
## Subscribe a contact
```bash theme={null}
curl https://api.sendrealm.com/contacts/c671f89b-3ec1-4c58-9ad2-4ef8c2917cda/topics/8c3c4d0e-f7f3-4d7f-92ae-b1498f6a2fa9 \
-X PUT \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"is_subscribed": true
}'
```
## Related pages
* [Topics API](/api-reference/endpoint/topics)
* [Contact Topic Subscription API](/api-reference/endpoint/contact-topic-subscription)
# Web Push Setup
Source: https://docs.sendrealm.com/tutorials/web-push
Configure Sendrealm Web Push and register browser subscriptions with the React SDK.
Sendrealm Web Push uses native browser Push API subscriptions and VAPID keys.
## Requirements
* A Sendrealm Push App with the Web provider active.
* A React, Vite, or Next.js app served over HTTPS. Localhost works for development.
* The Sendrealm service worker served from the same origin as your app.
* A permission prompt triggered from a user gesture, such as clicking an Enable notifications button.
## Activate The Web Provider
Open your Push App provider settings in the dashboard. The Web provider stores Sendrealm-managed VAPID keys. In most apps you do not need to copy these keys manually; the React SDK handles browser setup after initialization.
If keys are missing, click Activate provider. Use Regenerate keys only when you intentionally want browsers to create fresh subscriptions.
## Install The SDK
```bash theme={null}
npm install @sendrealm/react
```
Copy the service worker:
```bash theme={null}
npx @sendrealm/react setup
```
The setup command detects your public directory and writes
`sendrealm-service-worker.js` there. Re-run it after SDK upgrades. Manual copy is
also supported:
```bash theme={null}
cp node_modules/@sendrealm/react/sendrealm-service-worker.js public/sendrealm-service-worker.js
```
## Initialize React
```tsx theme={null}
import { useEffect } from "react";
import { init } from "@sendrealm/react";
export function App() {
useEffect(() => {
void init({
appId: "YOUR_SENDREALM_PUSH_APP_ID",
autoRequestPermission: false,
});
}, []);
return (
<>
{/* your app */}
>
);
}
```
Keep `autoRequestPermission` false unless your UX already guarantees initialization runs from a user action. Browsers can block permission prompts that are not user-initiated.
`init()` is idempotent and safe under React StrictMode duplicate effects. The package also exports `SendrealmProvider` for advanced custom-client cases, but it is not required for normal React, Vite, or Next.js apps.
## Add A Prompt Button
```tsx theme={null}
import { useSendrealmSubscription } from "@sendrealm/react";
export function NotificationButton() {
const { subscribed, optIn, optOut } = useSendrealmSubscription();
return (
);
}
```
After opt-in, the browser is registered with Sendrealm and can be targeted from the dashboard or API.
## Link Signed-In Users
```ts theme={null}
import { getSendrealmClient } from "@sendrealm/react";
const sendrealm = getSendrealmClient();
await sendrealm.login("user_123", "user@example.com");
await sendrealm.addTags({ plan: "pro", locale: "en-US" });
```
You can then target web devices by `device_ids`, `contact_ids`, `external_ids`, `emails`, audiences, or `platforms: ["web"]` from the API.
## Next.js Notes
Call `init()` from a Client Component and put the service worker file under `public/`.
```tsx theme={null}
"use client";
import { useEffect } from "react";
import { init } from "@sendrealm/react";
export function SendrealmInit() {
useEffect(() => {
void init({
appId: "YOUR_SENDREALM_PUSH_APP_ID",
autoRequestPermission: false,
});
}, []);
return null;
}
```
Render `` once near your root layout or app shell.
## Worker Hosting Notes
The browser must load the registered service worker from the same origin as your
app. Do not register `raw.githubusercontent.com`, GitHub Pages, or a CDN URL
directly as `serviceWorkerPath`. If you download the worker from GitHub
Releases, still deploy the file into your app's public directory and register it
as `/sendrealm-service-worker.js`.
## iOS Notes
iOS Web Push works only for installed Home Screen web apps. Your site must be HTTPS, provide a valid web app manifest, and ask for permission from a user gesture inside the installed PWA.
## Full SDK Reference
See [React Web Push SDK](/sdks/react) for hooks, diagnostics, launch URLs, image support, notification event listeners, and the complete client API.