Zapier
The 50heads app on Zapier asks real people a question from a Zap, brings the results back, and starts Zaps when a question finishes. It uses the same API as everything else: OAuth, the ask service with its caps and idempotency, and Webhooks v2.
People set it up from Zapier, not from 50heads. For the steps in plain words, see Use 50heads with Zapier in Help.
Triggers
Each trigger is a REST hook on one webhook event. The payload is the event's data, as signed deliveries carry it.
| Trigger | Event | Fires when |
|---|---|---|
| Question completed | question.completed | A question got every answer it asked for. Carries the summary, and the go or no-go verdict when the question has a go line. |
| Question closed underfilled | question.underfilled | A question closed with fewer answers than it asked for. The unanswered part is refunded. |
| Credits running low | credits.low | The balance fell below your low-credit threshold. |
Actions and search
| Step | API | What it does |
|---|---|---|
| Ask a question | POST /v1/estimate, then POST /v2/questions | Zapier shows the price before the step runs, for example $13 for 50 answers at Tier 1. Takes your own reference (externalRef), a project and labels. |
| Add heads | POST /v2/questions/{id}/heads | Reopens a finished question for more answers, with the same wording and targeting. The results merge. |
| Cancel a question | POST /v2/questions/{id}/cancel | Stops a live question. Unused credits go back to the balance. |
| Get results | GET /v2/questions/{id}/result | How the answers split, the go or no-go verdict (verdict), the head-to-head table for rankings and three-way or larger comparisons (headToHead) and the cohort hash (cohortHash), which is equal for questions asked of the same audience. |
| Find a question (search) | GET /v2/questions?externalRef=… or GET /v2/questions/{id} | By your own reference, archived questions included, or by its id. |
Connecting: OAuth and scopes
Zapier signs in with OAuth 2.1: the authorization code flow with PKCE, then refresh tokens. Its client id is a Client ID Metadata Document, so there is no client secret to store:
https://50heads.com/oauth/clients/zapier.jsonThe connection asks for these scopes, and the consent page lists them before anyone approves:
| Scope | Used for |
|---|---|
questions:read | Get results, find a question, and the trigger samples |
questions:write | Ask a question, add heads, cancel a question |
templates:read | Question types and prices for the ask step's fields |
account:read | Balance and the connection's cap, for the connection label and the credits trigger |
webhooks:read | Recent events, for sample data and polling |
webhooks:write | Create and delete the REST hooks the triggers use |
Each Zapier account connected to 50heads is one connection. It spends the credits of the account that approved it (personal, or the team in use), up to a daily cap. A new connection starts at 5,000 credits a day; change it under Developers, Connections, or from Settings, Integrations. An ask over the cap is refused with spend_cap_reached and nothing is spent. See Authentication for tokens and caps in general.
Retries never charge twice
Every ask and add-heads step sends an Idempotency-Key made from the Zap run and the step. When Zapier retries a step, the API returns the question from the first attempt and charges once. See Idempotency.
REST hook lifecycle
- Subscribe. When a Zap with a 50heads trigger is turned on, Zapier creates a webhook endpoint for its hook URL and that one event:
POST /v1/webhooks/endpoints. The endpoint belongs to the connection. - Deliver. Each event is a signed delivery like any other (see Verifying signatures), retried with backoff. Deliveries arrive at least once; the app drops repeats by event id.
- Unsubscribe. When the Zap is turned off or deleted, Zapier deletes the endpoint:
DELETE /v1/webhooks/endpoints/{endpointId}.
One connection can hold up to 50 hooks, one for each Zap trigger. The hooks show under Developers, Webhooks, and Settings, Integrations counts them for each connection.
Sample data and polling
When you set up a trigger, Zapier shows recent real events as samples. They come from the latest events of one type in the account, newest first, shaped exactly as deliveries carry them. Zapier also uses this route as a polling fallback. It needs webhooks:read.
curl "https://api.50heads.com/v1/webhooks/events?type=question.completed&limit=3" \
-H "Authorization: Bearer $FIFTYHEADS_TOKEN"type is any webhook event type; limit is 1 to 25, 3 by default. The response is { "events": [ … ] }, each item the same envelope as a delivery body (id, type, createdAt, data).
Disconnecting
Disconnecting revokes the connection: in Settings, Integrations; under Developers, Connections; or with DELETE /v1/connections/{id}. Its tokens stop working at once and every hook it created is deleted, so its Zaps stop asking and stop firing. Questions already asked still finish, and their results stay in 50heads.