Skip to main content

AutessaDB Analytics API

Query analytics tables from your own code: describe what a table holds, run read-only SQL as a job, page through or download the result, and keep the table fed by loading files or appending rows.

Every request is a POST with a JSON body to https://api.autessa.com/clients/autessadb/analytics/<operation>, with the analytics table's ID in the resourceId query parameter and your API key in the Authorization header (no Bearer prefix). For a query that joins several tables, resourceId is the primary table, and the key needs READ on every table the query reads.

Permissions​

PermissionOperations
READdescribe, preview, estimate, query, job-status, job-results, job-download-url, cancel, jobs
WRITEload-from-s3, append-rows

Creating tables, changing columns, and editing the semantic layer are on the Analytics Poweruser API and in the builder.

Values in results​

Rows are JSON objects keyed by column name. Values keep their exact meaning:

Column typeJSON value
STRING, BOOLEAN, INT, DOUBLEString, boolean, or number
LONGNumber, or a string when the value is too large to be exact in JSON
DECIMALString, e.g. "1284410.50"
DATE"2026-10-01"
TIMESTAMP, TIMESTAMPTZISO-8601 UTC string, e.g. "2026-10-01T00:00:00Z"
STRING_LISTArray of strings
JSONThe JSON value
emptynull

Queries are jobs​

Every query, load, and append runs as a job. Queries run asynchronously and typically take a few seconds; large scans take longer. Queries are written in ANSI SQL; date and approximate functions use the standard analytical names such as date_trunc('month', ts), approx_distinct(col), and format_datetime(ts, 'yyyy-MM').

A typical query:

  1. Run a query with waitMs up to 20 seconds. If the job finishes in that time, it comes back SUCCEEDED with a preview of the first 200 rows.
  2. If the state is QUEUED or RUNNING, call Get job status with waitMs until it finishes.
  3. Page through Get job results, or get a download link for the whole result.

Results are kept for 7 days. A query can run for at most 15 minutes (less on some plans) before it ends as TIMED_OUT.

Uploading a file to load​

Files for Load files are uploaded with the client intake endpoints at https://api.autessa.com/clients/autessadb-intake, which send the bytes straight to storage in parts:

  1. POST /multipart-initiate with {"fileName": "orders-2026-09.csv"} returns uploadId, s3Key, and s3Uri.
  2. POST /multipart-part-urls with uploadId, s3Key, and partNumbers returns a partUrls map. PUT each part (at least 5 MB except the last) to its link and keep each response's ETag header.
  3. POST /multipart-complete with uploadId, s3Key, and partETags (part number to ETag) returns the final s3Uri.

The CLI does all of this for you with autessa autessadb analytics load --localFile.


Describe tables​

POST/describe

Returns everything needed to query one or more analytics tables: SQL name, description, grain, row count, partition columns, columns with types and descriptions, measures, joins, and verified queries. Columns the caller cannot see are omitted. Agents should call this before writing SQL.

Permission: READ on every table described

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    tableIds
    Type
    array<string>
    Description

    Additional tables to describe in the same call.

  • Name
    includeStats
    Type
    boolean
    Description

    Include per-column statistics (null count, distinct count, minimum, maximum, and top values). Default false.

Response​

  • Name
    tables
    Type
    array<object>
    Description

    One entry per table: tableId, sqlName, name, description, grain, rowCount, dataBytes, lastLoadAt, partitionSpec, columns (name, type, nullable, description, synonyms, masked, and stats when requested), measures (name, sql, description), joins (sqlName, on, relationship), and verifiedQueries (id, question, sql).

  • Name
    semanticsVersion
    Type
    integer
    Description

    Version of the primary table's semantic layer, for Update the semantic layer.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/describe?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"includeStats": false
}'
Response
{
"tables": [
{
"tableId": "V1StGXR8Z5",
"sqlName": "order_lines",
"name": "Order Lines",
"description": "Every order line since 2019, loaded nightly from the ERP.",
"grain": "one row per order line",
"rowCount": 418220931,
"dataBytes": 21474836480,
"lastLoadAt": "2026-10-02T06:00:12Z",
"partitionSpec": [
{
"column": "order_date",
"transform": "MONTH"
}
],
"columns": [
{
"name": "order_id",
"type": "LONG",
"nullable": false,
"description": "ERP order number."
},
{
"name": "order_date",
"type": "DATE",
"nullable": false,
"description": "Date the order was placed."
},
{
"name": "region",
"type": "STRING",
"nullable": false,
"description": "Sales region.",
"synonyms": [
"territory"
]
},
{
"name": "net_amount",
"type": "DECIMAL(18,2)",
"nullable": false,
"description": "Line revenue after discounts, in USD.",
"synonyms": [
"net sales"
]
}
],
"measures": [
{
"name": "revenue",
"sql": "SUM(net_amount)",
"description": "Net revenue in USD."
}
],
"joins": [
{
"sqlName": "customers",
"on": "order_lines.customer_id = customers.id",
"relationship": "MANY_TO_ONE"
}
],
"verifiedQueries": [
{
"id": "vq_7d2a",
"question": "Monthly revenue by region this year",
"sql": "SELECT region, date_trunc('month', order_date) AS month, SUM(net_amount) AS revenue\nFROM order_lines\nWHERE order_date >= DATE '2026-01-01'\nGROUP BY 1, 2\nORDER BY 2, 1"
}
]
}
],
"semanticsVersion": 6
}

