Retrieval API endpoint
Accepts an owner-scoped durable crawl job. `max_credits` is required; the accepted request and active reader/source revisions are frozen for idempotent replay. A repeated matching idempotency key returns the original job without preparing another reservation.
/web/crawlThe endpoint returns 202 after it has persisted an owner-scoped job and its queue outbox record. Location is the configured public status URL and Retry-After suggests a three-second polling interval. An identical idempotency_key replays the original job and does not prepare another reservation.
Required body fields are idempotency_key (16–128 characters), url (absolute HTTP or HTTPS URL), and limits.max_credits (1–10,000). Optional sitemap is one of include, only, or skip and defaults to include. scope may opt into seed-host subdomains and restrict paths with anchored globs (* matches one path segment; ** matches multiple segments). Exclusions win. scope.query_policy is preserve or drop_tracking and defaults to preserve; tracking removal uses a pinned list and retains meaningful query parameters. fetch.render accepts auto or http and defaults to http; the effective browser-render cap is zero, so browser rendering and nonzero wait_for values are rejected.
limits.max_pages defaults to 100 and is bounded to 1–1,000 admitted URL tasks. Failed and skipped tasks consume a slot; retries reuse it. max_depth defaults to 2 and is bounded to 0–10; the seed has depth 0, and depth 0 performs no robots, sitemap, or link-discovery IO. timeout_seconds defaults to 300 and is bounded to 30–1,800; it counts from the moment work on the job starts, not from submission. max_total_bytes defaults to 20 MiB and is bounded to 1 KiB–100 MiB of decompressed metadata and document response bytes. max_browser_renders is fixed at 0. The trusted effective max_credits cap may be lower than 10,000.
The job uses a durable cursor and records one terminal outcome for each admitted URL. Sitemap and robots discovery are bounded and sitemap-only mode keeps the explicit seed while disabling page-link expansion. Source-profile changes stop further IO for an accepted job; already checkpointed results remain available.
A job waits at most 30 minutes in the queue before work starts. If it has not started by then it fails with a timeout error ("job was not started within the 30-minute queue limit"), nothing is charged, and the submission can be retried. deadline_at in the submission response is the latest possible finish time (30 minutes of queue wait plus timeout_seconds); once the job starts, deadline_at in the status response moves earlier to the start time plus timeout_seconds.
The response envelope contains job_id, state, replayed, status_url, results_url, and deadline_at. The state values are queued, running, cancelling, succeeded, failed, and cancelled.
Example request:
{
"idempotency_key": "crawl-docs-example-0001",
"url": "https://example.org/docs/",
"scope": {
"include_paths": ["/docs/**"],
"query_policy": "preserve"
},
"sitemap": "include",
"limits": {
"max_pages": 100,
"max_depth": 2,
"max_credits": 100
}
}
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| request (body) | object | Yes | Bounded crawl request |
curl -X POST "https://api.crawlora.net/api/v1/web/crawl" \
-H "x-api-key: $CRAWLORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"fetch":{"max_age":0,"only_main_content":true,"render":"http","wait_for":0},"idempotency_key":"string","limits":{"max_browser_renders":0,"max_credits":1,"max_depth":2,"max_pages":100,"max_total_bytes":20971520,"timeout_seconds":300},"scope":{"exclude_paths":["string"],"include_paths":["string"],"include_subdomains":true,"query_policy":"preserve"},"sitemap":"include","url":"string"}'{
"fetch": {
"max_age": 0,
"only_main_content": true,
"render": "http",
"wait_for": 0
},
"idempotency_key": "string",
"limits": {
"max_browser_renders": 0,
"max_credits": 1,
"max_depth": 2,
"max_pages": 100,
"max_total_bytes": 20971520,
"timeout_seconds": 300
},
"scope": {
"exclude_paths": [
"string"
],
"include_paths": [
"string"
],
"include_subdomains": true,
"query_policy": "preserve"
},
"sitemap": "include",
"url": "string"
}{
"code": 202,
"msg": "Accepted",
"data": {
"job_id": "opaque-job-id",
"state": "queued",
"replayed": false,
"status_url": "https://api.crawlora.net/api/v1/web/crawl/opaque-job-id",
"results_url": "https://api.crawlora.net/api/v1/web/crawl/opaque-job-id/results",
"deadline_at": "2026-10-09T04:35:00Z"
}
}Request schema
#/definitions/crawlretrieval.crawlRequestDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| fetch | crawlretrieval.crawlFetchDoc | No | ||||
| fetch.max_age | integer | No | min 0, max 604800000 | |||
| fetch.only_main_content | boolean | No | ||||
| fetch.render | string | No | auto, http | http | ||
| fetch.wait_for | integer | No | min 0, max 0 | |||
| idempotency_key | string | Yes | ||||
| limits | crawlretrieval.crawlLimitsDoc | Yes | ||||
| limits.max_browser_renders | integer | No | min 0, max 0 | 0 | ||
| limits.max_credits | integer | Yes | min 1, max 10000 | |||
| limits.max_depth | integer | No | min 0, max 10 | 2 | ||
| limits.max_pages | integer | No | min 1, max 1000 | 100 | ||
| limits.max_total_bytes | integer | No | min 1024, max 104857600 | 20971520 | ||
| limits.timeout_seconds | integer | No | min 30, max 1800 | 300 | ||
| scope | crawlretrieval.crawlScopeDoc | No | ||||
| scope.exclude_paths | array | No | ||||
| scope.include_paths | array | No | ||||
| scope.include_subdomains | boolean | No | ||||
| scope.query_policy | string | No | preserve, drop_tracking | preserve | ||
| sitemap | string | No | include, only, skip | include | ||
| url | string · uri | Yes |
Response schema
No response schema
| Status | Description | Schema |
|---|---|---|
| 400 | Invalid request or idempotency conflict | #/definitions/app.Response |
| 401 | Authentication required | #/definitions/app.Response |
| 402 | Insufficient credits or daily budget | #/definitions/app.Response |
| 404 | Resource not found | #/definitions/app.Response |
| 429 | Rate or active job quota exceeded | #/definitions/app.Response |
| 500 | Internal configuration or storage error | #/definitions/app.Response |
| 503 | Required backend or source profile unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X POST "https://api.crawlora.net/api/v1/web/crawl" \
-H "x-api-key: $CRAWLORA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"fetch":{"max_age":0,"only_main_content":true,"render":"http","wait_for":0},"idempotency_key":"string","limits":{"max_browser_renders":0,"max_credits":1,"max_depth":2,"max_pages":100,"max_total_bytes":20971520,"timeout_seconds":300},"scope":{"exclude_paths":["string"],"include_paths":["string"],"include_subdomains":true,"query_policy":"preserve"},"sitemap":"include","url":"string"}'