Browse documentation
Tutorial Updated 11 August 2026

Send data into Hodoflow with a webhook

Create a service account, point a workflow's webhook trigger at it, and post a payload that starts a real run.

Goal: An external caller posts JSON to your workflow's URL and gets back the id of the run it started.

View as Markdown

This is the complete inbound path: an identity for the caller, a workflow with a URL, and one authenticated request that produces a run you can open.

What you will build

  • A service account called Webhook ingest holding only the webhooks scope.
  • A workflow called Order intake with a webhook trigger that uses it.
  • One accepted delivery, visible as a completed run in Monitor.

Before you start

  • Creating a service account is limited to owners and admins. If New Service Account is missing, that is why.
  • Nothing external needs configuring. You will send the request yourself.

1. Create the service account

Go to Settings → Service Accounts and choose New Service Account.

Field Value
Name Webhook ingest
Scopes webhooks only
Run as Yourself, or whoever should own this integration long term

Run as matters more than it looks. A service account has no permissions of its own — it borrows a member's. Every request authenticated with it executes as that person, so deactivating them changes what the credential can reach.

Checkpoint: the service account appears in the list as Active.

2. Copy the client ID and secret

Open the service account and find Client Credentials. You get a client ID beginning cid_ and a client secret beginning csec_, each with a Copy button.

Unlike most secrets, these stay retrievable — you can come back to this page whenever an integration needs reconfiguring. Access is limited to owners and admins.

Checkpoint: you have both values to hand.

3. Build the workflow

Go to Workflows → New Workflow. In the trigger wizard choose Webhook, then select Webhook ingest in the Service account picker. Press Done.

Add one step so the workflow has something to do — an HTTP Request to any endpoint you like is enough for this walk-through — and connect the trigger to it.

Name the workflow Order intake and press Save.

Checkpoint: the trigger inspector now shows a read-only Webhook URL. Before saving it said Save workflow to generate webhook token — the token is minted on save.

4. Activate it

Press Activate. Only active triggers are served: until you do this, the URL answers 404.

Checkpoint: the workflow reads Active.

5. Exchange the credentials for a token

The client ID and secret are not what you send with the request. Exchange them for a short-lived token first:

curl -X POST https://app.example.com/api/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "cid_...",
"client_secret": "csec_..."
}'

The response is the token, its type, and its lifetime in seconds:

{"access_token": "eyJ...", "token_type": "bearer", "expires_in": 900}

Fifteen minutes. A long-lived integration exchanges again rather than caching one forever.

Checkpoint: you have an access_token.

6. Post a payload

Copy the Webhook URL from the trigger inspector and post to it:

curl -X POST https://app.example.com/api/v1/webhooks/YOUR_TRIGGER_TOKEN \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"order_id": "A-123", "total": 250}'

An accepted delivery returns 202 Accepted with the id of the run it started:

{"status": "accepted", "workflow_run_id": "0198f2c1-..."}

Checkpoint: you got 202 and a workflow_run_id.

7. Teach the workflow the payload's shape

Steps below the trigger can only offer fields they know about. In the trigger inspector, open Output Schema and press Refresh Schema.

Hodoflow shows a Test URL (no data saved) and waits. Post the same payload to that URL, and the field names appear as N fields found. Nothing is stored and no run is created.

order_id and total are now available to every step below, as input.order_id and input.total.

Checkpoint: 2 fields found.

Verify the result

You are done when all of these are true:

  • Settings → Service Accounts lists Webhook ingest as Active with only the webhooks scope.
  • Workflows lists Order intake as Active.
  • Your curl returned 202 with a workflow_run_id.
  • Workflows → Monitor holds a run whose Source is that trigger.
  • The trigger's Output Schema lists the fields you sent.

Common problems

401 with {"error": "invalid_client"} at the token step. Every credential problem returns this same response — wrong secret, unknown client, deactivated account. That is deliberate. Check the service account's status in Hodoflow rather than reading the error.

403 when posting to the webhook. The token authenticated but does not carry the webhooks scope. Add the scope, then exchange again — a scope change takes effect on the next exchange, not instantly.

404 when posting to the webhook. The workflow is not active, or the URL is from a version that is no longer live. Activate it and re-copy the URL.

202 with {"status": "duplicate"}. Hodoflow matched your request to a delivery it already accepted, so it did not start a second run. Change the payload, or send a different Idempotency-Key header.

The service account picker in the wizard was empty. Only active service accounts holding webhooks are listed. Check both.

429. The cap is 100 requests per minute per trigger token.

Next steps

Related documentation