Perchpush
For developers

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.

A few lines

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.
lib/main.dart
Perchpush.configure(appKey: 'pk_…');
await Perchpush.attachFirebase(FirebaseMessaging.instance,
    onMessageOpenedApp: FirebaseMessaging.onMessageOpenedApp);

await Perchpush.identify(user.id, signature: sig);
await Perchpush.track('lesson_completed');
Set up with your AI coding agent

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.
REST API

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.

A few server endpoints (base URL /api/v1)
POST /notificationsSend now, schedule, local time or best hour. Safe to retry with an Idempotency-Key.
POST /notifications/:id/pauseStop further batches; resume or cancel later.
POST /usersCreate or update a person with email, phone and typed attributes.
POST /users/:id/eventsRecord a server-side event, with optional revenue.
DELETE /users/:idErase a person, their devices, events, logs and inbox.
POST /importUpsert up to 10,000 people in one call.
GET /messagesThe delivery log, with the raw provider response for each attempt.

Full REST reference in the docs

Webhooks

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.completed

Prefer 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.

Perchpush-Signature header
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.
Debugging

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.

FAQ

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.

Free to start

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.