API Keys and Webhooks
Yes, there is an API, and which one you want depends on what you are driving. The workspace MCP endpoint is the programmatic interface to a workspace: an MCP client or script connected with a workspace API key can list and create agents, start and read sessions, and work with documents, data tables, boards, and the inbox. An agent API serves one agent’s tools to outside callers, who sign in with OAuth or a machine credential; see Give an Agent an API. A webhook starts an assignment run from any system that can send an HTTP POST, and is covered on this page. Other agent frameworks can also delegate work over A2A. There is no published REST API reference beyond these.
The workspace API key is the credential for all of them except the
agent API. A webhook caller presents it in an X-API-Key header; MCP and
A2A clients send it as Authorization: Bearer wak_….
The webhook surface is deliberately narrow. Everything about what happens — the instructions, the tools, the deliverable — lives on the assignment; the webhook only says now, and optionally hands over a payload. That keeps the integration contract small enough to fit in one table (below) while still covering the real cases: a ticketing system that wants an agent on every new ticket, a form tool that wants each submission enriched, a CI pipeline that wants a report after each deploy. Any system that can send an HTTP POST can start agent work.
Workspace API keys
Section titled “Workspace API keys”Manage keys in Workspace settings → API keys. Workspace admins create, rotate, and revoke keys; other members see the list.
- New API key asks only for a name. The full key — it starts with
wak_— is shown exactly once: “This is the only time the full key will be shown. Store it securely.” Afterward, the list shows only each key’s prefix and when it was last used. - Rotate issues a replacement key (also shown once) and revokes the old one.
- Revoke disables a key immediately.
A key acts as the person who created it, and only while they remain a member of the workspace. When someone leaves, their keys are revoked, so the callers that used them need a key from someone who is staying.
Because rotating issues a new key, every webhook bound to the old one refuses deliveries until it is bound to the replacement. Webhook consumer updates, below the key list, shows each webhook assignment with the key it is bound to, marked Bound to active key or Replacement needed; Update binding points it at the replacement. Then give the calling system the new key.
Name keys after their callers (ticketing-webhook, ci-pipeline) so
rotation and revocation stay surgical. When the ticketing vendor has an
incident, you rotate ticketing-webhook, rebind the one assignment that
uses it, and the CI pipeline never notices; when a system is decommissioned,
you revoke its key and nothing else changes. One shared key across callers
turns every one of those events into an all-hands re-credentialing.
The webhook contract
Section titled “The webhook contract”On an assignment’s Schedule tab, under Triggers, check Run via webhook, choose the API key callers will present, and set a Webhook path. The contract:
| Method | POST |
| URL | https://workprentice.ai/api/v1/hooks/<workspace-id>/<path> |
| Auth | X-API-Key: wak_… header carrying the key bound to this webhook, or sender-signature mode below |
| Body | Optional JSON, up to 5 MiB — delivered to the run as its webhook payload |
| Dry run | Append ?run_type=dry_run to hold back the assignment’s follow-up hooks |
| Success | 200 with the started session’s id, "status": "started", and the run type |
| Errors | 400 invalid JSON · 401 bad or missing credential · 403 paused assignment or agent · 404 unknown path · 413 body over 5 MiB (a 401 in sender-signature mode) |
A credential is required in either mode. Every delivery starts a real agent
run, so a webhook with no credential bound is not an open endpoint — it
rejects every call with a 401 until you bind an API key (the default
mode) or a signing secret (sender-signature mode, below). Only the bound key
opens it: another valid key from the same workspace is refused too.
Sender-signature authentication
Section titled “Sender-signature authentication”Some SaaS senders cannot set custom headers on their webhook deliveries, so
they cannot present an API key. Intercom is the canonical example: it signs
each delivery instead, sending an X-Hub-Signature header carrying an
HMAC-SHA1 of the raw request body computed with your Intercom app’s client
secret. Senders that sign with SHA-256 send X-Hub-Signature-256 instead, and
both are accepted. A delivery that carries both headers is verified against
the SHA-256 one.
For those senders, switch the webhook’s Authentication to Sender
signature and paste the Signing secret (for Intercom, the app’s
client secret from its Basic Info page). Deliveries then authenticate by
signature: a missing or wrong signature is a 401, exactly like a
bad API key. Because the body is what gets verified, it is read before
the caller is authenticated, so a body over 5 MiB, or one that arrives too
slowly, is also a 401 in this mode; an unauthenticated
caller cannot tell which mode a webhook uses. The secret is write-only — it
is never shown again after saving — and can be rotated by pasting a new
value. Everything else in the contract, including ?run_type=dry_run, works
the same in both modes.
A worked call
Section titled “A worked call”Suppose a support assignment listens at the path ticketing/new-ticket.
While you are still tuning the instructions, rehearse with a dry run and a
sample ticket. A dry run holds back the follow-up actions listed on the
assignment’s Hooks tab, but the agent’s own tool calls still happen, so
point early tests at records it is safe to change:
curl -X POST \ "https://workprentice.ai/api/v1/hooks/<workspace-id>/ticketing/new-ticket?run_type=dry_run" \ -H "X-API-Key: wak_..." \ -H "Content-Type: application/json" \ -d '{"ticket_id": "12345", "subject": "Cannot log in"}'A successful trigger returns the session that started:
{ "session_id": "…", "status": "started", "run_type": "dry_run" }Open that session in Workprentice to watch the run. The JSON body is handed
to the agent as the webhook payload, so the assignment’s instructions can
refer to it directly — “enrich the ticket in the payload” — and each caller
can send whatever fields its runs need. When the output looks right, drop
the run_type parameter and point the real system at the same URL; every
delivery starts a session and returns its id, so the calling system can link
straight to the run.
A 404 means the path matches no webhook-enabled assignment in the
workspace: the path is unknown, the assignment is archived, or its webhook
trigger was turned off. A 403 means the assignment or its agent is paused,
the agent is archived, or the agent is a template, which never runs. The
credential is checked before any 403 case, so a caller without a valid
credential gets a 401 and cannot learn the assignment’s or agent’s state;
only an authenticated caller sees the 403.
The webhook guide walks the full setup with example calls, from creating the key to going live.
Patterns that work
Section titled “Patterns that work”- One key per caller —
ticketing-webhook,ci-pipeline,forms-intake. Rotation and revocation stay scoped to the one system involved. - Dry run while iterating — keep
?run_type=dry_runon the URL until the sessions look right, then remove it. Same endpoint, same payloads, and the assignment’s follow-up hooks held back; send sample records, since the agent’s own tool calls still run. - Pause as the off switch — pausing the assignment makes its webhook
return
403, so you can take an intake offline during an incident without revoking any keys, and turn it back on just as cheaply. - Payload-aware instructions — write the assignment’s instructions
against the payload’s fields (“look up
ticket_id, draft a response tosubject”), so the caller controls the input and the assignment controls everything else.
For the complete site index, see llms.txt.