Skip to main content
Voyado’s App Push API enables your mobile app to send native push notifications (APNs on iOS, FCM on Android) to your customer’s mobile device through Customer Engagement. It also reports on which devices your customers are using, and lets your app report back on what happened to a push after it was sent, whether it was delivered, opened or dismissed. That engagement can then be used in automations and shown in analytics. Here you will learn how to integrate with the App Push API. This is intended for:
  • Mobile engineers (iOS or Android) integrating push notifications into an app
  • Backend engineers building a server that proxies push registration for a mobile app

Base path

Each endpoint in the App Push API uses a base path URL which is unique to your Customer Engagement environment. The value you’ll use can be found on Config Hub.

Show me about Config Hub

Your base path URL will be referred to as <base-path> from this point on.

Authentication

Every call to the App Push API requires a Bearer token:
Authorization
string
required
Identifies your app to Customer Engagement. Passed as a Bearer token. You will set this in Config Hub as part of configuring push settings.
The PublicApiKey is best thought of as an identifier for your app, and not a secret to be protected. It ships inside your compiled app binary, so it can be found by decompiling your IPA/APK. But that is fine - the key is write-only and scoped to registering devices and reporting events for one specific app configuration. It cannot read, modify, or delete any other tenant’s or app’s data. Treat it how you’d treat any other client-visible app identifier.
If you’d rather avoid shipping this identifier inside your app at all, see Backend-mediated integration below.

The endpoints

There are three endpoints and you use your base path to build the URLs like this: In each case, insert your own version of the base path. Here are the endpoints in more detail:
Used to register a device to a certain contact or update its record. The JSON payload contains the attributes:
  • platform
  • push_token
  • contact_id
  • app_version?
  • os_version?
  • device_model?
  • locale?
  • timezone?
Example call
Used to stop a certain device from receiving pushes, for example on logout or opt-out. The JSON payload contains the attributes:
  • push_token
Example call
Used to report what happened when a push arrived or was interacted with. Sent as an “events” array of JSON objects:
  • type
  • message_id
  • contact_id
  • recipient_id
  • occurred_at
  • app_state?
  • deeplink?
  • action_id?
Example call

Failure modes

Core concepts

Here are some core concepts for working with the App Push API.

1. An installation is a device

An “installation” is a single app install on a single device. It is identified solely by its push token (the APNs device token or FCM registration token). If the push token changes, the installation should be updated.

2. Binding a contact

The contact_id is the existing Customer Engagement contact identifier for the signed-in user. Registering an installation with a contact_id binds that device to that contact. Customer Engagement can then send targeted pushes to it.

3. Registration is idempotent

Calling the register endpoint with the same push token twice doesn’t create a duplicate, it just updates the existing record (for example by giving a new contact_id or refreshed device metadata).

Integration guidance

This section describes how to use the API. These are the patterns every integration should follow.

1. Authenticate first

Only call the register endpoint once you know, with certainty, who the current user is — that is, you have a valid contact_id from your own app’s authentication/session system.
Voyado does not know or derive your contact identity; your app must supply it. Registering a push token using the wrong (or a stale) contact_id means personalized pushes could go to the wrong person, so this ordering matters: confirm identity first, then register.

2. Register early

Register the device as early as possible in your app’s lifecycle but only when both of these conditions are met:
1

The user is authenticated

You have their contact_id from your own authentication system.
2

Notification permission has been granted

This condition is implicit: you cannot obtain a push token from the OS at all until the user has granted notification permission, so simply having a token in hand already satisfies this.
In practice this usually means to request notification permission at an appropriate point in your onboarding flow, and as soon as you have both a push token and a signed-in user, call register. For most apps that’s at app launch, if already logged in or immediately after login.

3. Minimize redundant calls

Registration is idempotent and safe to call repeatedly, but you should still avoid calling it more than necessary. So you should:
  • Cache the last successfully registered (push_token, contact_id) pair locally on the device
  • Only call register again when either value changes, such as when the push token rotates, the user logs in as a different contact, or you haven’t registered yet at all.
  • Don’t call register “just in case” on every single app launch if neither value has changed since your last successful call. Doing this will not break anything, but it creates unnecessary network traffic and battery cost.

4. Unregister on logout

When the user logs out, call the unregister endpoint along with the device’s current push token:
This is the recommended way to fully remove the installation from Customer Engagement. If the same device is used to log back in later (by the same or a different contact), your app should call the register endpoint again with the current push token and the newly authenticated contact_id. As in, a completely fresh registration.
Also call the unregister endpoint whenever a user explicitly opts out of push notifications in your app’s settings, or when you detect that OS-level notification permission has been revoked.

Endpoints in detail

Here is a more detailed run-down of the three endpoints mentioned above and how they are used.
Important points:
  • All requests and responses attribute names use JSON with snake_case field names.
  • All endpoints use the same base path and require the Authorization: Bearer <PublicApiKey> header

Register installation

