Small SDKs. Clear errors.An API you’ll remember.
Add Perchpush to Flutter, iOS, React Native or the web in a few lines, send from your backend with the REST API or Node.js, and let your AI coding agent do the wiring if you like.
One platform, every stack you ship.
Every SDK speaks the same concepts: an app key, devices, people, events, in-app messages and an inbox. Learn it once, use it everywhere.
Flutter
Pure Dart. Attaches to the firebase_messaging you already use and adds identity, events, in-app messages, an inbox and receipts.
perchpush_flutterFlutter docs iOS (Swift)
A Swift Package with zero dependencies. Register a raw APNs token for direct delivery, or an FCM token if you use Firebase.
Swift Package ManageriOS (Swift) docs Android (Kotlin)
Zero dependencies. Flutter, React Native and web apps on Android are fully supported today; the native SDK is in preview.
Preview · early accessAndroid (Kotlin) docs React Native
TypeScript with no native module. Works beside @react-native-firebase/messaging or expo-notifications.
@perchpush/react-nativeReact Native docs Web
One script tag and a service worker. Push to Chrome, Safari, Firefox and Edge, plus in-app messages and an inbox on your site.
perchpush.jsWeb docs Node.js
A small, typed server SDK for sends, people, events and imports, with idempotency keys and automatic retries on rate limits.
@perchpush/nodeNode.js docs REST API
Plain JSON over HTTPS from any language. Server keys with scopes, clear errors and an Idempotency-Key header.
/api/v1REST API docs Wire it in before your coffee cools.
- Configure with your public app key, attach your push token, and devices register on first launch.
- identify() links a device to a person. Sign the user id on your server with HMAC so nobody can pose as someone else.
- track() feeds segments, journeys and in-app triggers. install and session_start are automatic.
- Send from your server with a template and variables, on any mix of channels.
Perchpush.configure(appKey: 'pk_…');
await Perchpush.attachFirebase(FirebaseMessaging.instance,
onMessageOpenedApp: FirebaseMessaging.onMessageOpenedApp);
await Perchpush.identify(user.id, signature: sig);
await Perchpush.track('lesson_completed');Hand the setup to Claude Code, Cursor, Codex or Copilot.
The dashboard writes a setup brief for your app, with its client key, platforms and connection status filled in. Paste it into your coding agent and it installs the SDK, wires it in and checks that a device registers.
- In the app’s Setup guide, choose “Set up with your AI coding agent” and copy the brief.
- Method names in the brief are checked against the SDK sources, so the agent doesn’t invent APIs.
- Secrets stay out of it: the agent is told to keep server keys and identity secrets on your backend.
Predictable endpoints, honest errors.
Two kinds of keys
A public client key (pk_) for apps and websites can only register devices and report their own events. Server keys (sk_) stay on your backend, are stored as a hash, shown once and rotate instantly.
Scopes and allowlists
Create a named key for each service with only the scopes it needs (send, read, users) and an optional IP allowlist.
Clear errors
Errors are JSON with a plain message and a status code: 400, 401, 402 when the month’s sends are used up, 404, 409 or 429.
Rate limits by plan
From 120 calls a minute on Starter to 5,000 on Business. See plan limits.
POST /notifications | Send now, schedule, local time or best hour. Safe to retry with an Idempotency-Key. |
|---|---|
POST /notifications/:id/pause | Stop further batches; resume or cancel later. |
POST /users | Create or update a person with email, phone and typed attributes. |
POST /users/:id/events | Record a server-side event, with optional revenue. |
DELETE /users/:id | Erase a person, their devices, events, logs and inbox. |
POST /import | Upsert up to 10,000 people in one call. |
GET /messages | The delivery log, with the raw provider response for each attempt. |
Events to your server, signed so you can trust them.
Pick the events you want and Perchpush posts them as JSON. Failed deliveries retry with backoff over about 15 hours, and an endpoint pauses after 50 failures in a row.
campaign.sentnotification.openeddevice.registeredcontact.unsubscribedevent.trackedpurchaselink.clickedinstall.attributedinapp.clickedjourney.completedPrefer a chat message? Choose Slack, Discord, Telegram or Microsoft Teams as the format and get a readable line instead of JSON. Webhooks in the docs.
t=1762500000,v1=5f2b…c9e1
// v1 = hex(HMAC-SHA256(secret, t + "." + body))
// Same pattern as Stripe: check v1, then reject
// old timestamps to stop replays.When something fails, you see why.

Raw provider answers
Every attempt is logged with the exact reply from Apple, Google or the browser, on the delivery log, device and person pages.

Explain with AI
One click turns a cryptic error code into a plain-language fix.

Dead tokens cleaned up
Uninstalled apps and expired subscriptions are removed automatically and recorded as uninstalls.
Developer questions.
Does the Flutter SDK replace firebase_messaging?
No. It is pure Dart and attaches to the firebase_messaging your app already uses, then adds identity, events, in-app messages, an inbox and receipts.
Is there a native Android SDK?
A Kotlin SDK with zero dependencies is in preview; email us for early access. Android apps built with Flutter, React Native or the web are fully supported today, and any native app can call the REST SDK endpoints directly.
Can I send from my own backend?
Yes. Use the REST API or the Node.js SDK with a server key. Named keys can be limited to the send, read or users scopes and to an IP allowlist, and an Idempotency-Key header makes retries safe.
How do I verify webhooks?
Each request carries a signature header in the form t=<unix time>,v1=<hex HMAC-SHA256 of "t.body">, signed with your endpoint secret, the same pattern Stripe uses.
Ship your first push
this afternoon.
Create an app, upload your Firebase key and follow the guided setup, or paste the brief into your coding agent.


