Expo push notifications, sent from Notifly workflows.
Keep Expo's push service. You connect it to Notifly with an Expo access token, register the Expo push tokens your app receives, and the push steps of your Notifly workflows are sent through Expo to those devices.
Notifly adds what Expo's push API leaves to your backend: one trigger for push, in-app, email, SMS and chat; token bookkeeping per user; digest, delay and throttle steps; subscriber preferences checked before each send; and an activity feed with Expo's answer for every device.
What you need from Expo
This is the one field the dashboard asks for when you connect Expo Push, quoted from the create form.
| Field | Required | Stored | Notes |
|---|---|---|---|
| Access Token | Required | Encrypted at rest |
- Access Token. An access token from your Expo account, passed to Expo's server SDK with every push this integration sends.
Connect Expo Push in the dashboard
- Sign in at app.notifly.io, open Integration Store in the sidebar and choose Connect Provider.
- In the Connect Integration sheet, open the Push tab (or search across channels), find Expo Push and choose Connect.
- Pick the environment the integration belongs to. Development and Production keep separate integrations, so you can point each at a different Expo Push account or key.
- Fill in Delivery Provider Credentials with the fields in the table above, then choose Create Integration.
Register a device, then trigger a push
Tokens live on the subscriber, so the trigger only names the user: Notifly sends to every Expo push token that user has registered.
// npm install @notiflyio/api@0.1.26
import { Notifly } from "@notiflyio/api";
const notifly = new Notifly({ security: { secretKey: process.env.NOTIFLY_SECRET_KEY } });
// When your app sends its Expo push token (ExponentPushToken[...]) to your backend:
await notifly.subscribers.credentials.registerToken({
subscriberId: "user_123",
providerId: "expo",
registerSubscriberDeviceTokenRequestDto: { token: expoPushToken },
});
// Later, whenever something happens:
await notifly.trigger({
workflowId: "order-shipped",
to: "user_123",
payload: { orderId: "A-1042", carrier: "UPS" },
});Prefer plain HTTP? The same trigger is POST https://api.notifly.io/v1/events/trigger with an Authorization: ApiKey header and a body of { "name", "to", "payload" }.
What reaches Expo
- A push per token. Title and body from the push step, sent with Expo's server SDK to each registered token, one message at a time.
- Your payload as data. The trigger payload goes in the push's
datafield, with Notifly's message id as__nvMessageId. - Expo's answer. An error ticket fails that device's send with Expo's own message, recorded in the activity feed.
- Clean token lists. A token Expo calls not a valid Expo push token is removed from the subscriber, on by default.
- No token, no call. A subscriber with no Expo token is skipped and recorded in the activity feed.
What Notifly adds on top of Expo
Workflows around the send
One trigger runs a workflow: this provider’s step can sit beside in-app, email, SMS, push and chat steps, behind digest, delay and throttle steps.
Digest notifications →Subscriber preferences, enforced at send
Before each step runs, the subscriber’s workflow and channel preferences are checked; an opted-out step is skipped and the reason is recorded.
An in-app Inbox next to it
The same workflow can write to the Notifly Inbox, a real-time in-app feed you embed with the React component or the JavaScript SDK.
React notification inbox →Per-trigger provider parameters
Anything the trigger passes under overrides.providers.<provider id> is merged into the request Notifly sends to the provider, per workflow or per step.
Activity you can debug
Every message gets execution details in the activity feed, including the response or error the provider returned.
Secrets encrypted at rest
API keys, tokens and service accounts are stored encrypted with AES-256; new and re-saved credentials use authenticated AES-256-GCM. The table above marks which of this provider’s fields that covers.
Go deeper in the docs
Frequently asked questions
What goes in the Access Token field?
An access token from your Expo account. Notifly hands it to Expo's server SDK for every push it sends through this integration, so the field is required. It is stored encrypted at rest.
How do Expo push tokens reach Notifly?
Your backend registers each token on the subscriber with subscribers.credentials.registerToken and provider id expo. Registering the same token twice is a no-op, passing previousToken swaps a rotated token in one call, and when a subscriber goes over the token limit the oldest tokens are dropped. removeToken deletes exactly one token and leaves the others alone.
What happens to tokens Expo rejects?
When Expo answers a push with an error saying the token is not a valid Expo push token, Notifly removes that token from the subscriber; this is on by default. Any other error Expo returns is recorded in the activity feed and the token stays registered.
Does each device get its own push?
Yes. Notifly sends one Expo push per registered token and records each one in the activity feed with the token it went to and the ticket id Expo returned, so one bad token does not hide that the user's other devices received the push.
Can my app tell which Notifly message a push came from?
Yes. The push's data field carries your trigger payload with the Notifly message id added under __nvMessageId, next to the title and body rendered from the push step.
Bring your provider account. Keep your sender reputation.
One POST /v1/events/trigger — email, SMS, push, in-app, and chat. 10,000 events a month, free.