SureTake

Webhooks & Automations for Studios

Automatically send each finished recording session to your own tools: Zapier, Make, or a custom endpoint.

Overview

What is a webhook?

A webhook lets SureTake automatically notify your systems the moment a recording session finishes processing. Each time a session's files are ready, we send an HTTP POST to a URL you provide, containing everything about that episode: the download links, session notes, and (optionally) a transcript. It's how you automate the after-recording work: dropping files into cloud storage, kicking off an editing workflow, logging the episode, notifying your team, and so on. It works with tools like Zapier, Make, and n8n, or any endpoint you build yourself.

When does it fire?

Once per completed session, after every participant's track has finished uploading and converting, never per-file or mid-recording. You get a single recording.ready event with everything for that episode in one payload, so an automation can process the whole session at once (e.g. create one folder and drop all the files in). It fires for your studio's own recordings and for your clients' recordings alike.

Setting it up

Adding a webhook

In Manage Clients, find the Webhooks section. Paste your endpoint URL (it must be https://) and, optionally, a label to help you tell multiple webhooks apart. The label is only for your own reference and is never sent in the payload. Use the Test button to fire a sample payload to your URL so you can build against it before recording anything real.

Choosing which recordings trigger it

Your own recordings always trigger the webhook. For clients, each has its own Webhook switch in Manage Clients, set independently of their Email switch, so you can send some clients into your webhook, others to email, both, or neither. Turn a client's Webhook switch off and no webhook fires for that client (their email notifications are unaffected, and vice-versa).

Including a transcript

Turn on Include transcript in automations in the Webhooks section to have a transcript generated automatically and included in the webhook (see Transcripts below). Off by default.

The payload

What's in the recording.ready event

Every delivery is a JSON body shaped like this:

{
  "event": "recording.ready",
  "event_id": "b1f2…",          // unique per delivery, use to de-duplicate retries
  "version": "1",
  "timestamp": "2026-07-05T14:41:00Z",  // when the webhook fired
  "account_id": "…",
  "session_url": "https://app.suretake.io/share/…",  // shareable preview/download page
  "show":    { "id": "…", "name": "My Podcast" },
  "session": {
    "id": "…",
    "name": "Episode 12",
    "date": "2026-07-05",
    "started_at": "2026-07-05T14:03:00Z",  // full timestamp, for sorting
    "notes": "00:12:30 New topic\n00:41:05 Ad read",  // notes + markers, as text
    "notes_url": "https://app.suretake.io/api/share/…/notes"  // same notes as a .txt download
  },
  "client":  { "email": "guest@example.com", "name": "Jane Guest" },
  "track_count": 2,             // number of participant tracks in "tracks" below
  "tracks": [                   // ONLY individual participant recordings, no backup here
    {
      "type": "browser",       // an individual participant's local recording
      "recording_id": "…",
      "participant_id": "…",
      "name": "Host",
      "file_url": "https://…/host.mp4",
      "synced_url": null,       // present only if the participant joined late (time-aligned copy)
      "duration_seconds": 3120
    },
    {
      "type": "browser",
      "recording_id": "…",
      "participant_id": "…",
      "name": "Jane Guest",
      "file_url": "https://…/guest.mp4",
      "synced_url": null,
      "duration_seconds": 3115
    }
  ],
  // media_urls: flat "just grab these" list of participant files (same order as "tracks").
  // A no-code shortcut: map straight into a multi-file field, no code step. Already the
  // right file per track: the synced version when a track needed aligning, else file_url.
  "media_urls": [ "https://…/host.mp4", "https://…/guest.mp4" ],
  // The server-side recording of everyone together, kept OUT of "tracks" on purpose so
  // you can import just the participant recordings. Use it as a safety net if you want it.
  "combined_backup_url": "https://…/combined.mp4",
  "transcript": { "url": "https://…/transcript.docx" }  // or null (see Transcripts below)
}

A few notes: tracks holds only the individual participant recordings. It's an array whose length varies with the number of participants, so always iterate it rather than assuming a fixed count. The combined backup (the single server-side recording of everyone together) is deliberately not in tracks; it's provided separately as combined_backup_url, so you can import just the participant files and treat the backup as an optional safety net.

What are the notes and notes_url?

session.notes is the plain-text notes taken during the session, including any timestamped markers (each on its own timestamped line, e.g. 00:12:30 New topic). session.notes_url is that same text as a downloadable .txt file, so an automation can drop it into a folder alongside the media. Both are omitted/empty when no notes were taken.

What's the difference between tracks and media_urls?

They point at the same participant recordings, just two shapes for two kinds of consumer. tracks is the rich version: an array of objects with the full detail for each recording (participant name, duration_seconds, the recording_id, each track's file_url, and a synced_url when someone joined late). Reach for it when you want to label, organize, or make decisions per file.

media_urls is the convenience version: a flat array of just the files to grab, in the same order. It exists purely to make no-code automations easy. Tools like Zapier, Make, and n8n often can't pull a nested field out of an array of objects without a code/formatter step, so media_urls lets you map the whole list straight into a “multiple files” input. It's also the authoritative “just grab these” list: for any track that needed time-aligning (a late joiner), media_urls already points at the synced version, so you never have to check synced_url yourself. Every URL in it is the file you actually want.

For example, in a Descript import step you can map its media field directly to media_urls and it'll pull in every participant track at once, with no formatter or code step needed. Use whichever fits your tool; the combined backup is intentionally in neither, on combined_backup_url.

Working with the files

How can I automatically download the files into my own folders?

The webhook hands you direct download links (media_urls). How you pull them into folders is up to you. First, a word on file sizes:

A recording's media files are large, a combined backup can be hundreds of MB, and many no-code “upload to cloud storage” steps have file-size limits (for example, Zapier's Dropbox action caps around 100 MB, and some actions far lower). So routing a full recording through an automation tool into Dropbox / Drive often won't work. The download has to happen somewhere without that size ceiling:

Most reliable (any size): a small script (Python, a Node function, etc.) that downloads the URLs straight into a local or network folder, with no middleman and no size limit. Trigger it from the webhook, or run it on an always-on machine that reads the URLs from wherever you track jobs.

No-code, within limits: Zapier, Make, and n8n work well for the small files (the notes and transcript), and for media only if your destination pulls from the URL directly (its own API, a cloud function, a tool like rclone) rather than passing the file through the automation tool.

Bridge from your existing tools: if your order- or project-management software can hold the URLs, fetch from there. For example, a Google Sheet of links plus a script that pulls each job's files into the right folder.

How can I automatically import media files and set up sessions in Descript?

There are a variety of ways to do this in Descript, depending on the tools you use. (Note that Descript's own API is currently invite-only, so a fully custom integration may not be open to you yet.)

One approach we've experimented with is Zapier plus Descript's built-in integration, triggered by this webhook. We start the Zap with a “Catch Hook” trigger (Webhooks by Zapier) and paste in the SureTake webhook URL. Then a Descript “Import Media” action creates the project, named from the show and episode, and imports the files from media_urls. A second Descript action, “Edit Project with AI,” builds the sequence, transcribes the files, and adds the sequence to the main composition. That second step runs on Descript's built-in AI (Underlord), so it draws on your Descript account's credits.

One idea worth exploring here: session.notes (the timestamped markers your host and guests drop live during recording) rides in the same payload, so you can map it into that AI step's instructions, anything you could direct Underlord to do, you can drive from the notes taken in the moment.

We like to finish with an email notification so we know a new session is ready, and you can take it further from there, wiring in other tools like invoicing software or Slack.

One current limitation on Descript's side: new projects can only be created in your personal folder.

Verifying the request

How do I confirm a request really came from SureTake?

Each request carries an X-Webhook-Signature header, an HMAC-SHA256 of the raw request body, signed with your endpoint's secret (shown once when you create the endpoint; rotate it anytime). Recompute it on your end and compare. A match proves the request is genuine and untampered:

// Node.js: verify the request really came from SureTake
const crypto = require("crypto");

const signature = req.headers["x-webhook-signature"];
const expected = crypto
  .createHmac("sha256", YOUR_ENDPOINT_SECRET)   // the secret shown when you created the endpoint
  .update(rawRequestBody)                        // the raw body bytes, before JSON.parse
  .digest("hex");

const valid =
  signature &&
  crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
// if !valid → reject the request

The request also includes an X-Webhook-Event header (recording.ready). Verifying is optional but recommended for anything sensitive. Most no-code tools (Zapier/Make) skip it and simply trust the URL, which is fine if you keep the URL private.

Transcripts

How does the transcript get included?

With Include transcript in automations turned on, the webhook waits for a transcript to be generated from the session's combined backup, then includes a download link in transcript.url. The event holds for up to ~15 minutes for this; if the transcript isn't ready by then (or transcription fails), the event still fires, just with transcript set to null. So the single event is never blocked: the transcript rides along when it's ready in time, and its absence never stops delivery. The generated transcript is the same one you can download from your dashboard.

Delivery & reliability

How soon after a session ends does the webhook arrive?

When a session ends we first upload and convert every participant's track, time-align any late joiners, then hold briefly, about five minutes, to let everything settle before firing, so the links never open to still-processing files. For a typical recording, expect the webhook within roughly 5–10 minutes of the session ending. Longer sessions, or ones where a track needs recovery or alignment, take proportionally longer: the event simply waits until the whole session is genuinely ready, then fires once with everything included.

What if my endpoint is down?

Respond with any 2xx status to acknowledge receipt. If you don't, we retry a few times with increasing delays before giving up. Every attempt, success or failure and with the response code, is recorded in the webhook's Logs view, so you can see exactly what happened.

How long do the download links last?

The file links in the payload (tracks, combined backup, notes, transcript) are signed and valid for 7 days. Download the files within that window. The links then expire, so don't store the URLs long-term. The recordings themselves remain available in your dashboard for your plan's full retention period; only the direct links expire.

What if a download fails, or something's missing from the payload?

Every payload includes a session_url, the same shareable link you see on your dashboard and in your email notifications. It opens the session's page in a browser, where every track, the combined backup, the notes, and the transcript can be viewed and downloaded directly. So if a file link ever fails or a track hadn't finished processing at the moment the webhook fired, just open session_url to grab the files. And if the webhook never reached you at all, say your endpoint was down for every retry, nothing is lost: the recordings are always available from your SureTake dashboard for your plan's full retention period.

How do I avoid processing the same event twice?

Each delivery includes a unique event_id. If a retry causes you to receive the same event more than once, use event_id to recognize and skip the duplicate.