Web Push Sender API

Generate VAPID keys and send Web Push notifications to browser subscriptions with RFC 8291 payload encryption, TTL, urgency and topic.

GETPOSThttps://apibox.io.vn/v1/web-push
Developer utilities▶ Try it online

Call with no parameters (or action=generate_keys) to get a fresh P-256 VAPID key pair in base64url: public_key is the applicationServerKey for pushManager.subscribe() in the browser, private_key stays on your server. Keys are generated for the response only and never stored or logged.

action=send posts a notification to one subscription (the PushSubscription JSON from the browser: endpoint + keys.p256dh + keys.auth) or up to 50 subscriptions. The optional payload (text or JSON, max 4,078 bytes) is encrypted with aes128gcm (RFC 8291) using WebCrypto ECDH, HKDF and AES-GCM, and the request is signed with a VAPID ES256 JWT (RFC 8292) built from your vapid object (subject = mailto: or https: contact, public_key, private_key). Set ttl (seconds, default 86400), urgency (very-low, low, normal, high) and topic (replaces an undelivered message with the same topic).

Each result has the push service HTTP status; gone: true (404 / 410) means the subscription expired and should be deleted. action=encrypt returns the encrypted body and headers without sending, for debugging or sending yourself. Nothing is stored: subscriptions and keys live only in the request.

Parameters

NameInTypeRequiredDefault
actionbody|querystringnogenerate_keysgenerate_keys (default without a subscription), send or encrypt (build the request without sending).
subscriptionbodyobjectnoPushSubscription JSON: {"endpoint": "https://...", "keys": {"p256dh": "...", "auth": "..."}}.
subscriptionsbodyarraynoUp to 50 subscriptions for one send.
payloadbodystringnoMessage text or JSON object (max 4,078 bytes); omit for a push without data.
vapidbodyobjectno{"subject": "mailto:you@example.com", "public_key": "...", "private_key": "..."}, required for send.
ttlbody|querynumberno86400Seconds the push service keeps the message if the device is offline (0-2,419,200).
urgencybody|querystringnonormalvery-low, low, normal or high.
topicbody|querystringnoUp to 32 base64url characters; a newer message with the same topic replaces an undelivered one.

Example

curl -X POST "https://apibox.io.vn/v1/web-push" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":"send","subscription":{"endpoint":"https://fcm.googleapis.com/fcm/send/abc","keys":{"p256dh":"BCVxsr7N_eNgVRqvHtD0zTZsEc6-VV-JvLexhqUzORcxaOzi6-AYWXvTBHm4bjyPjs7Vd8pZGH6SRpkNtoIAiw4","auth":"BTBZMqHH6r4Tts7J_aSIgg"}},"payload":{"title":"Đơn hàng #1024","body":"Đã giao thành công"},"ttl":3600,"urgency":"high","vapid":{"subject":"mailto:ops@example.com","public_key":"BECWGWmqQ8K_C-FP8oHoC2GdtyNmQRTEHe8z3qsK5VDKHjkpMUG-RRrKyy-jczLPSqC1y15k6r_iPaGLt39VFOw","private_key":"(your private key)"}}'

Response

{
  "sent": 0,
  "failed": 1,
  "gone": 1,
  "ttl": 3600,
  "urgency": "high",
  "topic": null,
  "payload_bytes": 61,
  "results": [
    {
      "index": 0,
      "host": "fcm.googleapis.com",
      "ok": false,
      "status": 410,
      "gone": true,
      "retry_after": null,
      "message_id": null,
      "response": "push subscription has unsubscribed or expired.\n"
    }
  ]
}

Use cases

  • Send order or delivery notifications from a PHP, Apps Script or no-code backend
  • Create VAPID keys for a new PWA without installing the web-push library
  • Clean up expired subscriptions using the gone flag
  • Debug a service worker with a known-good encrypted push message

FAQ

Do you store my VAPID private key or the subscriptions?

No. Keys and subscriptions are used for the request only and never written to storage or logs. Send them with every call.

Which browsers does it work with?

Any browser that implements the standard Push API with VAPID: Chrome / Edge (FCM), Firefox (Mozilla autopush), Safari 16+ (Apple), Opera, Samsung Internet. The endpoint in the subscription decides the push service.

What does status 410 mean?

The push service says the subscription no longer exists (the user unsubscribed or the browser data was cleared). The result has gone: true; delete that subscription from your database.

Related APIs

Start with 1,000 free requests every month. Get free API key →