Preview rows​

POST/preview

Returns the first rows of a table without writing SQL. Previews run ahead of regular queries.

Permission: READ

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    limit
    Type
    integer
    Description

    Rows to return, up to 100. Default 50.

Response​

  • Name
    columns
    Type
    array<object>
    Description

    Column name and type, in order.

  • Name
    rows
    Type
    array<object>
    Description

    Rows as objects keyed by column name. See Values in results.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/preview?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"limit": 2
}'
Response
{
"columns": [
{
"name": "order_id",
"type": "LONG"
},
{
"name": "order_date",
"type": "DATE"
},
{
"name": "region",
"type": "STRING"
},
{
"name": "net_amount",
"type": "DECIMAL(18,2)"
}
],
"rows": [
{
"order_id": "90210331",
"order_date": "2026-10-01",
"region": "NA",
"net_amount": "129.00"
},
{
"order_id": "90210332",
"order_date": "2026-10-01",
"region": "EMEA",
"net_amount": "48.50"
}
]
}

Estimate a query​

POST/estimate

Checks a query and reports an upper bound on how much data it would scan, without running it. Use it to catch a missing partition filter before running an expensive query.

Permission: READ on every table the query references

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    sql
    Type
    string
    Description

    The query to estimate.

Response​

  • Name
    estimatedBytesScanned
    Type
    integer
    Description

    Upper bound on data the query would read, after skipping partitions its filters rule out.

  • Name
    referencedTables
    Type
    array<string>
    Description

    SQL names of the tables the query reads.

  • Name
    withinLimits
    Type
    boolean
    Description

    false if the estimate exceeds the per-query or remaining daily scan limit.

  • Name
    hint
    Type
    string
    Description

    When withinLimits is false: what to filter on, naming the partition columns.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/estimate?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"tableId": "V1StGXR8Z5",
"sql": "SELECT region, date_trunc('month', order_date) AS month, SUM(net_amount) AS revenue\nFROM order_lines\nWHERE order_date >= DATE '2026-01-01'\nGROUP BY 1, 2\nORDER BY 2, 1"
}
JSON
Response
{
"estimatedBytesScanned": 1288490188,
"referencedTables": [
"order_lines"
],
"withinLimits": true,
"hint": null
}

Run a query​

POST/query

Runs a read-only SQL query as a job. If the job finishes within waitMs, the response includes the first rows; otherwise poll Get job status and then fetch results.

The query must be a single SELECT statement, optionally with WITH, written in ANSI SQL. It can read any analytics tables the caller has READ access to, by SQL name. Row-level and field-level security apply. Statements that change data or settings are rejected with FORBIDDEN_CONSTRUCT. SQL is limited to 100 KB.

Permission: READ on every table the query references

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    sql
    Type
    string
    Description

    The query.

  • Name
    maxRows
    Type
    integer
    Description

    Maximum rows to keep in the result. Capped at your plan's result-row limit; a larger result is cut off with truncated: true.

  • Name
    maxBytesScanned
    Type
    integer
    Description

    Refuse to run if the estimate exceeds this many bytes. Cannot exceed your plan's per-query limit.

  • Name
    waitMs
    Type
    integer
    Description

    How long to wait for the job before returning, up to 20000. 0 returns as soon as the job is queued.

