Importing an audience

Bringing subscribers across from another provider — including the part most migration guides leave out.

What actually travels

Push tokens are not owned by your old provider, with one exception. That exception decides whether a migration is painless or partial, so it is worth understanding before you plan around it.

ChannelPortable?Why
Android (FCM)Yes Tokens are issued by your Firebase project. Any provider holding your service account can send to them. Subscribers never notice the switch.
iOS (APNs)Yes Tokens are bound to your Apple team and bundle ID. Same story.
Web pushOnly with the original keys A browser subscription is cryptographically bound to the VAPID key pair that created it. Without that exact pair, every send returns 403 forever.
The web push catch. To keep existing web subscribers you must import the old provider's VAPID private key — and most providers, OneSignal included, do not let you export it. If you cannot obtain it, those users have to visit your site and subscribe again. No product can work around this; anyone claiming otherwise is describing subscriptions that will silently fail.

If you do hold the pair, import it under Settings → Push platforms → Web using Replace with my own keysnot Regenerate, which mints a new pair and disconnects everyone. We verify the two halves are actually a pair before storing them, because a mismatched pair saves cleanly and then fails every single send.

The three steps

Nothing touches your audience until you have seen what will happen. There is no undo for a bad import, so the flow is deliberately not one click.

  1. Stage. Upload a CSV. We parse it into a staging table, detect the format, and propose a column mapping. Your audience is untouched.
  2. Check. We run every row through the mapping and report what would happen — rows to import, rows already known, opt-outs, duplicates, and every rejection with its reason. Still nothing written.
  3. Commit. Rows are written in batches with live progress. Row identity is (import, line number), so an import that stops at row 30,000 resumes there rather than replaying the first 30,000.

Columns

A OneSignal export is detected automatically and its columns mapped for you. Anything else you map by hand; common names are guessed.

FieldNotes
tokenRequired. FCM token, APNs token, or web push subscription JSON.
platformios / android / web, or a OneSignal device_type number. If missing, we infer it from the token's shape — a 64-character hex string is APNs, subscription JSON is web.
external_idYour own user id. Preserve it and your server-side code keeps working unchanged.
tagsA JSON object. Keys are registered in the property catalog on import, so you can segment on them immediately rather than waiting for users to come back.
subscribedOpt-out state. Unsubscribed rows are imported and suppressed — never silently dropped, and never messaged.
Plus first name, last name, email, phone, gender, country, language and timezone.

Rejections

Rows are rejected rather than guessed at. Importing a token that can never be delivered to is worse than skipping it, because it inflates your audience and quietly burns quota.

ReasonFix
No push tokenCheck the mapping — the token column may be named something we didn't recognize.
Unrecognized platformOneSignal device types for SMS and email are not push platforms. Remove those rows.
Country is not a 2-letter codeWe won't truncate Nepal to Ne — that invents data. Convert to ISO codes.
Tags column is not valid JSONMust be a JSON object, e.g. {"plan":"pro"}.

Every rejected row is downloadable as a CSV with its reason and original columns — fix and re-upload. Re-importing is safe: writes are upserts on natural keys, so the same file twice converges instead of duplicating.

How imported tokens get validated

No provider lets you check whether a token is alive without sending to it, so an import cannot verify what it ingests. Your first real send does that, and cleanup is automatic:

Provider saysWhat happens
Unregistered / gone (APNs 410, FCM UNREGISTERED, web 410) Unambiguous — the device is retired immediately.
Wrong VAPID key (web 403 mismatch) Marked invalid. That subscriber must resubscribe.
Invalid argument (FCM) FCM uses this for both a dead token and a malformed payload. We only retire the device if another device on the same channel succeeded in that send — which proves the payload was fine. Otherwise the device is left alone.
That last rule exists because acting on an ambiguous rejection could wipe a healthy audience over a single content bug. Expect your reachable count to drop after the first send to an imported list — that is the dead weight leaving, and it is the number getting more honest, not worse.

Limits

100,000 rows per fileSplit larger exports; imports are additive.
60MB per uploadComfortably covers 100k rows with attributes.
← Message contentAudience filters →