Trawl docs
API reference

Trawl API.

AI web extraction as an async job API. Every endpoint, request, and response — generated from the live OpenAPI spec.

Base URL

https://api.trawl.productcraft.co

Auth

Authorization: Bearer …

Spec version

OpenAPI 3.0.0 · v0.1.0

Webhooks

get/v1/workspaces/{workspace_id}/webhooksAuth

List webhooks for the workspace (secrets masked)

Path parameters

workspace_id*string

Response · 200

data*array

Example

Request

GET /v1/workspaces/{workspace_id}/webhooks
Authorization: Bearer YOUR_TOKEN

Response

{
  "data": [
    {
      "id": "string",
      "workspace_id": "string",
      "url": "string",
      "active": false,
      "failure_count": 0,
      "last_status_code": 0,
      "last_attempt_at": "string",
      "auto_disabled_at": "string",
      "first_failure_at": "string",
      "created_at": "string"
    }
  ]
}
post/v1/workspaces/{workspace_id}/webhooksAuth

Create a workspace webhook. The response includes the signing secret in clear EXACTLY ONCE — copy it now.

Path parameters

workspace_id*string

Headers

Idempotency-Keystring

Stripe-style idempotency key. The signing secret is returned exactly once; a retry without this header creates a second webhook + secret. 24h TTL.

Request body

url*string

Destination URL (https required in prod).

activeboolean

Disabled webhooks are never delivered to.

Response · 201 Webhook created. Includes plaintext `signing_secret` exactly once.

id*string
workspace_id*string
url*string
active*boolean
failure_count*number
last_status_code*number
last_attempt_at*string
auto_disabled_at*string
first_failure_at*string
created_at*string
signing_secret*string

Plaintext signing secret returned EXACTLY ONCE on create + rotate. Persist immediately — it never appears on subsequent GETs.

Example

Request

POST /v1/workspaces/{workspace_id}/webhooks
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "url": "string",
  "active": false
}

Response

{
  "id": "string",
  "workspace_id": "string",
  "url": "string",
  "active": false,
  "failure_count": 0,
  "last_status_code": 0,
  "last_attempt_at": "string",
  "auto_disabled_at": "string",
  "first_failure_at": "string",
  "created_at": "string",
  "signing_secret": "string"
}
get/v1/workspaces/{workspace_id}/webhooks/{id}Auth

Get a webhook (secret masked)

Path parameters

workspace_id*string
id*string

Response · 200

id*string
workspace_id*string
url*string
active*boolean
failure_count*number
last_status_code*number
last_attempt_at*string
auto_disabled_at*string
first_failure_at*string
created_at*string

Example

Request

GET /v1/workspaces/{workspace_id}/webhooks/{id}
Authorization: Bearer YOUR_TOKEN

Response

{
  "id": "string",
  "workspace_id": "string",
  "url": "string",
  "active": false,
  "failure_count": 0,
  "last_status_code": 0,
  "last_attempt_at": "string",
  "auto_disabled_at": "string",
  "first_failure_at": "string",
  "created_at": "string"
}
patch/v1/workspaces/{workspace_id}/webhooks/{id}Auth

Update url / active flag (active=true clears auto-disable)

Path parameters

workspace_id*string
id*string

Request body

urlstring

New destination URL.

activeboolean

Pause/resume the webhook. Setting active=true clears auto-disable.

Response · 200

id*string
workspace_id*string
url*string
active*boolean
failure_count*number
last_status_code*number
last_attempt_at*string
auto_disabled_at*string
first_failure_at*string
created_at*string

Example

Request

PATCH /v1/workspaces/{workspace_id}/webhooks/{id}
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "url": "string",
  "active": false
}

Response

{
  "id": "string",
  "workspace_id": "string",
  "url": "string",
  "active": false,
  "failure_count": 0,
  "last_status_code": 0,
  "last_attempt_at": "string",
  "auto_disabled_at": "string",
  "first_failure_at": "string",
  "created_at": "string"
}
delete/v1/workspaces/{workspace_id}/webhooks/{id}Auth

Delete a webhook

Path parameters

workspace_id*string
id*string

Response · 204

No content.

get/v1/workspaces/{workspace_id}/webhooks/{id}/deliveriesAuth

Recent delivery attempts for a webhook (default 50, max 200, newest first)

Path parameters

workspace_id*string
id*string

Response · 200

Recent delivery attempts.

post/v1/workspaces/{workspace_id}/webhooks/{id}/rotate-secretAuth

Rotate the signing secret. Returns the new secret in clear EXACTLY ONCE.

Path parameters

workspace_id*string
id*string

Response · 201

No content.

post/v1/workspaces/{workspace_id}/webhooks/{id}/testAuth

Fire a synthetic event to this webhook (asynchronous; check the destination logs)

Path parameters

workspace_id*string
id*string

Response · 202

No content.


Jobs

get/v1/workspaces/{workspace_id}/jobsAuth

List trawl jobs (paginated, newest first)

Path parameters

workspace_id*string

Query parameters

statusenum (5)

Filter by job status.

cursorstring

Opaque cursor for pagination.

limitnumber