Response​

  • Name
    jobId
    Type
    string
    Description

    The job's ID.

  • Name
    state
    Type
    string
    Description

    QUEUED, RUNNING, SUCCEEDED, FAILED, CANCELLED, or TIMED_OUT.

  • Name
    bytesScanned
    Type
    integer
    Description

    Data read so far, in bytes.

  • Name
    elapsedMs
    Type
    integer
    Description

    Run time so far.

  • Name
    error
    Type
    object
    Description

    When the job failed: errorCode, message, and a hint such as the valid column names. See Errors.

  • Name
    preview
    Type
    object
    Description

    When the job succeeded within waitMs: columns, the first 200 rows, totalRows, and truncated (true if the result hit maxRows).

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/query?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"tableId": "V1StGXR8Z5",
"sql": "SELECT region, date_trunc('month', order_date) AS month, SUM(net_amount) AS revenue\nFROM order_lines\nWHERE order_date >= DATE '2026-01-01'\nGROUP BY 1, 2\nORDER BY 2, 1",
"waitMs": 20000
}
JSON
Response
{
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"state": "SUCCEEDED",
"bytesScanned": 402653184,
"elapsedMs": 2140,
"preview": {
"columns": [
{
"name": "region",
"type": "STRING"
},
{
"name": "month",
"type": "TIMESTAMPTZ"
},
{
"name": "revenue",
"type": "DECIMAL(18,2)"
}
],
"rows": [
{
"region": "EMEA",
"month": "2026-01-01T00:00:00Z",
"revenue": "1284410.50"
},
{
"region": "NA",
"month": "2026-01-01T00:00:00Z",
"revenue": "2390112.75"
}
],
"totalRows": 24,
"truncated": false
}
}

Get job status​

POST/job-status

Returns a job's state, optionally waiting for it to finish. Jobs can be read by the caller who started them, or by anyone with READ on every table they reference.

Permission: READ

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    jobId
    Type
    string
    Description

    The job.

  • Name
    waitMs
    Type
    integer
    Description

    How long to wait for the job to finish before returning, up to 20000.

Response​

  • Name
    jobId
    Type
    string
    Description

    The job's ID.

  • Name
    state
    Type
    string
    Description

    QUEUED, RUNNING, SUCCEEDED, FAILED, CANCELLED, or TIMED_OUT.

  • Name
    bytesScanned
    Type
    integer
    Description

    Data read so far, in bytes.

  • Name
    elapsedMs
    Type
    integer
    Description

    Run time so far.

  • Name
    error
    Type
    object
    Description

    When the job failed: errorCode, message, and a hint such as the valid column names. See Errors.

  • Name
    resultRowCount
    Type
    integer
    Description

    Rows in the result, once succeeded.

  • Name
    truncated
    Type
    boolean
    Description

    true if the result was cut off at maxRows.

  • Name
    resultColumns
    Type
    array<object>
    Description

    Column name and type of the result.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/job-status?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"waitMs": 10000
}'
Response
{
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"state": "SUCCEEDED",
"bytesScanned": 402653184,
"elapsedMs": 2140,
"resultRowCount": 24,
"truncated": false,
"resultColumns": [
{
"name": "region",
"type": "STRING"
},
{
"name": "month",
"type": "TIMESTAMPTZ"
},
{
"name": "revenue",
"type": "DECIMAL(18,2)"
}
]
}

Get job results​

POST/job-results

Returns one page of a finished job's result. Results are kept for 7 days.

Permission: READ

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    jobId
    Type
    string
    Description

    The job.

  • Name
    page
    Type
    integer
    Description

    Page number, starting at 0.

  • Name
    pageSize
    Type
    integer
    Description

    Rows per page, up to 1000. Default 1000.

Response​

  • Name
    columns
    Type
    array<object>
    Description

    Column name and type.

  • Name
    rows
    Type
    array<object>
    Description

    Rows as objects keyed by column name. See Values in results.

  • Name
    page
    Type
    integer
    Description

    This page.

  • Name
    totalRows
    Type
    integer
    Description

    Rows in the whole result.

  • Name
    hasMore
    Type
    boolean
    Description

    true if later pages exist.

  • Name
    truncated
    Type
    boolean
    Description

    true if the result itself was cut off at maxRows.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/job-results?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"page": 0,
"pageSize": 1000
}'
Response
{
"columns": [
{
"name": "region",
"type": "STRING"
},
{
"name": "month",
"type": "TIMESTAMPTZ"
},
{
"name": "revenue",
"type": "DECIMAL(18,2)"
}
],
"rows": [
{
"region": "EMEA",
"month": "2026-01-01T00:00:00Z",
"revenue": "1284410.50"
},
{
"region": "NA",
"month": "2026-01-01T00:00:00Z",
"revenue": "2390112.75"
}
],
"page": 0,
"totalRows": 24,
"hasMore": false,
"truncated": false
}

