Notion button send webhook: put the video URL back on the page

A Notion button can send a webhook that starts a Sume video job. When Sume calls back, PATCH the page's URL property with the finished video.

5 min readSume
All posts

A Notion button can run a Send webhook action, which sends an HTTP POST to your URL. Getting a finished Sume video back onto the page is your endpoint's job, done through Notion's API. So have your endpoint submit the job with a callback_url, then update the page yourself from Sume's job.completed callback with Notion's PATCH /v1/pages/{page_id}, writing the video link into a URL property.

Notion facts come from its help pages for database buttons and database automations and its developer pages for Update page, the property value object and request limits, read 2026-09-29. Sume facts come from Webhooks and Videos. This post starts after the click.

How does a Notion button start the job?

Database buttons are a property whose actions run when someone clicks: Notion lists Send webhook among the button actions, available on paid plans, and it sends a POST to the URL you enter. Two limits shape the design. Notion's webhook page says database button properties can't be selected as webhook content, and it doesn't document the body a button sends. So inspect one real delivery before you depend on a field.

The automations page gives a second route: button actions can trigger database automations, and a database automation can send selected page properties. Both routes end at the same place, an endpoint of your own that submits the Sume job and remembers which page it was for.

How do I write the video URL back to the page?

When the job finishes, Sume POSTs a job.completed event. Its payload.artifacts entries carry a url. Verify the signature on the raw body, find the page you saved at submit time, and PATCH one URL property. Notion's property page shows a URL write as { "url": "https://..." } under the property's name.

import { verifyWebhook } from "@sume-com/sdk";

export async function POST(request: Request) {
  const secret = process.env.SUME_COM_WEBHOOK_SIGNING_SECRET;
  if (!secret) return new Response("not configured", { status: 500 });
  const body = await request.text(); // raw, before any JSON.parse
  if (!(await verifyWebhook({ body, headers: request.headers, secret }))) {
    return new Response("bad signature", { status: 401 });
  }
  const event = JSON.parse(body);
  const url = event.payload?.artifacts?.[0]?.url;
  if (event.event !== "job.completed" || !url) return new Response(null, { status: 204 });

  const pageId = await pageIdForJob(event.job_id); // saved when you submitted
  const res = await fetch(`https://api.notion.com/v1/pages/${pageId}`, {
    method: "PATCH",
    headers: {
      Authorization: `Bearer ${process.env.NOTION_TOKEN}`,
      "Notion-Version": process.env.NOTION_VERSION!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ properties: { "Video URL": { url } } }),
  });
  // 429/529: answer 503 so Sume redelivers later; the same PATCH is safe to repeat.
  return new Response(null, { status: res.ok ? 204 : 503 });
}

Which Notion property should hold the video?

A URL property is the simplest. If you want a playable attachment, the Files & media property takes an external URL.

From Notion's property value object page, read 2026-09-29.
PropertyWrite shapeNotes
URL{ "url": "https://example.com/v.mp4" }A URL string or null
Files & media{ "files": [ { "name": "...", "external": { "url": "..." } } ] }A file update replaces the full list, so include files you want to keep

What about Notion's rate limit and Sume's retries?

Notion limits each connection to 180 requests per minute, an average of 3 per second, or 600 per minute on Business and Enterprise workspaces. Over the limit you get HTTP 429 with a Retry-After header in seconds; Notion also documents 529 for temporary overload. Sume retries a callback that gets a non-2xx response, up to 10 attempts 30 seconds apart by default, with 10 seconds allowed per attempt, so answering 503 on a Notion 429 is a workable backoff. Dedupe on job_id.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume