Skip to main content

OneSignal Push Notification API

This application provides a wrapper for the OneSignal REST API.

Available Endpoints

Currently, the application exposes two endpoints for sending push notifications:

  • Create notification
  • Retrieve delivery status

Authentication

Endpoints are secured using JWT (JSON Web Token) authentication. This is already implemented in the Aleteia platform.

Refer to this example for implementation.

The payload should contain only the application_id, and you must include the exp claim (short expiration, e.g., 1–2 minutes) to prevent replay attacks.

The JWT must be sent in the Authorization header prefixed with Bearer. Example here.

Create Notification

POST https://reports.aleteia.org/push_notifications/:application_id/create

Parameters (as JSON):

{
"notification": {
"title": "Notification Title",
"message": "Test Notification",
"link": "http://example.com",
"image": "http://placehold.it/256x256?text=Icon",
"web_image": "http://placehold.it/1024x768?text=Big+Image",
"locale": "it"
}
}

Response

HTTP 201 with JSON:

{
"id": 2,
"message": "Some message",
"link": "http://example.com",
...
}

Error: HTTP 422 (validation) or HTTP 403 (auth error).

Delivery pipeline

A create with delivery_type: all and a link is stored as two rows, one app and one web, so the response is an array rather than a single object. Each row is handed to OneSignalDeliveryJob once its transaction has committed — enqueuing earlier made the Sidekiq worker resolve the job's GlobalID on its own connection before the insert was visible and fail with ActiveRecord::RecordNotFound, delaying delivery to the retry.

Every row carries an idempotency_key generated at creation and sent to OneSignal, so a retried delivery of the same row cannot push twice.

The endpoint is not idempotent for the caller

The key protects a row, not a request. Two POSTs carrying the same publication are two independent notifications with two different keys, and OneSignal delivers both — as happened on 2026-09-07, when fr.aleteia.org posted post_id 1117083 twice 11 seconds apart and every recipient got the push twice. Callers must send one request per publication — that one came from the WordPress form being submitted twice, tracked in issue #1015.

Unlike the /scrape webhook, which WordPress fires again on 25% of posts as they are re-saved, this endpoint is reached once per publication in 98% of cases: over the 15 days of log retention only that single publication repeated, out of 59.

Retrieve Notification Status

GET https://reports.aleteia.org/push_notifications/:id

Response format:

{
"id": 5,
"title": "Notification Title",
"message": "Final development test",
...
"full_status": {
"delivery_status": "completed",
...
}
}

App Management & v2 Key Provisioning

The application maintains a local mirror of OneSignal apps (OneSignalApplication records). Each app stores a single v2 API key (v2_api_key), provisioned via the OneSignal Organization API and stored with Active Record encryption. The legacy v1 REST key (basic_auth_key) and its client have been removed.

Synchronization

OneSignalApplication.synchronize pulls the current app list from the OneSignal Organization API, filters to apps matching the current environment (production apps in production, staging/other apps elsewhere), and upserts them locally. New apps get a v2 key provisioned automatically during creation. The sync runs hourly via the OneSignalAppImportJob cron job.

Required ENV Variable

The Organization API requires ONE_SIGNAL_ORG_KEY — an org-level key distinct from the per-app keys.