Download job results​

POST/job-download-url

Returns a short-lived link to download a finished job's full result. Only the caller who ran the job can download it.

Permission: READ

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    jobId
    Type
    string
    Description

    The job.

  • Name
    format
    Type
    string
    Description

    CSV (default) or PARQUET.

Response​

  • Name
    url
    Type
    string
    Description

    The download link.

  • Name
    expiresAt
    Type
    string
    Description

    When the link stops working, 5 minutes after it is issued.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/job-download-url?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"format": "CSV"
}'
Response
{
"url": "https://files.autessa.com/r/1f8e5c3a.../result.csv",
"expiresAt": "2026-10-02T15:05:00Z"
}

Cancel a job​

POST/cancel

Cancels a queued or running job. A running job stops within a few seconds.

Permission: READ, and the caller must have started the job

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    jobId
    Type
    string
    Description

    The job.

Response​

  • Name
    jobId
    Type
    string
    Description

    The job.

  • Name
    state
    Type
    string
    Description

    CANCELLED, or the final state if the job had already finished.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/cancel?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54"
}'
Response
{
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"state": "CANCELLED"
}

List jobs​

POST/jobs

Lists recent jobs on a table, newest first: queries, loads, and appends.

Permission: READ

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    kind
    Type
    string
    Description

    Only this kind: QUERY, LOAD, or APPEND.

  • Name
    state
    Type
    string
    Description

    Only jobs in this state.

  • Name
    mine
    Type
    boolean
    Description

    Only jobs the caller started. Default false.

  • Name
    limit
    Type
    integer
    Description

    Jobs per page, up to 100. Default 25.

  • Name
    cursor
    Type
    string
    Description

    The nextCursor from the previous page.

Response​

  • Name
    jobs
    Type
    array<object>
    Description

    Each job: jobId, kind, state, sql (first 500 characters), createdBy, createdAt, finishedAt, resultRowCount, bytesScanned, and elapsedMs.

  • Name
    nextCursor
    Type
    string
    Description

    Cursor for the next page, or null.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/jobs?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"kind": "QUERY",
"limit": 1
}'
Response
{
"jobs": [
{
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"kind": "QUERY",
"state": "SUCCEEDED",
"sql": "SELECT region, date_trunc('month', order_date) AS month, SUM(net_amount) AS revenue\nFROM order_lines\nWHERE order_date >= DATE '2026-01-01'\nGROUP BY 1, 2\nORDER BY 2, 1",
"createdBy": {
"userId": "u8Kd2LmQ4x",
"name": "Dana Ortiz"
},
"createdAt": "2026-10-02T14:59:51Z",
"finishedAt": "2026-10-02T14:59:53Z",
"resultRowCount": 24,
"bytesScanned": 402653184,
"elapsedMs": 2140
}
],
"nextCursor": "eyJ0IjoiMjAyNi0xMC0wMlQxNDo1OTo1MVoifQ"
}

Load files​

POST/load-from-s3

Loads one or more CSV or Parquet files into the table as a job. Upload each file first (see Uploading a file to load) and pass the s3Uri you get back. Values are converted to the column types; rows that cannot be converted are counted and sampled in the job result rather than silently dropped. A load is all-or-nothing: if it fails, no rows are added.

Permission: WRITE

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    sourceUris
    Type
    array<string>
    Description

    The uploaded files' s3Uri values.

  • Name
    format
    Type
    string
    Description

    CSV or PARQUET. Inferred from the file extension when omitted.

  • Name
    mode
    Type
    string
    Description

    APPEND (default) adds the rows; REPLACE swaps the table's contents for them.

  • Name
    csv
    Type
    object
    Description

    CSV options: delimiter (default ,), header (default true), nullString, quote, dateFormat, and timestampFormat.

  • Name
    columnMapping
    Type
    object
    Description

    Map of file column name to table column name, when they differ. Unmapped table columns are left empty.

Response​

  • Name
    jobId
    Type
    string
    Description

    The load job. Poll Get job status; a finished load reports rowsLoaded, rowsRejected, and rejectedSample.

  • Name
    state
    Type
    string
    Description

    The job's state.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/load-from-s3?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"sourceUris": [
