This article shows you how to switch a flow's start node to webhook mode so an external system — a photo workflow, Zapier, or any HTTP client — can automatically launch a run by sending a single photo and its data fields.
Before you start
- The Flows tab must be enabled for your organization. If you do not see it in the top navigation, contact your account owner.
- You need a flow to attach the webhook to, but it does not need steps yet. A delivery to a flow that has only its start node is accepted and recorded (it runs as a no-op), and the fields it carries are captured so you can wire up the rest of the pipeline afterward. To build the pipeline, see Flow overview: build your first pipeline.
- Your flow must be saved before a webhook URL is available.
Switch the start node to webhook mode
The start node's configuration panel opens with a Trigger picker at the top, set to Photos (manual upload) by default. To put the flow in webhook mode:
- Open the flow from the Flows list.
- Click the start node on the canvas to open its configuration panel on the right.
- Under Trigger, open the dropdown and select External system (GFITpro / webhook).
- Click Save (or press Cmd+S / Ctrl+S).
What the panel shows next depends on whether your organization has a GFITpro connection:
- No GFITpro connection — the per-flow webhook configuration described in the rest of this article appears directly, with a note steering new setups toward the organization-level Connection URL: For an external trigger, prefer your organization's Connection URL (Flows → Connection). The per-flow webhook is legacy — its URL changes whenever the flow is rebuilt. If you are setting up a new external trigger, use the Connection URL — see Connecting a photo source to your flows (Connection & Routing).
- GFITpro connection active — the panel leads with a GFITpro connection status section instead. It shows whether GFITpro photos are routed to this flow (with a Set as default flow button if they are not) and an Open Connection settings link to the organization-level setup. The per-flow webhook configuration sits behind an Advanced: per-flow webhook disclosure — the label gains an (enabled) suffix once the flow has a webhook URL, and the disclosure opens expanded automatically in that case so an active webhook is never hidden. Click the disclosure to reach the webhook configuration described below.
After saving, the start node's label in the editor header changes from Run to Webhook and the run button is disabled — webhook-triggered flows launch only from incoming POST requests, not from the editor.
Get your flow's webhook URL
When the start node is in webhook mode, the configuration panel shows a Webhook URL section. This is a single capability URL: the flow's secret token is built into the end of the address, so your caller only needs the URL — there is no separate token to copy and no Authorization header to set. This makes it easy to paste into no-code tools and form builders that can't add custom headers.
- The URL is shown in a read-only field. Click the copy button next to it to copy it to your clipboard.
- Because the token lives in the URL, treat the whole address as sensitive. The panel warns: Anyone with this URL can trigger the flow — treat it like a secret.
If no URL exists yet, click Generate URL to create one. To replace a leaked URL, click Regenerate — the old URL stops working immediately. To disable the webhook entirely without deleting the flow, click Revoke.
These changes take effect immediately on the server; you do not need to save the flow again.
Declare the fields your caller will send
Under Fields, list the names of the data fields your external system will include with each photo. Each name you add here becomes a {variable} available in every downstream step's text fields. The hint under the section reads: Names of the data fields your payload sends. They become {variables} in any create step.
- Type a field name in the input (for example,
firstNameorteamName) and press Enter or click the + button. - Repeat for each field your caller sends.
- To remove a field, click the × next to its name.
Field names are case-sensitive. Use the same capitalization in this list and in your POST request.
You don't have to declare every field by hand. After a webhook delivers, the field names it carried are remembered from your flow's recent deliveries and surfaced here automatically. Any field seen recently but not yet declared appears under Seen in recent deliveries — click to pin: as a quick-add chip; click one to add it to your field list. Until a delivery has arrived, the panel shows a hint: Send a test request to this URL to auto-detect your payload's fields — once one comes in, every field appears here to map into your steps.
Send a photo with a POST request
The Payload section shows a ready-to-run cURL command with your real URL already filled in. Copy it with the Copy cURL button and paste it into a terminal to test immediately.
The request shape — note there is no Authorization header:
POST /api/flow-hooks/{flowId}/{token}
Content-Type: application/json
{
"imageURL": "https://example.com/photos/player42.jpg",
"firstName": "Alex",
"teamName": "Diamonds"
}
This is the flat payload shape most source systems emit: the image URL sits at the top level under an aliased key, and every other top-level value becomes a data field. You can reference those fields as {firstName}, {teamName}, and so on in your steps.
The image URL is read from the first of these top-level keys that is present, in this order:
photo_urlimageURLimage_urlphotoUrlphoto
The URL must be publicly reachable. Templified fetches the image and copies it into secure storage before the run starts, so the URL only needs to be accessible at POST time.
Optional fields:
-
filename— the original file name (for example,alex_diamonds.jpg). If omitted, the name is derived from the URL. -
fields— a nested object of key/value pairs. This is the canonical form and still works. If you send both a nestedfieldsobject and top-level values, they are merged; a nestedfieldsentry wins over a top-level key with the same name. -
Idempotency-Keyheader — a unique string for this delivery (for example, your internal event ID). If you send the sameIdempotency-Keytwice, the second request returns the sameflowRunIdas the first without starting a new run. Use this to protect against duplicate deliveries from retry logic in your calling system.
The nested form looks like this and is fully equivalent:
{
"photo_url": "https://example.com/photos/player42.jpg",
"fields": {
"firstName": "Alex",
"teamName": "Diamonds"
}
}
Read the response
A successful POST returns 202 Accepted:
{
"flowRunId": "clxyz…",
"status": "running",
"pollUrl": "/api/flows/runs/clxyz…"
}
The run is launched asynchronously. You can poll pollUrl to track progress, or check the run history inside the Flows editor by opening the Runs menu at the top of the editor. A delivery to a flow that has no steps yet still returns 202 and is recorded as a completed no-op run.
Error responses
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized |
The token in the URL is wrong or revoked, or the webhook is not enabled for this flow. Check that you copied the full, current URL from the Webhook URL section. |
| 400 | missing_photo |
No image URL was found. The message reads photo_url (or imageURL) is required — send the image under one of the accepted keys. |
| 400 | photo_fetch_failed |
Templified could not fetch the image at the URL you sent. Verify the URL is publicly reachable. |
| 403 | flow_disabled |
The Flows feature is not enabled for your organization. |
Idempotency and duplicate deliveries
Webhook delivery systems (including Zapier, GFcrew, and most HTTP clients with retry logic) can send the same event more than once if the first delivery times out or the caller does not receive the 202 response. To prevent a single photo from launching multiple runs:
- Generate a stable, unique key for each photo delivery — your internal event ID or a UUID works well.
- Send it as the
Idempotency-Keyrequest header. - If the same key arrives a second time, Templified returns the original
flowRunIdand does not start a new run.
If you do not send an Idempotency-Key, each POST starts a new run regardless of the photo or fields it carries.
Comments
0 comments
Article is closed for comments.