The endpoint is:
Register endpoint
This creates or updates an installation. This call is idempotent, which means it is safe to call every time your app has a current push token and a signed-in contact, without checking whether the device is already registered.
The following attributes can be used:
string
required
This will be “ios” or “android”.
string
required
The APNs device token or FCM registration token. This is the installation’s identity.
string
required
Your Voyado contact identifier for the signed-in user.
string
Your app’s version string. (See note below.)
string
Device OS version. (See note below.)
string
Device model identifier. (See note below.)
string
Device locale, for example en-US. (See note below.)
string
IANA timezone, for example Europe/Stockholm. (See note below.)
app_version, os_version, device_model, locale, and timezone are metadata that Voyado does not currently use for any targeting, filtering, or business logic. It is recommended to send them anyway as they are likely to power future capabilities (such as minimum-OS-version rules or locale-aware send scheduling), and it costs you nothing to include them now rather than adding them retroactively later.
This is an example request for tenant “acme” (using a likely value for <host>):
Request details
The payload:
Registering an installation
A successful request gives a HTTP 202 Accepted response with an empty body.

Unregister installation

The endpoint is:
Register endpoint
This entirely removes the installation identified by the push token sent. Use this on logout and when the user explicit opts out.
The push token is sent in the request body, not in the URL. A push token is a sensitive value and should never appear in a URL path, since URLs are logged by proxies, browsers, and monitoring tools far more readily than request bodies.
string
required
The push token identifying the installation that is to be removed.
Request details
The payload:
Registering an installation
A successful request gives a HTTP 202 Accepted response with an empty body.

Report events

An engagement events describes what happened to a push after it was sent. The endpoint to send one or a batch of events:
Report events endpoint
Events are validated as a whole batch before any of them are accepted. If any event in the batch is invalid, the whole batch is rejected.
Events request body
string
required
One of delivered or opened or dismissed - See “Event types” below for more details.
string
required
Echoed back from the push payload your app received.
string
required
Echoed back from the push payload your app received.
datetime
required
When the event happened, from the device’s clock. ISO-8601 format.
string
required
The Voyado contact this event relates to.
string
This will be “foreground”, “background”, or “killed”, which is the app’s state when the event occurred.
Echoed from the push payload, if the notification carried one and the user tapped it.
string
The identifier of a custom notification action button the user tapped, if the notification included custom actions and tapping one opened the app. Reported alongside opened.
Every push Voyado sends includes both a message_id and recipient_id in its payload specifically so your app can echo it back on every event. This is how Voyado correlates “delivered” and “opened” events with the original send. Consult your platform’s push payload documentation for exactly where this value appears in the payload your app receives.
Reporting a batch of events
The payload:
The events
A successful request gives a HTTP 202 Accepted response:
Every error from every endpoint uses the same envelope:
Error response
The request_id value uniquely identifies the request server-side; include it when contacting support about a specific failed call.
What the delivered event is designed to mean is that your app push has “reached” the user, and that it is now possible for them to see it (think of an email reaching an inbox). However the notification permissions on a user’s device can vary wildly. For example, a user may allow pushes but choose to show them not as a banner but as a red notification badge on the app icon. Therefore it is hard to give exact guidance on when you should send the “delivered” event and it is up to you to implement it in a way that works for you.

Sending a push

Here are example payloads for sending a push on Android and on iOS.

Migrating from another provider

If you’re currently sending push notifications through a different push provider and want to move to Voyado, it’s recommended to follow a gradual, dual-provider transition rather than a sudden total cut-over.
This works best when your app’s implementation can actually support running two providers side by side. So check that first. Some existing push SDKs register their own OS-level callbacks (such as UNUserNotificationCenterDelegate on iOS or FirebaseMessagingService on Android) and don’t forward those callbacks anywhere your own code can intercept them, which can make it difficult or impossible to also wire up Voyado registration and event reporting alongside them.Only your app’s developers can assess whether your current setup allows for this. If it doesn’t, talk to your Voyado contact about alternative migration approaches.
1

Integrate both providers side by side

Add Voyado registration (this API) to your app alongside your existing provider’s SDK. Your app now registers with both providers whenever a user authenticates.
2

Let registrations accumulate naturally

As your existing users open the app over the following days and weeks, each one registers with Voyado automatically — no forced re-login, no push notification required to trigger it, no big migration event. Coverage grows organically with normal app usage.
3

Decide when to cut over

How many registered contacts is “enough” to switch is entirely a business decision on your side — Voyado doesn’t enforce or suggest a threshold. Once you’re satisfied with coverage, you cut over.
4

Changing where you trigger sends from

Registering a device with Voyado never causes a push to be sent, this must still be explicitly done. This means that running both providers’ registration side by side during the transition does not risk duplicate pushes on its own.
5

Remove the legacy SDK (optional)

Do this when you’re fully cut over and confident that you no longer need the legacy SDK.
You should not send pushes from both the old provider and from Voyado at the same time during the transition. Doing this creates a risk of sending the push twice.

Backend-mediated integration

Not every customer wants their mobile app talking to Voyado directly. If you’d rather route push registration and event reporting through your own backend, that’s fully supported. In this case your backend just calls the same API as discussed above on your app’s behalf. Important points to consider are:
  • Your backend calls the exact same Voyado endpoints (register, unregister, events) as those described above, with the exact same fields.
  • Your backend can supply contact_id itself when calling Voyado, since it already knows which of your own users is making the request (via your existing session/auth system), Your mobile app only needs to hand its push token to your backend, and not to Voyado directly.
  • The key never ships inside your distributed app binary where it could be extractable by unpacking the IPA/APK. This is a meaningful security advantage. If keeping the key off-device matters to you, this pattern is worth the extra implementation effort.
Everything else in this guide — when to register, when to unregister, the migration approach — applies in the backend-mediated case. It’s only who makes the HTTP call to Voyado that changes.