Set up the Frank webhook

Have Frank tell your server the moment an interview is completed, instead of polling for it.

ON THIS PAGE

  1. How it works
  2. Connect your endpoint
  3. Verify the request came from Frank
  4. The payload
  5. When it fires
  6. Fetch the full interview
  7. Send a test event

1. How it works

When an interview is completed, Frank sends a POST to a URL you own. Use it to mark a participant as interviewed, advance them through a flow, or sync the result into your CRM or analytics — without asking Frank repeatedly whether anything has finished.

You configure one endpoint for the whole account. It covers every research you run; there is no per-research or per-product configuration, and no list of endpoints.

2. Connect your endpoint

  1. In Frank, go to Settings → Webhooks. Before setup the card reads Not configured — Add an endpoint to start receiving events.
  2. Enter the URL that should receive 2 events and choose Configure webhook.
  3. Store the signing secret Frank generates. You need it to verify every incoming request, and it cannot be read back later.
Before setup: enter your URL and choose Configure webhook.
Only public HTTPS endpoints are accepted.
Once configured the card reads Configured — Delivering interview events to your endpoint and gains Send test event, Rotate secret, Save changes and Delete webhook. To change the URL later, edit the field and choose Save changes. Deleting stops delivery and returns the card to Not configured; you can connect a new URL afterwards.
Once configured: the secret is masked, and Send test event and Rotate secret become available.
The secret cannot be viewed again

Once the webhook exists, the Signing secret field shows only a masked value (frank_whsec_••••) — Frank will not reveal the existing secret. If you did not store it, or you need to replace it, use Rotate secret to generate a new value, then update your receiver to match.

3. Verify the request came from Frank

Every request carries your secret — a frank_whsec_ -prefixed value — in the X-Frank-Secret header. Verify it against your stored copy before trusting the body, and reject any request that does not match.

4. The payload

FIELD                                                 TYPE                                            NOTES

event                                         string                                   interview.completed

eventId                                      string                                   interview.completed:

                                                                                              <interviewId>

occurredAt                                string (ISO 8601)                When the event occurred.

data.interviewId                        string (uuid)                        The completed interview.

data.researchId                         string (uuid)                       The research it belongs to.

data.type                                    string                                  audio , video or chat .

data.startedAt                            string (ISO 8601) | null      When the interview started.

data.endedAt                              string (ISO 8601)               When the interview ended.

data.durationSeconds               integer                                Length in seconds.

data.participant.external_id       string | null                         Your own participant identifier,

                                                                                                when one was supplied.

data.participant.name                string | null                         null when the participant stayed

                                                                                                anonymous.

data.participant.email                 string | null                         null when the participant stayed

                                                                                                anonymous.

data.turns                                    integer                                Number of turns in the
                                                                                                conversation.

Request body        Copy

{

"event": "interview.completed",

"eventId": "interview.completed:<interviewId>",

"occurredAt": "2026-07-27T08:00:00.000Z",

"data": {

"interviewId": "<uuid>",

"researchId": "<uuid>",

"type": "audio | video | chat",

"startedAt": "<ISO-8601 | null>",

"endedAt": "<ISO-8601>",

"durationSeconds": 123,

"participant": {

"external_id": "<external participant ID | null>",

"name": "<participant name | null>",

"email": "<participant email | null>"

},

"turns": 12

}

}

The same sample is available in-product: View interview.completed payload expands on the Webhooks page in both states.

5. When it fires

The webhook fires when an interview is completed. At this time interview.completed is the only supported event.

So a participant who joins and immediately leaves will never reach your endpoint. If you need to know about those, poll the interviews endpoint instead — their status is available through the API.

6. Fetch the full interview

The payload identifies the interview; the transcript and the rest of its detail come from the authenticated API using data.interviewId . See the API documentation.

7. Send a test event

From the Configured card, Send test event posts a test interview.completed to your endpoint and reports the outcome. On success it reads Last test: 200 — your endpoint accepted the event. On failure it reports the error code your endpoint returned.