"s3://autessa-intake/cP2mK7dX4v/9a1e.../orders-2026-09.csv"
],
"format": "CSV",
"mode": "APPEND",
"csv": {
"header": true,
"timestampFormat": "%Y-%m-%d %H:%M:%S"
}
}'
Response
{
"jobId": "6c2b9e14-3f7a-4d81-b0e5-a9d4c2f81b37",
"state": "QUEUED"
}

Append rows​

POST/append-rows

Appends a small batch of rows sent in the request body: up to 10,000 rows or 5 MB per call. Appends that arrive within a few seconds of each other are committed together, so rows become visible to queries within about 5 seconds. Use Load files for bulk data.

Permission: WRITE

Request parameters​

  • Name
    tableId
    Type
    string
    Description

    The analytics table. For multi-table queries, the primary table; on the client API it must match the resourceId query parameter.

  • Name
    rows
    Type
    array<object>
    Description

    Rows as objects keyed by column name, with plain JSON values. Send DECIMAL and large integers as strings, dates and timestamps as ISO-8601 strings.

Response​

  • Name
    accepted
    Type
    integer
    Description

    Rows accepted.

  • Name
    loadId
    Type
    string
    Description

    Identifier written to the _load_id column of these rows.

  • Name
    errors
    Type
    array<object>
    Description

    Rows refused: index and message. Refused rows are not appended; the others are.

curl -X POST 'https://api.autessa.com/clients/autessadb/analytics/append-rows?resourceId=V1StGXR8Z5' \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"rows": [
{
"order_id": "90210333",
"order_date": "2026-10-02",
"region": "APAC",
"net_amount": "310.00"
}
]
}'
Response
{
"accepted": 1,
"loadId": "append-2026-10-02T15:00:05Z",
"errors": []
}

Masked columns​

Text columns created with masked: true are stored encrypted and appear in results as mask text unless the caller's role allows revealing them.

  • create and add-columns: columns[].masked: true (STRING only).
  • describe: columns[].encrypted, revealable, and maskStrategy.
  • query, preview, job-results, and job-download-url accept reveal: true to return plaintext for callers whose role shows the column; every reveal is recorded in the access log.
  • job-results also accepts revealRow (0-based row of the whole result) with revealColumn and returns revealedCell {row, column, value} for a single cell.
  • Result columns[] carry masked, revealable, revealed, and maskStrategy.
  • In SQL, masked columns support =, <>, IN, IS NULL, GROUP BY, DISTINCT, COUNT(DISTINCT), MIN/MAX, joins with other masked columns, and ORDER BY (by an internal code). LIKE, ranges, and other functions fail with FORBIDDEN_CONSTRUCT and a hint.
  • Loads into tables with masked columns run in the app rather than the analytics engine; load responses say so in notes.

Errors​

Failed calls, and jobs that end in FAILED or TIMED_OUT, carry an error code, a plain-language message, and where possible a hint:

Error
{
"errorCode": "UNKNOWN_COLUMN",
"errors": ["Column \"net_amt\" does not exist in order_lines."],
"hint": "Columns in order_lines: order_id, order_date, region, customer_id, net_amount."
}
Error codeWhen
PARSE_ERRORThe SQL could not be parsed. The message points at the position.
FORBIDDEN_CONSTRUCTThe SQL is not a single read-only query: it changes data or settings, has several statements, or calls a function that reads files or system state.
UNKNOWN_TABLEThe query names a table that does not exist or that the caller cannot read. The two cases are reported the same way.
UNKNOWN_COLUMNThe query names a column that does not exist or is hidden from the caller. The hint lists the available columns.
SCAN_LIMITThe query would scan more than the per-query limit, maxBytesScanned, or the remaining daily allowance. The hint names the partition columns to filter on.
TIMEOUTThe query ran past the time limit.
ROW_LIMITToo many rows were requested; lower maxRows or pageSize.
QUOTAA plan limit was reached: storage, concurrent queries, data loaded per day, or appended rows per minute.
VERSION_CONFLICTThe semantic layer changed since expectedVersion. Describe again and retry.
INVALID_SCHEMAA column name, type, or partition spec is invalid, or a schema change is not a safe widening.
FORBIDDENThe caller lacks the table permission for the operation, or the job belongs to another caller.
NOT_FOUNDThe table or job does not exist, or its results have expired.

HTTP status codes follow the usual pattern: 400 for invalid requests and SQL errors, 401 for a missing or invalid key, 403 for FORBIDDEN, 404 for NOT_FOUND, 409 for VERSION_CONFLICT, 413 for SCAN_LIMIT and ROW_LIMIT, and 429 for QUOTA and rate limits.