Send push notifications using the Firebase API for AI video

Send a push with the FCM HTTP v1 API from your server when the video job's webhook arrives: POST messages:send with a short-lived OAuth 2.0 token.

5 min readSume
All posts

To send a push notification using the Firebase API, your server POSTs a message to the FCM HTTP v1 endpoint, https://fcm.googleapis.com/v1/projects/<project-id>/messages:send, with a short-lived OAuth 2.0 access token from a service account and the device's registration token as the target. For a “your video is ready” push, send it from the webhook handler that hears the video job finish.

The Firebase facts below come from its HTTP v1, server environment and Admin SDK pages, read 2026-09-28. The video job side uses Sume's webhooks docs. Sume has no Firebase connector; both halves are plain HTTPS from your server.

How do I send a push notification with FCM HTTP v1?

Firebase's steps, in order:

  • Get credentials from a service account in your Firebase project. On Cloud Functions and other Google Cloud runtimes, Firebase says to use Application Default Credentials.
  • Mint a short-lived OAuth 2.0 access token for the scope https://www.googleapis.com/auth/firebase.messaging, and send it as Authorization: Bearer <access_token>.
  • POST a JSON body with a message holding the target token and a notification with title and body. A data payload of your own fields can go with it or instead of it.
  • On success, the response is a JSON object with the message name.

Should I use the Admin SDK or the HTTP v1 API?

Firebase calls the Admin SDK "the recommended method", with SDKs for Node, Java, Python, C# and Go, because it handles authentication for you; the HTTP v1 API is for developers "who prefer a raw server protocol" (server environment). The Admin SDK page now recommends addressing a device by its Firebase Installation ID (fid) and marks the token field deprecated, though "during the migration period, the token field also accepts FIDs" (Admin SDK). Either way, the ID comes from the client FCM SDKs in your React Native, Flutter or native app, and your server stores it per user. Firebase says registration tokens "must be kept secret".

When should the server send the push?

When the video job ends, not on a timer. A video job runs for a while, so the app shouldn't sit open polling. The server learns first and tells the device.

From Sume's Webhooks and Video generation docs and Firebase's HTTP v1 page, read 2026-09-28.
StepWhereWhat happens
1App → your backendRegisters the device's FCM ID for the signed-in user
2Backend → SumeSubmits the video job with a callback_url and stores job_id → user
3Sume → backendPOSTs job.completed, job.failed or job.canceled once the job is terminal
4Backend → FCMVerifies the signature, looks up the user, POSTs to messages:send
5AppOpens on tap and asks your backend for the finished file
import { verifyWebhook } from "@sume-com/sdk";

export async function POST(req: Request) {
  const raw = await req.text(); // raw body, before JSON.parse
  const ok = await verifyWebhook({
    body: raw,
    headers: req.headers,
    secret: process.env.SUME_COM_WEBHOOK_SIGNING_SECRET!,
  });
  if (!ok) return new Response("bad signature", { status: 401 });
  const event = JSON.parse(raw);
  const job = await claimJobOnce(event.job_id); // your DB; null on a repeat
  if (job && event.event === "job.completed") {
    await fetch(`https://fcm.googleapis.com/v1/projects/${PROJECT_ID}/messages:send`, {
      method: "POST",
      headers: { Authorization: `Bearer ${await getAccessToken()}`, "Content-Type": "application/json" },
      body: JSON.stringify({ message: {
        token: job.deviceToken,
        notification: { title: "Your video is ready", body: "Tap to watch it." },
        data: { job_id: event.job_id },
      } }),
    });
  }
  return new Response(null, { status: 204 });
}

Is the webhook safe to act on?

Only after it verifies. verifyWebhook from Sume's SDK checks the sume-v1 HMAC over the raw body and the timestamp window (Verifying webhooks), and in current code it returns false when the secret is empty. Sume makes up to 10 delivery attempts and asks you to "use job_id as the idempotency key", so claimJobOnce should mark the job so a repeat sends no second push. Answer with a 2xx quickly: each attempt times out after 10 seconds, so move the FCM call to a queue if it may be slow (Webhooks). getAccessToken is the token helper from Firebase's own sample.

Should the push carry the video URL?

Better not. Send the job_id in data and let the app fetch the file URL from your backend after the user is signed in. The finished file lives at a public media.sume.com URL, and anyone who has that URL can fetch it, so it doesn't belong on a lock screen.

What if the webhook or the push never arrives?

Plan for both. Ten refused Sume deliveries leave a failed delivery and a job that still finished; the docs call delivery "an optimization, never the only recovery path", so keep polling the job as a backup (Webhooks). On the Firebase side, your server must be "able to handle requests and resend them using exponential back-off" (server environment). When the app opens, have it ask your backend for the user's latest jobs rather than trust that every push landed. Progress updates for long video jobs covers what to show while it runs.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume