Skip to main content
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:
StatusMeaning
PENDINGQueued, waiting to start
RUNNINGBrowser is executing your goal
COMPLETEDFinished (check result for data)
FAILEDInfrastructure error occurred
CANCELLEDManually 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,
  "streaming_url": "https://tf-abc123.fra0-tinyfish.unikraft.app/stream/0"
}
FieldDescription
run_idUnique identifier for this run
statusCurrent lifecycle status
resultYour extracted data (when COMPLETED)
errorError details (when FAILED)
streaming_urlURL 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

ParameterTypeDescription
statusstringFilter by status: PENDING, RUNNING, COMPLETED, FAILED, CANCELLED
goalstringSearch runs by goal text (case-insensitive partial match)
created_afterISO 8601Only return runs created after this timestamp
created_beforeISO 8601Only return runs created before this timestamp
sort_directionasc | descSort order by creation date (default: desc)
cursorstringPagination cursor from a previous response
limitnumberResults 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"

Pagination Response

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 streaming_url 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/${run_id}/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.
ScenarioResponse statuscancelled_atmessage
Run cancelledCANCELLEDTimestampnull
Already cancelledCANCELLEDTimestamp"Run already cancelled"
Already completedCOMPLETEDnull"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.

Endpoints

Choose sync, async, or streaming

Error Codes

Handle errors gracefully