Skip to content
Thyme Docs

Executable Webhooks

Webhooks let an external service invoke an active executable without a workspace API key. They are additive: the executable's cron or interval schedule continues to run.

Where webhooks are enabled, workspace owners and admins manage webhook URLs from Console → Executables → executable detail → Webhooks. Each executable can have up to ten active, named URLs.

Generate and protect the URL

Click Generate URL, give the caller a recognizable name, and copy the URL from the shown-once dialog. Thyme stores only a SHA-256 hash of its 256-bit secret, so the URL cannot be recovered later. If it is lost, rotate it. If it is exposed, revoke or rotate it immediately.

Rotating invalidates the old URL immediately and reveals a replacement once. Revocation is permanent and also blocks retained result links for that named webhook.

Invoke with predefined args

An empty POST, a whitespace-only body, or {} runs with the executable's predefined args.

curl --request POST "$THYME_WEBHOOK_URL" \
  --header "Idempotency-Key: deploy-event-001"

Invoke with custom args

A non-empty object completely replaces predefined args; values are never merged. It must fully satisfy the function's uploaded args schema.

curl --request POST "$THYME_WEBHOOK_URL" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: rebalance-event-001" \
  --data '{"recipient":"0x1111111111111111111111111111111111111111","amount":10}'

The body limit is 256 KiB. Arrays, scalars, null, malformed JSON, missing required fields, and wrong types are rejected before execution. A function without an args schema accepts only the empty/predefined mode.

Idempotency and limits

Idempotency-Key is optional, 1–128 characters, and retained for 24 hours per named webhook. Retrying the same request with the same key returns the original execution. Reusing the key with different custom args returns 409 idempotency_conflict.

Use a key for any executable that may submit a transaction: without one, retrying after a network timeout can create a second execution.

Each named URL accepts at most 60 new executions per minute. A second request is rejected with 409 execution_in_progress while the executable already has an active execution or storage lock.

Responses

Thyme waits up to 55 seconds for final post-processing. A fast execution returns 200 with:

  • Execution status and ID
  • Transaction and UserOperation hashes when submitted
  • Gas, chain, timing, CU, and submitted-call metadata
  • A 24-hour snapshot when the execution updated storage
  • A sanitized semantic error for failed or skipped executions

Execution-level failed and skipped outcomes still use HTTP 200: the webhook was accepted and delivered successfully, and data.status describes the task outcome. Validation, authentication, rate, and availability errors use 4xx status codes.

If work is still running, the response is 202 Accepted with Location, Retry-After: 2, and data.resultUrl. Poll that URL with GET. Send Prefer: respond-async to skip the initial wait and receive 202 immediately.

A submitted_unknown outcome can remain unresolved after a receipt timeout; use the recorded hashes and authenticated monitoring to reconcile it before submitting another logical action. Results and updated-storage snapshots expire after 24 hours. Full sandbox logs are available through the authenticated Console and management API/CLI, not in webhook responses.

Common errors

HTTPCodeMeaning
404not_foundURL is unknown, invalid, rotated, or revoked.
409executable_unavailableExecutable/function is not active.
409execution_in_progressAnother run currently owns the executable.
409idempotency_conflictKey was reused with a different request.
413body_too_largeBody exceeds 256 KiB.
415unsupported_media_typeNon-empty body is not JSON.
422invalid_argumentsCustom args do not satisfy the schema.
422arguments_schema_missingCustom args were sent to a schema-less function.
429rate_limitedNamed webhook exceeded 60 new executions/minute.