---
title: Push
description: Send Web Push or FCM notifications through a push transport.
icon: Bell
source: "src/push.ts"
---

Use push for browser Web Push subscriptions or FCM device tokens.
The sender passes the target and notification payload to a push transport.

<Callout title="The one rule">Treat subscription endpoints and device tokens as secrets — they are long-lived delivery credentials.</Callout>

## Quick start

<Steps>
  <Step title="Create a Push sender">

```ts
import { createPushSender } from "sently/push";
import { WebPushTransport } from "sently/transports/webpush";

const push = createPushSender({
  transport: new WebPushTransport({
    vapidPublicKey: process.env.VAPID_PUBLIC_KEY!,
    vapidPrivateKey: process.env.VAPID_PRIVATE_KEY!,
    subject: "mailto:you@example.com",
  }),
});
```

  </Step>
  <Step title="Send to a browser subscription or FCM token">

```ts
// Web Push
await push.send({
  subscription: {
    endpoint: "https://fcm.googleapis.com/fcm/send/example",
    keys: { p256dh: "browser-public-key", auth: "browser-auth-secret" },
  },
  title: "Report ready",
  body: "Your weekly report is ready to view.",
});

// FCM (with FcmTransport)
await push.send({
  token: deviceRegistrationToken,
  title: "Report ready",
  body: "Your weekly report is ready to view.",
});
```

  </Step>
</Steps>

## Sender configuration

| Option | Type | Meaning |
| --- | --- | --- |
| `transport` | `PushTransport` | Required delivery implementation. |
| `plugins` | `PushPlugin[]` | Optional transforms run before delivery. |
| `hooks` | `PushHooks` | Optional callbacks for delivery activity. |

## Options shapes

`PushOptions` is a union:

| Shape | Required target | Transport |
| --- | --- | --- |
| Web Push | `subscription` | `WebPushTransport` |
| FCM | `token` | `FcmTransport` |

Shared fields include `title`, `body`, and optional `data` / `icon` / `ttl`.
Web Push also accepts `urgency`, `topic`, rich Notification fields, and silent /
data-only sends — see [Push options](../reference/push-options).

## Troubleshooting

<Accordions>
  <Accordion title="Why does the transport reject my endpoint?">
    Web Push validates subscription endpoint hosts before sending. Add only exact private relay hostnames with `allowedEndpointHosts` when needed.
  </Accordion>
  <Accordion title="Why does FCM reject my subscription object?">
    `FcmTransport` requires `token`. Pass a Web Push `subscription` only to `WebPushTransport`.
  </Accordion>
  <Accordion title="Why is the endpoint redacted in hooks?">
    Endpoint paths and FCM tokens are long-lived credentials, so hook context keeps only a redacted fingerprint.
  </Accordion>
</Accordions>

## Learn more

- [Push options](../reference/push-options)
- [Web Push](../transports/webpush)
- [FCM](../transports/fcm)
- [Failover](../guides/failover)
- [Hooks](./hooks)

## Next

<Cards>
  <Card title="Web Push transport" href="/docs/transports/webpush" />
  <Card title="FCM transport" href="/docs/transports/fcm" />
</Cards>
