Skip to main content
Webhooks let you receive an HTTP callback when a run reaches a terminal state, so you don’t need to poll for results.

How It Works

  1. Pass a webhook_url when you create a run
  2. When the run finishes (COMPLETED, FAILED, or CANCELLED), TinyFish sends a POST request to your URL
  3. The payload contains the full run data — the same shape as GET /v1/runs/{id}
Webhook delivery is non-blocking. If your endpoint is down, the run still succeeds — you can always fetch the result via the API.

Configuration

Add webhook_url to any run creation endpoint. The URL must use HTTPS.
Webhooks are supported on all run endpoints: /run, /run-async, /run-sse, and /run-batch.

Payload

Your endpoint receives a POST request with Content-Type: application/json:

Minimal Example

A simplified view of the webhook payload with just the key fields:

Event Types

EventWhen
run.completedRun finished (check result for data)
run.failedInfrastructure error occurred
run.cancelledRun was manually cancelled

Payload Fields

FieldTypeDescription
eventstringEvent type (e.g. run.completed)
run_idstringUnique run identifier
statusstringCOMPLETED, FAILED, or CANCELLED
dataobjectFull run data — same shape as GET /v1/runs/{id}
data.resultobject | nullExtracted data (when completed)
data.errorobject | nullError details (when failed)
data.stepsarrayList of actions the agent took
Screenshots are not included in webhook payloads to keep the payload size small. To get screenshots, call GET /v1/runs/{id}?screenshots=base64 after receiving the webhook.

Error Payload

When a run fails, data.error contains details about what went wrong:

Retry Behavior

TinyFish retries failed webhook deliveries automatically:
BehaviorDetail
Total attempts4 (1 initial + 3 retries)
BackoffExponential: 1s, 2s, 4s
Timeout10 seconds per attempt
4xx responsesNo retry (fails immediately)
5xx responsesRetried with backoff
Network errorsRetried with backoff

Receiving Webhooks

Here’s how to handle webhook events on your server:

Best Practices

TinyFish waits up to 10 seconds for your response. Do heavy processing asynchronously — acknowledge the webhook immediately and handle the data in the background.
In rare cases (network retries, server restarts), you may receive the same webhook more than once. Use run_id to deduplicate.
For sensitive workflows, confirm the webhook data by calling GET /v1/runs/{run_id} before acting on the payload.
Any 2xx response acknowledges the webhook. Non-2xx responses trigger retries (except 4xx, which fail immediately).

Runs

Understand run lifecycle and statuses

Endpoints

Choose sync, async, or streaming