Response · 200 Page of jobs with pagination cursor.

data*array
pagination*object
next_cursor*string
has_more*boolean

Example

Request

GET /v1/workspaces/{workspace_id}/jobs
Authorization: Bearer YOUR_TOKEN

Response

{
  "data": [
    {
      "id": "string",
      "workspace_id": "string",
      "status": "queued",
      "json_schema": {},
      "description": "string",
      "suggested_urls": [
        "string"
      ],
      "max_steps": 0,
      "timeout_s": 0,
      "model_tier": "string",
      "webhook_id": "string",
      "result": {},
      "error": "string",
      "attempts": 0,
      "enqueued_at": "string",
      "started_at": "string",
      "completed_at": "string",
      "created_at": "string"
    }
  ],
  "pagination": {
    "next_cursor": "string",
    "has_more": false
  }
}
post/v1/workspaces/{workspace_id}/jobsAuth

Create (enqueue) a trawl job

Path parameters

workspace_id*string

Headers

Idempotency-Keystring

Pass a key (1..256 chars, [A-Za-z0-9_\-:]) to make retries safe — replays return the original response for 24h.

Request body

json_schema*object

JSON Schema describing the shape of the extraction result. Must be a non-empty object with `type: "object"`.

Example: {"type":"object","properties":{"title":{"type":"string"}},"required":["title"]}

description*string

Natural-language description of what to extract.

Example: "Extract the product title and price from each page."

suggested_urlsarray

Seed URLs the worker should start from.

webhook_idstring

Webhook id to notify when the job finishes.

max_stepsnumber

Maximum number of worker steps before the job stops.

timeout_snumber

Wall-clock timeout for the job, in seconds.

model_tierstring

Model tier the worker should use (e.g. `standard`, `pro`).

Response · 201 Job created and queued.

id*string
workspace_id*string
status*enum (5)
json_schema*object
description*string
suggested_urls*array
max_steps*number
timeout_s*number
model_tier*string
webhook_id*string
result*object
error*string
attempts*number
enqueued_at*string
started_at*string
completed_at*string
created_at*string

Example

Request

POST /v1/workspaces/{workspace_id}/jobs
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json

{
  "json_schema": {
    "type": "object",
    "properties": {
      "title": {
        "type": "string"
      }
    },
    "required": [
      "title"
    ]
  },
  "description": "Extract the product title and price from each page.",
  "suggested_urls": [
    "string"
  ],
  "webhook_id": "string",
  "max_steps": 0,
  "timeout_s": 0,
  "model_tier": "string"
}

Response

{
  "id": "string",
  "workspace_id": "string",
  "status": "queued",
  "json_schema": {},
  "description": "string",
  "suggested_urls": [
    "string"
  ],
  "max_steps": 0,
  "timeout_s": 0,
  "model_tier": "string",
  "webhook_id": "string",
  "result": {},
  "error": "string",
  "attempts": 0,
  "enqueued_at": "string",
  "started_at": "string",
  "completed_at": "string",
  "created_at": "string"
}
get/v1/workspaces/{workspace_id}/jobs/{id}Auth

Get a single trawl job

Path parameters

workspace_id*string
id*string

Response · 200 Job row.

id*string
workspace_id*string
status*enum (5)
json_schema*object
description*string
suggested_urls*array
max_steps*number
timeout_s*number
model_tier*string
webhook_id*string
result*object
error*string
attempts*number
enqueued_at*string
started_at*string
completed_at*string
created_at*string

Example

Request

GET /v1/workspaces/{workspace_id}/jobs/{id}
Authorization: Bearer YOUR_TOKEN

Response

{
  "id": "string",
  "workspace_id": "string",
  "status": "queued",
  "json_schema": {},
  "description": "string",
  "suggested_urls": [
    "string"
  ],
  "max_steps": 0,
  "timeout_s": 0,
  "model_tier": "string",
  "webhook_id": "string",
  "result": {},
  "error": "string",
  "attempts": 0,
  "enqueued_at": "string",
  "started_at": "string",
  "completed_at": "string",
  "created_at": "string"
}
post/v1/workspaces/{workspace_id}/jobs/{id}/cancelAuth

Cancel a queued or running trawl job

Path parameters

workspace_id*string
id*string

Response · 200 Job cancelled.

id*string
workspace_id*string
status*enum (5)
json_schema*object
description*string
suggested_urls*array
max_steps*number
timeout_s*number
model_tier*string
webhook_id*string
result*object
error*string
attempts*number
enqueued_at*string
started_at*string
completed_at*string
created_at*string

Example

Request

POST /v1/workspaces/{workspace_id}/jobs/{id}/cancel
Authorization: Bearer YOUR_TOKEN

Response

{
  "id": "string",
  "workspace_id": "string",
  "status": "queued",
  "json_schema": {},
  "description": "string",
  "suggested_urls": [
    "string"
  ],
  "max_steps": 0,
  "timeout_s": 0,
  "model_tier": "string",
  "webhook_id": "string",
  "result": {},
  "error": "string",
  "attempts": 0,
  "enqueued_at": "string",
  "started_at": "string",
  "completed_at": "string",
  "created_at": "string"
}