Message API
The Message API sends top-level transient notifications. Use it for alerts, completion messages, image snapshots, price notifications, and other content that does not need later updates or closing.
Endpoint
Section titled “Endpoint”POST /messageThe request body must be JSON. Unknown extension fields are ignored for forward compatibility; known fields that are forbidden for an action are still rejected. If a private Gateway enables PUSHGO_TOKEN, include Authorization: Bearer <token>.
Headers
Section titled “Headers”| Header | Required | Description |
|---|---|---|
Content-Type: application/json | Yes | Request body format. |
Authorization: Bearer <token> | Gateway-dependent | Required only when a private Gateway enables PUSHGO_TOKEN. |
Request Fields
Section titled “Request Fields”| Field | Type | Required | Description |
|---|---|---|---|
channel_id | string | Yes | Target channel ID. |
password | string | Yes | Channel password; trimmed before validation, then 8-128 bytes. |
title | string | Yes | Message title, must not be empty. |
body | string | No | Message body, Markdown is supported. |
op_id | string | No | Idempotency key, 1-128 chars, letters/digits/_/:/-. |
thing_id | string | No | Scope the message to a Thing ID; 1-64 chars, letters/digits/_/:/-. The Gateway validates the format but does not require a server-side Thing record. |
occurred_at | number or numeric string | No | Unix seconds or milliseconds accepted and normalized to milliseconds. Required when thing_id is present. |
severity | string | No | critical, high, normal, low; unknown values normalize to normal. |
ttl | number or numeric string | No | Expiration time; Unix seconds or milliseconds accepted. Provider TTL is capped at 30 days. |
url | string | No | Optional click-through URL. |
images | string[] | No | Up to 32 image URLs, max 2048 bytes each. |
tags | string[] | No | Up to 32 tags, max 64 bytes each, trimmed and deduplicated. |
ciphertext | string | No | Optional E2EE ciphertext payload. |
metadata | object | No | Custom scalar key-values; key <= 64 bytes, non-empty scalar text <= 512 bytes; nested objects, arrays, and null are rejected. |
message_id is generated by the Gateway and is rejected if supplied. Because unknown extension fields are ignored, use the documented names carefully: a misspelled field is not applied.
Severity Mapping
Section titled “Severity Mapping”severity | APNs interruption level | FCM priority |
|---|---|---|
critical | critical | HIGH |
high | time-sensitive | HIGH |
normal | active | HIGH |
low | passive | NORMAL |
Minimal Example
Section titled “Minimal Example”curl -X POST https://gateway.pushgo.dev/message \ -H "Content-Type: application/json" \ -d '{ "channel_id": "YOUR_CHANNEL_ID", "password": "YOUR_CHANNEL_PASSWORD", "title": "Backup completed", "body": "The daily NAS backup has finished.", "severity": "normal" }'Associate with a Thing
Section titled “Associate with a Thing”If the alert belongs to a persistent entity, pass thing_id and an explicit occurred_at.
{ "channel_id": "YOUR_CHANNEL_ID", "password": "YOUR_CHANNEL_PASSWORD", "thing_id": "8a1fc4b3d9f04fd2857f92f66f7cc5d1", "occurred_at": 1713750000000, "title": "Home NAS disk warning", "body": "volume1 usage has reached 92%.", "severity": "high", "tags": ["nas", "disk"]}Success Response
Section titled “Success Response”If you provide op_id, repeating it with the same normalized payload and scope returns the original result. Reusing it with a different payload or scope returns 409. If omitted, the Gateway generates it.
{ "success": true, "data": { "op_id": "00191f23cc000-0123456789abcdef0123456789abcdef", "message_id": "8a1fc4b3d9f04fd2857f92f66f7cc5d1" }}success=true acknowledges durable Gateway acceptance, not provider success or device display. Store op_id and query GET /send_status/{op_id} when coarse dispatch status matters.
Common Errors
Section titled “Common Errors”| Status | Typical reason |
|---|---|
400 | Missing/invalid required field, forbidden message_id, empty title, or invalid metadata. |
401 | Private Gateway requires a Bearer token, but the header is missing or wrong. |
404 | Channel does not exist or credentials do not match. |
409 | An op_id was reused for a different payload or scope. |
413 | Request body exceeds 32 KiB (32,768 bytes). |
503 | Gateway could not accept the submission. |
See Limits & Errors for shared limits.
Legacy GET Query Form
Section titled “Legacy GET Query Form”GET /message is retained for compatibility. It accepts the scalar fields above as query parameters; images and tags are comma-separated, while metadata is a JSON-encoded string. Prefer the JSON POST route for new integrations because URLs, access logs, and browser history can expose the channel password or payload.
Compatibility Endpoints
Section titled “Compatibility Endpoints”PushGo also provides ntfy, Bark, and ServerChan compatibility endpoints for migration. Their field coverage is limited; use native /message when you need thing_id, E2EE, or full PushGo semantics. See Migration Guide.