Skip to content

Request a result export

POST
/api/v1/bi/queries/{id}/exports
Code sample: cURL
curl -X POST 'https://api.justcrawl.io/api/v1/bi/queries/$JOB_ID/exports' \
-H 'Authorization: Bearer $JUSTCRAWL_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"format":"csv"}'

Enqueue a CSV or Parquet export of a completed query’s results, then poll GET /api/v1/bi/exports/{exportId} for the download link.

The status code tells you whether work was started. 202 means a new export was enqueued (reused: false); 200 means an existing queued, running, or ready export for the same query and format was returned instead (reused: true). Repeated clicks therefore collapse onto one job rather than fanning out. A previously failed export is never reused — asking again after a failure starts a fresh attempt.

Exports are capped at 100000 rows and 268435456 stored JSONL bytes (both configurable per deployment); a larger result returns 400 result_too_large with the measured and maximum row/byte values as siblings of error. Narrow the query with LIMIT or WHERE and re-run it.

id
required
string format: uuid

The source query. Must have reached success.

Media typeapplication/json
object
format
required
string
Allowed values: csv parquet

An existing export was reused rather than starting a new one

Media typeapplication/json
object
export
required

A CSV or Parquet export of a completed query. Exports are materialized asynchronously.

object
id
required
string format: uuid
queryId
required
string format: uuid
format
required
string
Allowed values: csv parquet
status
required
string
Allowed values: queued running ready failed
rowCount
required
integer
nullable
byteSize
required
integer
nullable
attemptGeneration
required

Current fenced worker generation. The ready object key names exactly this generation.

integer
attempts
required

Durable processing/recovery attempts consumed by this export.

integer
errorCode
required

Machine-readable failure reason, present only when status is failed. One of: source_unavailable, source_malformed, source_too_large, source_read_failed, upload_failed, encoding_error, or retry_exhausted. Every terminal response retains both export and source-query ids.

string
nullable
errorMessage
required

Customer-safe description of the failure, present only when status is failed. Never raw exception, driver, or cloud-provider text — see errorCode for the machine-readable reason.

string
nullable
requestedAt
required
string format: date-time
startedAt
required
string format: date-time
nullable
completedAt
required
string format: date-time
nullable
downloadUrl
required

Presigned S3 credential granting read access to the export bytes with no authentication. Expires after downloadUrlExpiresInSec and is re-issued on every poll, so fetch it when you need it — never log, cache, or forward it. Null until status is ready.

string format: uri
nullable
downloadUrlExpiresInSec
required

Lifetime of downloadUrl in seconds. Null whenever downloadUrl is null.

integer
nullable
reused
required
boolean
Example
{
"export": {
"format": "csv",
"status": "queued"
}
}

A new export was enqueued

Media typeapplication/json
object
export
required

A CSV or Parquet export of a completed query. Exports are materialized asynchronously.

object
id
required
string format: uuid
queryId
required
string format: uuid
format
required
string
Allowed values: csv parquet
status
required
string
Allowed values: queued running ready failed
rowCount
required
integer
nullable
byteSize
required
integer
nullable
attemptGeneration
required

Current fenced worker generation. The ready object key names exactly this generation.

integer
attempts
required

Durable processing/recovery attempts consumed by this export.

integer
errorCode
required

Machine-readable failure reason, present only when status is failed. One of: source_unavailable, source_malformed, source_too_large, source_read_failed, upload_failed, encoding_error, or retry_exhausted. Every terminal response retains both export and source-query ids.

string
nullable
errorMessage
required

Customer-safe description of the failure, present only when status is failed. Never raw exception, driver, or cloud-provider text — see errorCode for the machine-readable reason.

string
nullable
requestedAt
required
string format: date-time
startedAt
required
string format: date-time
nullable
completedAt
required
string format: date-time
nullable
downloadUrl
required

Presigned S3 credential granting read access to the export bytes with no authentication. Expires after downloadUrlExpiresInSec and is re-issued on every poll, so fetch it when you need it — never log, cache, or forward it. Null until status is ready.

string format: uri
nullable
downloadUrlExpiresInSec
required

Lifetime of downloadUrl in seconds. Null whenever downloadUrl is null.

integer
nullable
reused
required
boolean
Example
{
"export": {
"format": "csv",
"status": "queued"
}
}

Unsupported format (invalid_format), or the result exceeds an export row/byte cap (result_too_large)

Media typeapplication/json
object
error
required
object
code
required

Stable, machine-readable error code. Match on this, not on message.

string
message
required

Customer-safe description. Never raw exception or driver text, with one deliberate exception: a syntax_error (SQLSTATE 42601) passes the database’s own message through verbatim, because it describes SQL the caller wrote themselves and names nothing they could not already see — see the root CLAUDE.md §Error reporting for the full carve-out.

string
docs_url
required

Reference page for this code. Codes shared with the rest of the API have their own page; the BI-local vocabulary points at the single BI errors page that tabulates all of them.

string format: uri
request_id
required

Correlation id. Identical to the X-Request-ID response header — quote either one to support.

string
error
required
object
code
string
Allowed values: invalid_format result_too_large
rowCount

Rows in the source result. Present on result_too_large only, alongside error.

integer
maxRowCount

The export row cap. Present on result_too_large only.

integer
byteSize

Stored JSONL bytes in the source result. Present on result_too_large only.

integer
nullable
maxByteSize

