Public Notify API
Endpoint Summary
Section titled “Endpoint Summary”- Base URL:
https://api.notificator-project.com - Resource:
/on the public API domain - Primary method:
POST
Supported methods:
POSTcreate and dispatch an external notificationGETreturn endpoint metadata (or OpenAPI with?format=openapi)OPTIONSCORS preflight
OpenAPI document:
GET https://api.notificator-project.com?format=openapi
Authentication
Section titled “Authentication”Provide exactly one API key using any of these headers:
Authorization: Bearer wpnotif_...X-API-Key: wpnotif_...X-WPNOTIF-Key: wpnotif_...
Key type policy:
- Allowed:
public_client,internal_service - Rejected:
wordpress_server,strapi_server
Domain policy:
- If a key has
allowed_domains, requestOriginorRefererhost must match. - Requests without
OriginorRefererare accepted for server-to-server traffic. localhostand127.0.0.1are always accepted for local testing.
Request Contract
Section titled “Request Contract”Content types accepted:
application/jsonapplication/x-www-form-urlencodedtext/plain
Minimum payload requirement:
- A request must include at least one meaningful notification field.
- Valid examples:
title,body,message,category,severity, non-emptypayload, or non-emptydata. - Requests that only include control flags (for example only
sendPush) return400.
Request fields
Section titled “Request fields”| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
title | string | No | External Notification | Trimmed to 140 chars. |
body | string | No | "" | Trimmed to 2000 chars. |
source | string | No | third_party | Trimmed to 200 chars. |
category | string | No | info | Normalized to info, task, promo. |
severity | string | No | null | Normalized to info, warning, error, critical or omitted. |
sendPush | boolean | No | true | Controls Expo push send attempt. |
sendEmail | boolean | No | account preference | Overrides email delivery for this request. |
sendMqtt | boolean | No | true | Controls MQTT publish step. |
strictDelivery | boolean | No | false | When true, MQTT failures return 502 (fail-fast). When false, MQTT failures are reported as partial success (200). |
deviceId | string | No | all active devices | Sends MQTT only to one device when provided. |
mqttQos | number | No | 1 | Valid values: 0, 1, 2. |
mqttConnection | object | No | environment | Use { "mode": "custom" } with mqttConfig for request-scoped HiveMQ Cloud credentials. |
mqttConfig | object | No | none | Validated HiveMQ Cloud WSS credentials. The API uses them for this request and does not persist them. |
payload | object | No | {} | Preferred metadata object merged into downstream data. |
data | object | No | {} | Additional metadata object merged into downstream data. |
Any additional top-level fields are preserved and merged into internal data.
Normalization Rules
Section titled “Normalization Rules”Incoming payloads are normalized for common webhook formats:
subject->titledescriptionortext->bodyservice->source- JSON string values in
payloadanddataare auto-parsed into objects categoryandseverityresolution precedence: top-level ->payload->data
Example Requests
Section titled “Example Requests”JSON webhook
Section titled “JSON webhook”curl -X POST "https://api.notificator-project.com" \ -H "Authorization: Bearer wpnotif_YOUR_PUBLIC_CLIENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject": "Build Failed", "description": "CI pipeline failed on deploy.", "service": "github_actions", "severity": "error", "payload": { "workflow": "deploy.yml", "branch": "main" } }'Form-encoded webhook
Section titled “Form-encoded webhook”curl -X POST "https://api.notificator-project.com" \ -H "Authorization: Bearer wpnotif_YOUR_PUBLIC_CLIENT_KEY" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "subject=Disk Space Alert" \ --data-urlencode "description=Node reached 92% disk usage" \ --data-urlencode "service=infra_monitor" \ --data-urlencode "payload={\"host\":\"api-1\",\"disk\":92}"Plain-text webhook
Section titled “Plain-text webhook”curl -X POST "https://api.notificator-project.com" \ -H "Authorization: Bearer wpnotif_YOUR_PUBLIC_CLIENT_KEY" \ -H "Content-Type: text/plain" \ --data "Payment provider timeout on checkout"Strict delivery request (fail-fast MQTT)
Section titled “Strict delivery request (fail-fast MQTT)”Use this mode when your caller must treat MQTT delivery as mandatory.
curl -X POST "https://api.notificator-project.com" \ -H "Authorization: Bearer wpnotif_YOUR_PUBLIC_CLIENT_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Queue Backlog High", "body": "Order queue is above threshold.", "source": "erp_worker", "sendMqtt": true, "strictDelivery": true, "payload": { "queue": "orders", "pending": 182 } }'Success Response
Section titled “Success Response”By default (strictDelivery: false), MQTT publish failures do not fail the whole request. The endpoint returns 200 with ok: true plus MQTT warning fields.
{ "ok": true, "kind": "external_notification", "stored": true, "payloadPreview": { "type": "external_notification", "title": "Queue Backlog High", "body": "Order queue is above threshold.", "source": "erp_worker", "category": "task", "severity": "warning", "dataKeys": ["queue", "pending", "cluster"] }, "pushSent": true, "pushAttempted": 1, "pushEnabled": true, "emailEnabled": false, "mqttPublishedCount": 1, "mqttFailedCount": 0, "mqttSkipped": false, "mqttError": null, "warnings": [], "mqttEnabled": true, "timestamp": "2026-03-29T12:00:00.000Z"}Partial success example (MQTT failure)
Section titled “Partial success example (MQTT failure)”{ "ok": true, "kind": "external_notification", "stored": true, "pushSent": true, "pushAttempted": 1, "pushEnabled": true, "mqttPublishedCount": 0, "mqttFailedCount": 1, "mqttError": "Publish failed", "warnings": ["mqtt_publish_failed_partial"], "mqttEnabled": true, "timestamp": "2026-03-29T12:00:00.000Z"}Success fields
Section titled “Success fields”| Field | Type | Description |
|---|---|---|
ok | boolean | true when request was processed. |
kind | string | Always external_notification. |
stored | boolean | Whether encrypted notification was stored. |
storeReason | string | Included when stored is false. |
payloadPreview | object | Sanitized preview of normalized payload. |
pushSent | boolean | At least one push token succeeded. |
pushAttempted | number | Number of push tokens attempted. |
pushEnabled | boolean | Reflects request-level sendPush. |
emailEnabled | boolean | Whether email delivery was enabled for this request. |
emailSent | boolean | Whether the configured email provider accepted the alert. |
mqttPublishedCount | number | Number of successful MQTT publishes completed. |
mqttFailedCount | number | Number of MQTT publish failures in the request. |
mqttSkipped | boolean | true when no active MQTT targets were available. |
mqttSkipReason | string | Included when MQTT was skipped. |
mqttError | string | First MQTT error message when one or more publishes fail. |
warnings | string[] | Warning codes for partial-success outcomes (for example mqtt_publish_failed_partial). |
mqttEnabled | boolean | Reflects request-level sendMqtt. |
timestamp | string | Server timestamp in ISO-8601 format. |
Hosted service
Section titled “Hosted service”The Public Notify API is operated by the Notificator Project. Integrations only
need a public_client key and always send requests to the canonical endpoint.
The hosted service owns the protected infrastructure credentials required for
the official mobile app, including Expo push security.
Do not request, copy, or embed Expo, Supabase, email-provider, or platform MQTT
credentials in an integration. Node.js projects can use
@notificator-project/api, which is a server-side client for the hosted API.
Error Responses
Section titled “Error Responses”| HTTP | Example error | Meaning |
|---|---|---|
400 | Invalid request body | Body could not be parsed. |
400 | Request payload is empty | No meaningful notification fields were provided. |
401 | Authorization required | No auth header/key supplied. |
401 | Invalid API key | Key missing, revoked, or unknown. |
401 | API key type not allowed for this endpoint... | Key type is not public_client or internal_service. |
401 | Origin is not allowed for this API key | Domain policy denied request. |
401 | Authentication service unavailable | Backend key validation service not configured/available. |
404 | Device not found for user | Provided deviceId does not belong to key owner. |
409 | Device is inactive or paused | Target device exists but is not publishable. |
502 | MQTT publish failed | Returned only when strictDelivery=true and MQTT publish fails. |