> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pushnotif.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Send a push

> Send one push to one user, now, from your own server.

For pushes only your backend knows about, sent the moment something happens:
a new chat message, a match, a reply. The push goes out during the request,
usually within a second.

> [!WARNING]
>
> Use this for **one-to-one messages that answer something a person did**, never
> for marketing or re-engagement. Direct sends skip [the holdout](https://docs.pushnotif.ai/strategy/holdout.md),
> quiet hours and caps, because they aren't part of your notification program.
> Sending campaigns this way would hide them from the holdout, so you could no
> longer tell whether your program helps. Use a [flow](https://docs.pushnotif.ai/strategy/flows.md) or a
> [broadcast](https://docs.pushnotif.ai/strategy/broadcasts.md) for those.

## Authentication

Send a [server key](https://docs.pushnotif.ai/dashboard/team-and-apps.md#server-keys) as a bearer token:

```bash theme={null}
Authorization: Bearer pns_...
```

An ingest key (`pna_...`) is refused here, with the same
`401 {"error": "unauthorized"}` as a missing or revoked key. A server key can
send pushes to any of your users: keep it on your server, never in your app.

## Body

**user\_id** `string` *required*

Your own id for the user, as you passed it to
[`identify`](https://docs.pushnotif.ai/sdk/identifying-users). At most 256 characters.

**idempotency\_key** `string` *required*

Your unique id for this push, at most 256 characters - for a chat push, the
message's id. Sending the same key again never sends a second push: you get
back the result of the first. So you can retry a request that timed out
without risking a duplicate.

**title** `string` *required*

At most 120 characters.

**subtitle** `string`

At most 120 characters.

**body** `string` *required*

At most 400 characters.

**deep\_link** `string`

Opened when the push is tapped. At most 2048 characters.

**badge** `number`

The number to show on your app icon, such as the unread count. A whole
number, 0 or more; `0` clears it. Leave it out to keep the current badge.

**data** `object`

Custom keys for your app's code, delivered beside the alert. Values may be any
JSON. At most 20 keys; a key is letters, digits and underscores, and `aps`,
`pnai` and `deep_link` are reserved. The whole push must fit in Apple's 4 KB
limit.

## Response

**send\_id** `string`

Our id for the send. It's the same for every retry with the same
`idempotency_key`.

**status** `string`

* `sent` (`200`): Apple accepted the push.
* `pending` (`202`): nothing has gone out yet, and we'll retry on our side, so
  don't send it again yourself. This happens when Apple is briefly
  unavailable.
* `cancelled` (`422`): it won't be sent. See `reason`.

**sent\_at** `string`

When it was sent, as ISO 8601. Only when `status` is `sent`.

**reason** `string`

Why it was cancelled. Only when `status` is `cancelled`. For example:

* `message_too_large`: the push is over Apple's 4 KB limit.
* `all_tokens_unregistered`: every device token was rejected by Apple, for
  example because the app was deleted.
* `delivery_unknown`: we couldn't tell whether Apple received it. It may
  have arrived, so it's never retried.

## Errors

| Status | Body | Means |
| - | - | - |
| `400` | `{"error": "title: expected a non-empty string"}` | The request is invalid. Fix it; retrying won't help. |
| `401` | `{"error": "unauthorized"}` | Missing, revoked or wrong kind of key |
| `404` | `{"error": "unknown_user"}` | No user with this `user_id` has been identified. |
| `422` | `{"error": "no_device"}` | The user has no device that can receive a push. |
| `503` | `{"error": "sending_disabled"}` | Sending is switched off for this app's backend. |

Nothing is recorded for these errors, so you can retry with the same
`idempotency_key` once the cause is fixed.

```bash cURL theme={null}
curl https://api.pushnotif.ai/v1/send \
  -H "Authorization: Bearer pns_..." \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "u_123",
    "idempotency_key": "msg_8812",
    "title": "Priya",
    "body": "Are you free Thursday?",
    "deep_link": "myapp://chat/42",
    "badge": 3,
    "data": { "chat_id": 42 }
  }'
```

```json 200 theme={null}
{
  "send_id": "8b1f6c2e-4a3d-4f0e-9c71-2d5e8a6b9f10",
  "status": "sent",
  "sent_at": "2026-11-11T18:04:12.511Z"
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.