A run is a single execution of an automation. When you call any TinyFish Web Agent endpoint, you create a run that moves through a lifecycle from start to finish.
Run Lifecycle
Every run moves through these statuses:
| Status | Meaning |
|---|
PENDING | Queued, waiting to start |
RUNNING | Browser is executing your goal |
COMPLETED | Finished (check result for data) |
FAILED | Infrastructure error occurred |
CANCELLED | Manually stopped |
Cancellation is only supported for runs created via /run-async or /run-sse. Runs created via the synchronous /run endpoint cannot be cancelled because the request blocks until completion.
The Run Object
When you fetch a run, you get back the following object:
{
"run_id": "abc123",
"status": "COMPLETED",
"result": { ... },
"error": null,
"streamingUrl": "https://tf-abc123.fra0-tinyfish.unikraft.app/stream/0"
}
| Field | Description |
|---|
run_id | Unique identifier for this run |
status | Current lifecycle status |
result | Your extracted data (when COMPLETED) |
error | Error details (when FAILED) |
streamingUrl | URL to watch the browser live |
Searching and Filtering Runs
GET /v1/runs supports filtering, text search, sorting, and pagination to help you find specific runs.
Query Parameters
| Parameter | Type | Description |
|---|
status | string | Filter by status: PENDING, RUNNING, COMPLETED, FAILED, CANCELLED |
goal | string | Search runs by goal text (case-insensitive partial match) |
created_after | ISO 8601 | Only return runs created after this timestamp |
created_before | ISO 8601 | Only return runs created before this timestamp |
sort_direction | asc | desc | Sort order by creation date (default: desc) |
cursor | string | Pagination cursor from a previous response |
limit | number | Results per page, 1–100 (default: 20) |
Examples
Search by goal text:
curl "https://agent.tinyfish.ai/v1/runs?goal=linkedin" \
-H "X-API-Key: YOUR_API_KEY"
Filter by status and date range:
curl "https://agent.tinyfish.ai/v1/runs?status=COMPLETED&created_after=2026-01-01T00:00:00Z&created_before=2026-02-01T00:00:00Z" \
-H "X-API-Key: YOUR_API_KEY"
Oldest first with pagination:
curl "https://agent.tinyfish.ai/v1/runs?sort_direction=asc&limit=10" \
-H "X-API-Key: YOUR_API_KEY"
The response includes a pagination object with total, next_cursor, and has_more:
{
"data": [ ... ],
"pagination": {
"total": 142,
"next_cursor": "eyJpZCI6...",
"has_more": true
}
}
Pass next_cursor as the cursor parameter to fetch the next page.
Watching Runs Live
Every run includes a streamingUrl where you can watch the browser execute in real-time. This is useful for debugging, demos, or showing users what’s happening behind the scenes.
Embed the URL in an iframe to display the live browser view in your app:
<iframe
src="https://tf-abc123.fra0-tinyfish.unikraft.app/stream/0"
width="800"
height="600"
/>
The streaming URL is valid for 24 hours after the run completes.
Understanding COMPLETED Status
COMPLETED means the infrastructure worked, not that your goal succeeded.
Always check the result field:
Goal succeeded:
{
"status": "COMPLETED",
"result": {
"products": [
{ "name": "Widget", "price": 29.99 }
]
}
}
Infrastructure worked, goal failed:
The browser worked fine, but TinyFish Web Agent couldn’t achieve your goal.
{
"status": "COMPLETED",
"result": {
"status": "failure",
"reason": "Could not find any products on the page"
}
}
Handling Run Results
Use this pattern to handle both infrastructure failures and goal failures in your code.
async function handleTinyFishResponse(run: TinyFishRun) {
switch (run.status) {
case "COMPLETED":
if (!run.result) {
return { success: false, error: "No result returned" };
}
// Check for goal-level failure in result
if (run.result.status === "failure" || run.result.error) {
return {
success: false,
error: run.result.reason || run.result.error || "Goal not achieved",
};
}
return { success: true, data: run.result };
case "FAILED":
return {
success: false,
error: run.error?.message || "Automation failed",
retryable: true,
};
case "CANCELLED":
return { success: false, error: "Run was cancelled" };
default:
return { success: false, error: `Unexpected status: ${run.status}` };
}
}
Cancelling Runs
You can cancel a run that is PENDING or RUNNING by sending a POST request to /v1/runs/{id}/cancel. This works for runs created via /run-async or /run-sse only.
const response = await fetch(`https://agent.tinyfish.ai/v1/runs/${runId}/cancel`, {
method: "POST",
headers: {
"X-API-Key": process.env.TINYFISH_API_KEY,
},
});
const result = await response.json();
// result.status: CANCELLED, COMPLETED, or FAILED
// result.cancelled_at: timestamp if cancelled
// result.message: additional context (e.g. "Run already cancelled")
The cancel endpoint is idempotent — calling it on an already-cancelled or completed run returns the current state without error.
| Scenario | Response status | cancelled_at | message |
|---|
| Run cancelled | CANCELLED | Timestamp | null |
| Already cancelled | CANCELLED | Timestamp | "Run already cancelled" |
| Already completed | COMPLETED | null | "Run already finished" |
Only runs created via the API (/run-async or /run-sse) can be cancelled using this endpoint. Runs created through the dashboard UI or via the synchronous /run endpoint cannot be cancelled.