The export source-byte cap. Present on result_too_large only.

integer
Example
{
"error": {
"code": "invalid_format"
}
}

Missing or invalid authentication token

Media typeapplication/json
object
error
string
Example
{
"error": "Missing or invalid authentication token"
}

Access to the BI surface itself is refused. no_org and feature_disabled fire on every BI route from the mount guard, before any handler runs — feature_disabled is the first response most new integrations see, because the SQL console is entitled per organization. Permission and verified-email gates use insufficient_permissions and email_not_verified; rls_denied and kill_switched come from the engine. This response never describes resource-level authorization: an id you do not own returns 404, not 403.

Media typeapplication/json
object
error
required
object
code
required

Stable, machine-readable error code. Match on this, not on message.

string
message
required

Customer-safe description. Never raw exception or driver text, with one deliberate exception: a syntax_error (SQLSTATE 42601) passes the database’s own message through verbatim, because it describes SQL the caller wrote themselves and names nothing they could not already see — see the root CLAUDE.md §Error reporting for the full carve-out.

string
docs_url
required

Reference page for this code. Codes shared with the rest of the API have their own page; the BI-local vocabulary points at the single BI errors page that tabulates all of them.

string format: uri
request_id
required

Correlation id. Identical to the X-Request-ID response header — quote either one to support.

string
error
required
object
code
string
Allowed values: no_org feature_disabled insufficient_permissions email_not_verified authentication_required user_not_found rls_denied kill_switched
Example
{
"error": {
"code": "feature_disabled",
"message": "SQL console is not enabled for this organization",
"docs_url": "https://docs.justcrawl.io/guides/errors/bi",
"request_id": "req_9f3a1c7e2b40"
}
}

Not found, or not owned by your organization. The two are deliberately indistinguishable so cross-tenant existence cannot be probed

Media typeapplication/json

Error envelope returned by every /api/v1/bi/* handler error. Unlike the rest of the API — where the structured shape is opt-in via the application/vnd.justcrawl.v1+json media type — a BI handler always emits it, and all four fields are always present. The one exception: 401s from missing or invalid auth are rejected by shared middleware before any BI handler runs, so they carry the flat { "error": "<message>" } shape (Error schema) instead — see the Unauthorized response on each operation.

object
error
required
object
code
required

Stable, machine-readable error code. Match on this, not on message.

string
message
required

Customer-safe description. Never raw exception or driver text, with one deliberate exception: a syntax_error (SQLSTATE 42601) passes the database’s own message through verbatim, because it describes SQL the caller wrote themselves and names nothing they could not already see — see the root CLAUDE.md §Error reporting for the full carve-out.

string
docs_url
required

Reference page for this code. Codes shared with the rest of the API have their own page; the BI-local vocabulary points at the single BI errors page that tabulates all of them.

string format: uri
request_id
required

Correlation id. Identical to the X-Request-ID response header — quote either one to support.

string
Example
{
"error": {
"code": "not_found",
"message": "Query not found",
"docs_url": "https://docs.justcrawl.io/guides/errors/not_found",
"request_id": "req_9f3a1c7e2b40"
}
}

The source query has not reached success (not_ready)

Media typeapplication/json
object
error
required
object
code
required

Stable, machine-readable error code. Match on this, not on message.

string
message
required

Customer-safe description. Never raw exception or driver text, with one deliberate exception: a syntax_error (SQLSTATE 42601) passes the database’s own message through verbatim, because it describes SQL the caller wrote themselves and names nothing they could not already see — see the root CLAUDE.md §Error reporting for the full carve-out.

string
docs_url
required

Reference page for this code. Codes shared with the rest of the API have their own page; the BI-local vocabulary points at the single BI errors page that tabulates all of them.

string format: uri
request_id
required

Correlation id. Identical to the X-Request-ID response header — quote either one to support.

string
error
required
object
code
string
Allowed values: not_ready
status
string
Allowed values: queued running failed canceled
Example
{
"error": {
"code": "not_ready"
},
"status": "queued"
}

Unexpected server error. Full detail goes to the logs and PostHog $exception capture, never the response

Media typeapplication/json

Error envelope returned by every /api/v1/bi/* handler error. Unlike the rest of the API — where the structured shape is opt-in via the application/vnd.justcrawl.v1+json media type — a BI handler always emits it, and all four fields are always present. The one exception: 401s from missing or invalid auth are rejected by shared middleware before any BI handler runs, so they carry the flat { "error": "<message>" } shape (Error schema) instead — see the Unauthorized response on each operation.

object
error
required
object
code
required

Stable, machine-readable error code. Match on this, not on message.

string
message
required

Customer-safe description. Never raw exception or driver text, with one deliberate exception: a syntax_error (SQLSTATE 42601) passes the database’s own message through verbatim, because it describes SQL the caller wrote themselves and names nothing they could not already see — see the root CLAUDE.md §Error reporting for the full carve-out.

string
docs_url
required

Reference page for this code. Codes shared with the rest of the API have their own page; the BI-local vocabulary points at the single BI errors page that tabulates all of them.

string format: uri
request_id
required

Correlation id. Identical to the X-Request-ID response header — quote either one to support.

string
Example
{
"error": {
"code": "internal_error",
"message": "Failed to list queries",
"docs_url": "https://docs.justcrawl.io/guides/errors/internal_error",
"request_id": "req_9f3a1c7e2b40"
}
}