OneSignal — Source
Source — Vendo imports subscriber profiles, sent notifications, and audience segments from OneSignal for analytics.
OneSignal is also available as a destination.
What Vendo Imports
Vendo extracts the following streams from the OneSignal REST API:
| Stream | Description |
|---|---|
| Profiles | Device/subscription records with tags, push tokens, and external user IDs |
| Notifications | Sent push, email, and SMS messages with per-message delivery and engagement stats |
| Segments | Audience segment definitions with filter criteria and subscriber counts |
Profiles Stream
Source: GET /players
Each row represents a device/subscription with:
id— OneSignal player ID (primary key)external_user_id— your app’s user ID (cross-device join key)identifier— push token, email address, or phone numbertags— your custom profile properties (JSON object)- Device info:
device_os,device_type,device_model,language,timezone - Activity:
last_active,session_count,amount_spent,playtime - Location:
country,lat,long
Tags are serialized as a JSON string in BigQuery — use JSON_EXTRACT_SCALAR or JSON_VALUE to query specific properties.
Notifications Stream
Source: GET /notifications
Metadata and delivery stats for every push/email/SMS sent from OneSignal:
id,name,contents,headings- Targeting:
included_segments,excluded_segments,filters - Scheduling:
send_after,completed_at,queued_at - Stats:
successful,failed,errored,converted,remaining platform_delivery_stats— per-platform delivery breakdown (iOS / Android / web)
Segments Stream
Source: GET /apps/{app_id}/segments
Audience segment definitions including:
id,name,read_onlyfilters— the filter expression tree (tag matchers, last-session, etc.)- Creation and update timestamps
Authentication
OneSignal uses two credentials for REST API access:
- App ID — UUID identifying your OneSignal app
- REST API Key — private key authorizing server-side API calls
Auth header: Authorization: Basic <REST_API_KEY>
Both values are found in the OneSignal dashboard under Settings → Keys & IDs.
Setup
- In the Vendo app, navigate to Apps and click Add App
- Select OneSignal from the integration catalog
- Enter your App ID (UUID) and REST API Key
- Vendo validates the credentials against the OneSignal API (
GET /apps/{app_id}) - Once connected, create a source and choose which streams to enable:
- Profiles (default)
- Notifications
- Segments
Backfill & Incremental Behavior
Streams are classified by how backfill and incremental sync treat them:
| Stream | Backfill (historical load) | Incremental (scheduled sync) |
|---|---|---|
| Profiles | All subscribers, full snapshot — fetched once on chunk 1 of the backfill. | Full snapshot on every run. Every id is re-read and MERGEd — tag or attribute changes always land in BigQuery. |
| Segments | All segments, full snapshot — fetched once on chunk 1 of the backfill. | Full snapshot every run. |
| Notifications | Only notifications queued within the backfill range — queued_at ∈ [start, end] per chunk. | queued_at >= last successful sync. |
Why profiles is full-snapshot on every sync
OneSignal’s /players endpoint does not expose a reliable updated_at
field. The closest proxy is last_active, but it only changes when the
subscription is active (app opens, notification delivery, session
starts) — pure server-to-server tag updates to inactive subscribers can
leave last_active unchanged. To guarantee every tag/attribute change
lands in BigQuery, the connector re-fetches the full player list on every
run and MERGEs by id.
Cost implications:
- The
/playersAPI cost is identical with or without a watermark filter (OneSignal has no server-side date filter on this endpoint), so there’s no incremental savings to be had at the API layer. - BigQuery write cost scales with your subscriber count. For accounts
under ~100k subscribers this is negligible. For accounts with millions
of subscribers, a smarter path is needed — OneSignal recommends their
CSV export endpoint (
POST /players/csv_export) for bulk exports. Not yet implemented; reach out if you need it.
Notifications pagination early-terminates
Because OneSignal’s /notifications endpoint returns rows in
reverse-chronological order by queued_at, pagination stops as soon as
the API returns a row older than the requested start_time. A 30-day
backfill window pages through ~30 days of notifications, not the entire
account history.
Platform Details
| Setting | Value |
|---|---|
| Sync Method | Server-side via OneSignal REST API |
| Default Frequency | Daily (1440 min) |
| Backfill Chunk | 30 days (not used for full-snapshot streams) |
| Rate Limit | ~60 req/min (client self-throttles at 1 rps) with 429 backoff |
| Pagination | offset + limit — 300 for players, 50 for notifications/segments |
Known Limitations
- The
/playersendpoint does not support server-sideupdated_sincefiltering, so incremental mode still fetches the full list each run. For apps with >1M subscribers, consider using OneSignal’s CSV export (not yet implemented by this connector). - The new OneSignal User Model (
/apps/{app_id}/users) has no bulk list endpoint, so the connector uses the legacy/playersendpoint. Apps that have fully migrated to the User Model can still read devices via/players— it returns one row per subscription. - Nested fields (
tags,filters,platform_delivery_stats) are stored as JSON strings because BigQuery autodetect cannot infer a stable schema when tag shapes vary across rows.
Verify Setup
- After connecting, check the app status shows Active
- Trigger a manual sync and wait for the job to complete
- In your Vendo BigQuery dataset, query:
SELECT COUNT(*) FROM `{dataset}.onesignal_{conn_id}_profiles`; SELECT COUNT(*) FROM `{dataset}.onesignal_{conn_id}_notifications`; SELECT COUNT(*) FROM `{dataset}.onesignal_{conn_id}_segments`; - Inspect tag properties with:
SELECT id, JSON_VALUE(tags, '$.plan') AS plan FROM `{dataset}.onesignal_{conn_id}_profiles` WHERE tags IS NOT NULL LIMIT 10;
Troubleshooting
401 Unauthorized
Cause: Incorrect REST API Key or App ID. Solution: Copy the exact values from Settings → Keys & IDs — both need to belong to the same OneSignal app.
”App not found” (404)
Cause: The App ID doesn’t match any OneSignal app accessible by the key. Solution: Confirm the App ID UUID matches the one shown in the dashboard.
Missing tags
Cause: Players created before tag fields existed won’t have them.
Solution: Expected — filter with tags IS NOT NULL when querying.