Admin — Webhooks
Webhooks are custom HTTP endpoints that external systems can POST to in order to trigger an agent turn or a routine. They’re blank slates — any system that can make an authenticated HTTP POST can become a ThinkWork trigger through a webhook.
The list
Section titled “The list”Route: /webhooks
File: apps/admin/src/routes/_authed/_tenant/webhooks/index.tsx
A searchable DataTable with:
| Column | Notes |
|---|---|
| Name | Display name |
| Type | Badge: Agent or Routine depending on what the webhook targets |
| Target | Agent or routine name |
| Enabled | Enabled / Disabled badge |
| Last Invoked | Relative timestamp |
| Invocation count | Lifetime count |
| Created | Timestamp |
A New Webhook button opens the creation dialog.
The detail page
Section titled “The detail page”Route: /webhooks/:webhookId
File: apps/admin/src/routes/_authed/_tenant/webhooks/$webhookId.tsx
Header
Section titled “Header”- Webhook name
- Enable / disable toggle
- Delete with confirmation
Token card
Section titled “Token card”- The bearer token (masked by default with a show / copy button)
- The full invocation URL:
https://<api-endpoint>/webhooks/<webhookId>
External systems call the URL with Authorization: Bearer <token> and a JSON body. The token is a random 32-character string generated at webhook creation and never rotated automatically.
Configuration
Section titled “Configuration”Read-only display of:
- Target type (agent / routine)
- Target name
- Rate limit (requests per minute)
- Prompt override (for agent targets — the string the agent receives when the webhook fires)
Invocation log
Section titled “Invocation log”An expandable table of run cards, one per invocation:
- Status — succeeded / failed
- Started at / finished at
- Error message (for failures)
- Context snapshot — the JSON payload the webhook received, used for replay and debugging
REST endpoints
Section titled “REST endpoints”| Endpoint | Purpose |
|---|---|
GET /api/webhooks | List webhooks |
GET /api/webhooks/:webhookId | Detail |
GET /api/webhooks/:webhookId/runs | Invocation history |
POST /api/webhooks | Create |
PATCH /api/webhooks/:webhookId | Update |
DELETE /api/webhooks/:webhookId | Delete |
POST /api/webhooks/:webhookId/test | Manual test invocation |
External usage
Section titled “External usage”Once created, external systems trigger the webhook with a simple POST:
curl -X POST "https://<api-endpoint>/webhooks/<webhookId>" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{"message": "hello from external system", "context": {"foo": "bar"}}'The backend:
- Validates the token
- Checks the rate limit (returns 429 if exceeded)
- Invokes the target (agent turn or routine execution)
- Writes a row to the invocation log with the full payload in
context_snapshot - Returns a response once the target starts (not once it finishes)
The webhook is fire-and-forget from the caller’s perspective. If the caller wants to know the result, they should read it from the created thread or poll the run status.
Data model
Section titled “Data model”webhooks— Aurora table with id, tenant_id, name, description, token, target_type (agent/routine), agent_id / routine_id, prompt, config, enabled, rate_limit, last_invoked_at, invocation_count, created_at, updated_at- Runs —
thread_turnsrows withwebhook_idFK and acontext_snapshotfield storing the inbound JSON payload - Rate limit state — in-memory per webhook (per instance, not distributed); resets on Lambda cold start
Rate limiting
Section titled “Rate limiting”Each webhook has a per-minute rate limit (default 10). When the limit is exceeded, the backend returns HTTP 429 without invoking the target and without writing to the run log. The rate limit is a hard cap — there’s no queue or back-pressure.
Because rate limit state is per-Lambda-instance, distributed invocations can collectively exceed the declared limit by the number of warm Lambda instances. For workflows that genuinely need hard caps, use a downstream queue rather than relying on the webhook’s rate limit.
Prompt overrides
Section titled “Prompt overrides”For agent-targeted webhooks, the prompt field lets operators specify a canonical prompt that the agent receives when the webhook fires. The inbound JSON body is still available in context_snapshot and can be referenced by the agent’s tools, but the prompt override controls what the agent “hears” when the turn starts.
This is how operators ship “when something happens, do X” workflows: the prompt override says “do X” and the inbound payload carries the context.
Workflows
Section titled “Workflows”Set up a custom Zapier trigger
Section titled “Set up a custom Zapier trigger”- Click New Webhook
- Name it “Zapier → daily-summary agent”
- Target type: agent
- Target: the
daily-summaryagent - Rate limit: 10/min
- Prompt override: “A new Zapier trigger fired. Review the payload and produce a summary.”
- Save
- Copy the token and the URL
- Paste into Zapier’s webhook action
- Test from Zapier — verify the invocation appears in the log
Debug a failing webhook
Section titled “Debug a failing webhook”- Open the webhook detail page
- Scroll to the invocation log
- Expand the most recent failed row
- Check the error message
- Check
context_snapshotto see what was actually received - Common causes: token mismatch (401), rate limit (429), target agent not found or disabled (500), payload parse error (400)
Rotate a leaked token
Section titled “Rotate a leaked token”Known limits
Section titled “Known limits”- No in-place token rotation. Rotation is delete + recreate.
- Per-instance rate limiting. The rate limit is enforced per warm Lambda instance, not distributed. Distributed usage can collectively exceed the declared limit.
- No queue. Rate-limited requests are rejected, not queued.
- Fire-and-forget. The caller gets an immediate ack; the actual result lands on the thread created by the invocation.
- REST-only. Webhooks don’t flow through urql; the list refetches after each mutation.
Related pages
Section titled “Related pages”- Automations — the time-based counterpart to webhook-driven triggers, plus the multi-step routines webhooks can launch
- Agents — the other target type for webhook invocations
- Automations (concept) — the product model