AutessaDB Analytics
The full lifecycle of analytics tables: create a table from a schema or a sample file, add columns, describe it for agents with a semantic layer, load and append data, run read-only SQL as jobs, and provision the agent tools that query it.
All paths on this page are relative to https://api.autessa.com/autessa_poweruser/autessadb/analytics. Every request is a POST with a JSON body, and the target table is selected by the tableId field in the body. There is no resourceId query parameter. See the Poweruser API overview for authentication and conventions.
The poweruser key acts as its linked user, so table access levels apply as they do in the builder: READ to describe and query, WRITE to load and append, ADMIN to change columns and the semantic layer. A query that joins several tables needs READ on every one of them.
Values in results
Rows are JSON objects keyed by column name. Values keep their exact meaning:
| Column type | JSON value |
|---|---|
STRING, BOOLEAN, INT, DOUBLE | String, boolean, or number |
LONG | Number, or a string when the value is too large to be exact in JSON |
DECIMAL | String, e.g. "1284410.50" |
DATE | "2026-10-01" |
TIMESTAMP, TIMESTAMPTZ | ISO-8601 UTC string, e.g. "2026-10-01T00:00:00Z" |
STRING_LIST | Array of strings |
JSON | The JSON value |
| empty | null |
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:
- Run a query with
waitMsup to 20 seconds. If the job finishes in that time, it comes backSUCCEEDEDwith apreviewof the first 200 rows. - If the state is
QUEUEDorRUNNING, call Get job status withwaitMsuntil it finishes. - 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 and Infer a schema are uploaded with the client intake endpoints at https://api.autessa.com/clients/autessadb-intake, which send the bytes straight to storage in parts:
POST /multipart-initiatewith{"fileName": "orders-2026-09.csv"}returnsuploadId,s3Key, ands3Uri.POST /multipart-part-urlswithuploadId,s3Key, andpartNumbersreturns apartUrlsmap.PUTeach part (at least 5 MB except the last) to its link and keep each response'sETagheader.POST /multipart-completewithuploadId,s3Key, andpartETags(part number to ETag) returns the finals3Uri.
The CLI does all of this for you with autessa autessadb analytics load --localFile.
Create an analytics table
/createCreates an analytics table. Choose the columns, an optional partition spec of up to two fields, and the SQL name queries will use. The table counts toward your AutessaDB table limit.
Permission: Company-level; no table permission is needed
Request parameters
- Name
tableName- Type
- string
- Description
Display name.
- Name
description- Type
- string
- Description
What the table holds.
- Name
schema- Type
- object
- Description
The table's columns in
columnDefinitions. Each hascolumnName(lowercasesnake_case),columnTypeoranalytics.type(STRING,INT,LONG,DOUBLE,DECIMALwithprecisionandscale,BOOLEAN,DATE,TIMESTAMP,TIMESTAMPTZ,STRING_LIST, orJSON),required,columnComment, and optionallymaskedandanalytics.synonyms.
- Name
analytics- Type
- object
- Description
partitionSpec: up to two{column, transform, param}entries, wheretransformisIDENTITY,YEAR,MONTH,DAY,HOUR,BUCKET(param= bucket count), orTRUNCATE(param= width).sortOrder: columns to sort data by within partitions.sqlName: unique within your company; defaults to the table name insnake_case.
Response
- Name
tableId- Type
- string
- Description
The new table's ID.
- Name
sqlName- Type
- string
- Description
The SQL name to use in queries.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/create' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableName": "Order Lines",
"description": "Every order line since 2019.",
"schema": {
"columnDefinitions": [
{
"columnName": "order_id",
"columnType": "INTEGER",
"required": true
},
{
"columnName": "order_date",
"analytics": {
"type": "DATE"
},
"required": true
},
{
"columnName": "region",
"columnType": "SHORT_TEXT",
"required": true
},
{
"columnName": "net_amount",
"analytics": {
"type": "DECIMAL",
"precision": 18,
"scale": 2
},
"columnComment": "Line revenue after discounts, in USD."
}
]
},
"analytics": {
"partitionSpec": [
{
"column": "order_date",
"transform": "MONTH"
}
],
"sqlName": "order_lines"
}
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/create',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableName: 'Order Lines',
description: 'Every order line since 2019.',
schema: {
columnDefinitions: [
{
columnName: 'order_id',
columnType: 'INTEGER',
required: true
},
{
columnName: 'order_date',
analytics: {
type: 'DATE'
},
required: true
},
{
columnName: 'region',
columnType: 'SHORT_TEXT',
required: true
},
{
columnName: 'net_amount',
analytics: {
type: 'DECIMAL',
precision: 18,
scale: 2
},
columnComment: 'Line revenue after discounts, in USD.'
}
]
},
analytics: {
partitionSpec: [
{
column: 'order_date',
transform: 'MONTH'
}
],
sqlName: 'order_lines'
}
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/create',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableName': 'Order Lines',
'description': 'Every order line since 2019.',
'schema': {
'columnDefinitions': [
{
'columnName': 'order_id',
'columnType': 'INTEGER',
'required': True
},
{
'columnName': 'order_date',
'analytics': {
'type': 'DATE'
},
'required': True
},
{
'columnName': 'region',
'columnType': 'SHORT_TEXT',
'required': True
},
{
'columnName': 'net_amount',
'analytics': {
'type': 'DECIMAL',
'precision': 18,
'scale': 2
},
'columnComment': 'Line revenue after discounts, in USD.'
}
]
},
'analytics': {
'partitionSpec': [
{
'column': 'order_date',
'transform': 'MONTH'
}
],
'sqlName': 'order_lines'
}
}
)
data = response.json()
{
"tableId": "V1StGXR8Z5",
"sqlName": "order_lines"
}
Infer a schema from a file
/infer-schemaReads a sample CSV or Parquet file and proposes columns and types, with sample rows and warnings such as mixed types or unparseable dates. Use the result as the schema for Create an analytics table.
Permission: Company-level
Request parameters
- Name
s3Uri- Type
- string
- Description
The uploaded sample file (see Uploading a file to load).
- Name
format- Type
- string
- Description
CSVorPARQUET. Inferred from the extension when omitted.
Response
- Name
columns- Type
- array<object>
- Description
Proposed column definitions.
- Name
sampleRows- Type
- array<object>
- Description
Up to 20 parsed rows.
- Name
warnings- Type
- array<string>
- Description
Problems found in the sample.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/infer-schema' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"s3Uri": "s3://autessa-intake/cP2mK7dX4v/9a1e.../orders-sample.csv"
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/infer-schema',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
s3Uri: 's3://autessa-intake/cP2mK7dX4v/9a1e.../orders-sample.csv'
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/infer-schema',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
's3Uri': 's3://autessa-intake/cP2mK7dX4v/9a1e.../orders-sample.csv'
}
)
data = response.json()
{
"columns": [
{
"columnName": "order_id",
"analytics": {
"type": "LONG"
},
"required": true
},
{
"columnName": "order_date",
"analytics": {
"type": "DATE"
},
"required": true
},
{
"columnName": "region",
"analytics": {
"type": "STRING"
},
"required": false
}
],
"sampleRows": [
{
"order_id": "90210331",
"order_date": "2026-10-01",
"region": "NA"
}
],
"warnings": [
"region: 3 of 1000 sampled rows are empty."
]
}
Describe tables
/describeReturns 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
resourceIdquery 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, andstatswhen requested),measures(name,sql,description),joins(sqlName,on,relationship), andverifiedQueries(id,question,sql).
- Name
semanticsVersion- Type
- integer
- Description
Version of the primary table's semantic layer, for Update the semantic layer.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/describe' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"includeStats": false
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/describe',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
includeStats: false
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/describe',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'includeStats': False
}
)
data = response.json()
{
"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
/previewReturns 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
resourceIdquery parameter.
- Name
limit- Type
- integer
- Description
Rows to return, up to 100. Default 50.
Response
- Name
columns- Type
- array<object>
- Description
Column
nameandtype, in order.
- Name
rows- Type
- array<object>
- Description
Rows as objects keyed by column name. See Values in results.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/preview' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"limit": 2
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/preview',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
limit: 2
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/preview',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'limit': 2
}
)
data = response.json()
{
"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
/estimateChecks 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
resourceIdquery 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
falseif the estimate exceeds the per-query or remaining daily scan limit.
- Name
hint- Type
- string
- Description
When
withinLimitsisfalse: what to filter on, naming the partition columns.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/estimate' \
-H "Authorization: $POWERUSER_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
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/estimate',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
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"
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/estimate',
headers={'Authorization': os.environ['POWERUSER_KEY']},
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"
}
)
data = response.json()
{
"estimatedBytesScanned": 1288490188,
"referencedTables": [
"order_lines"
],
"withinLimits": true,
"hint": null
}
Run a query
/queryRuns 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
resourceIdquery 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.
0returns 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, orTIMED_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 ahintsuch as the valid column names. See Errors.
- Name
preview- Type
- object
- Description
When the job succeeded within
waitMs:columns, the first 200rows,totalRows, andtruncated(trueif the result hitmaxRows).
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/query' \
-H "Authorization: $POWERUSER_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
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/query',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
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
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/query',
headers={'Authorization': os.environ['POWERUSER_KEY']},
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
}
)
data = response.json()
{
"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
/job-statusReturns 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
resourceIdquery 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, orTIMED_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 ahintsuch as the valid column names. See Errors.
- Name
resultRowCount- Type
- integer
- Description
Rows in the result, once succeeded.
- Name
truncated- Type
- boolean
- Description
trueif the result was cut off atmaxRows.
- Name
resultColumns- Type
- array<object>
- Description
Column
nameandtypeof the result.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-status' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"waitMs": 10000
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-status',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
jobId: '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54',
waitMs: 10000
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-status',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'jobId': '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54',
'waitMs': 10000
}
)
data = response.json()
{
"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
/job-resultsReturns 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
resourceIdquery 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
nameandtype.
- 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
trueif later pages exist.
- Name
truncated- Type
- boolean
- Description
trueif the result itself was cut off atmaxRows.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-results' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"page": 0,
"pageSize": 1000
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-results',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
jobId: '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54',
page: 0,
pageSize: 1000
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-results',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'jobId': '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54',
'page': 0,
'pageSize': 1000
}
)
data = response.json()
{
"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
/job-download-urlReturns 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
resourceIdquery parameter.
- Name
jobId- Type
- string
- Description
The job.
- Name
format- Type
- string
- Description
CSV(default) orPARQUET.
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
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-download-url' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"format": "CSV"
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-download-url',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
jobId: '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54',
format: 'CSV'
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/job-download-url',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'jobId': '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54',
'format': 'CSV'
}
)
data = response.json()
{
"url": "https://files.autessa.com/r/1f8e5c3a.../result.csv",
"expiresAt": "2026-10-02T15:05:00Z"
}
Cancel a job
/cancelCancels 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
resourceIdquery 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
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/cancel' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54"
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/cancel',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
jobId: '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54'
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/cancel',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'jobId': '1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54'
}
)
data = response.json()
{
"jobId": "1f8e5c3a-9b2d-4e7f-a6c1-3d0b9e2f7a54",
"state": "CANCELLED"
}
List jobs
/jobsLists 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
resourceIdquery parameter.
- Name
kind- Type
- string
- Description
Only this kind:
QUERY,LOAD, orAPPEND.
- 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
nextCursorfrom the previous page.
Response
- Name
jobs- Type
- array<object>
- Description
Each job:
jobId,kind,state,sql(first 500 characters),createdBy,createdAt,finishedAt,resultRowCount,bytesScanned, andelapsedMs.
- Name
nextCursor- Type
- string
- Description
Cursor for the next page, or
null.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/jobs' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"kind": "QUERY",
"limit": 1
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/jobs',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
kind: 'QUERY',
limit: 1
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/jobs',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'kind': 'QUERY',
'limit': 1
}
)
data = response.json()
{
"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
/load-from-s3Loads 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
resourceIdquery parameter.
- Name
sourceUris- Type
- array<string>
- Description
The uploaded files'
s3Urivalues.
- Name
format- Type
- string
- Description
CSVorPARQUET. Inferred from the file extension when omitted.
- Name
mode- Type
- string
- Description
APPEND(default) adds the rows;REPLACEswaps the table's contents for them.
- Name
csv- Type
- object
- Description
CSV options:
delimiter(default,),header(defaulttrue),nullString,quote,dateFormat, andtimestampFormat.
- 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, andrejectedSample.
- Name
state- Type
- string
- Description
The job's state.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/load-from-s3' \
-H "Authorization: $POWERUSER_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"
}
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/load-from-s3',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
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'
}
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/load-from-s3',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'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'
}
}
)
data = response.json()
{
"jobId": "6c2b9e14-3f7a-4d81-b0e5-a9d4c2f81b37",
"state": "QUEUED"
}
Append rows
/append-rowsAppends 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
resourceIdquery parameter.
- Name
rows- Type
- array<object>
- Description
Rows as objects keyed by column name, with plain JSON values. Send
DECIMALand 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_idcolumn of these rows.
- Name
errors- Type
- array<object>
- Description
Rows refused:
indexandmessage. Refused rows are not appended; the others are.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/append-rows' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"rows": [
{
"order_id": "90210333",
"order_date": "2026-10-02",
"region": "APAC",
"net_amount": "310.00"
}
]
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/append-rows',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
rows: [
{
order_id: '90210333',
order_date: '2026-10-02',
region: 'APAC',
net_amount: '310.00'
}
]
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/append-rows',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'rows': [
{
'order_id': '90210333',
'order_date': '2026-10-02',
'region': 'APAC',
'net_amount': '310.00'
}
]
}
)
data = response.json()
{
"accepted": 1,
"loadId": "append-2026-10-02T15:00:05Z",
"errors": []
}
Add columns
/add-columnsAdds columns to an analytics table, or widens existing column types safely (for example INT to LONG, or a DECIMAL to a larger precision). New columns are empty for existing rows. Renaming, removing, and narrowing columns are not supported.
Permission: ADMIN
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
resourceIdquery parameter.
- Name
columns- Type
- array<object>
- Description
New columns, in the same form as
schema.columnDefinitions. New columns cannot be required.
- Name
widen- Type
- array<object>
- Description
Type changes:
columnNameand the newtype(withprecisionandscaleforDECIMAL).
Response
- Name
columns- Type
- array<object>
- Description
The table's full column list after the change.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/add-columns' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"columns": [
{
"columnName": "channel",
"analytics": {
"type": "STRING"
},
"columnComment": "Sales channel."
}
]
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/add-columns',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
columns: [
{
columnName: 'channel',
analytics: {
type: 'STRING'
},
columnComment: 'Sales channel.'
}
]
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/add-columns',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'columns': [
{
'columnName': 'channel',
'analytics': {
'type': 'STRING'
},
'columnComment': 'Sales channel.'
}
]
}
)
data = response.json()
{
"columns": [
{
"name": "order_id",
"type": "LONG"
},
{
"name": "order_date",
"type": "DATE"
},
{
"name": "region",
"type": "STRING"
},
{
"name": "net_amount",
"type": "DECIMAL(18,2)"
},
{
"name": "channel",
"type": "STRING"
}
]
}
Suggest a semantic layer with AI
/suggest-semanticsDrafts the semantic layer from the table's columns, statistics, and a 50-row sample, as the caller is allowed to see them: description, grain, column descriptions and synonyms, measures, example verified queries, and joins to other analytics tables the caller can read. Nothing is saved. Suggested queries and measures are checked against the SQL rules and the caller's access; items that fail are dropped with a note, and items the engine cannot validate are returned flagged. Pass the result (or the merged layer) to Update the semantic layer to save it. Suggestions do not count toward AI usage.
Permission: WRITE
Request parameters
- Name
tableId- Type
- string
- Description
The analytics table.
- Name
focus- Type
- array
- Description
Limit the draft to some parts: any of
description,columns,measures,synonyms,verifiedQueries,joins. Default: all.
- Name
existing- Type
- boolean
- Description
true(default) keeps the current values and only fills gaps;falsedrafts everything again.
Response
- Name
suggestion- Type
- object
- Description
The draft:
description,grain,columns(map of column name todescriptionandsynonyms),measures,verifiedQueries(question,sql),joins.
- Name
merged- Type
- object
- Description
The current semantic layer with the passing suggestions applied; never removes anything. Send it to
/update-semanticsto save.
- Name
validated- Type
- object
- Description
Per suggested query and measure:
ok, anderrorwhen the check failed.
- Name
notes- Type
- array
- Description
Plain-language notes, for example which items were dropped and why.
- Name
semanticsVersion- Type
- integer
- Description
The version the draft was made from; pass it as
expectedVersionwhen saving.
- cURL
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/suggest-semantics' -H 'Authorization: Bearer $AUTESSA_POWERUSER_KEY' -H 'Content-Type: application/json' -d '{"tableId": "V1StGXR8Z5", "focus": ["description", "columns", "measures"]}'
Update the semantic layer
/update-semanticsReplaces the table's semantic layer: description, grain, column descriptions and synonyms, measures, joins, and verified queries. Send the semanticsVersion you last read; if someone else saved in between, the call fails with VERSION_CONFLICT. Measures and verified queries are checked in the background, and any that no longer run are flagged.
Permission: ADMIN
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
resourceIdquery parameter.
- Name
expectedVersion- Type
- integer
- Description
The
semanticsVersionfrom Describe tables.
- Name
semantics- Type
- object
- Description
description,grain,columns(map of column name todescriptionandsynonyms),measures(name,sql,description,format),joins(tableId,on,relationshipofMANY_TO_ONE,ONE_TO_MANY, orONE_TO_ONE), andverifiedQueries(question,sql).
Response
- Name
semanticsVersion- Type
- integer
- Description
The new version.
- Name
validationJobId- Type
- string
- Description
The background check of measures and verified queries.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/update-semantics' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"tableId": "V1StGXR8Z5",
"expectedVersion": 6,
"semantics": {
"description": "Every order line since 2019, loaded nightly from the ERP.",
"grain": "one row per order line",
"columns": {
"net_amount": {
"description": "Line revenue after discounts, in USD.",
"synonyms": [
"net sales"
]
}
},
"measures": [
{
"name": "revenue",
"sql": "SUM(net_amount)",
"description": "Net revenue in USD.",
"format": "currency"
}
],
"joins": [
{
"tableId": "Hq4ZpN8sXe",
"on": "order_lines.customer_id = customers.id",
"relationship": "MANY_TO_ONE"
}
],
"verifiedQueries": [
{
"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"
}
]
}
}
JSON
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/update-semantics',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
expectedVersion: 6,
semantics: {
description: 'Every order line since 2019, loaded nightly from the ERP.',
grain: 'one row per order line',
columns: {
net_amount: {
description: 'Line revenue after discounts, in USD.',
synonyms: ['net sales']
}
},
measures: [
{
name: 'revenue',
sql: 'SUM(net_amount)',
description: 'Net revenue in USD.',
format: 'currency'
}
],
joins: [
{
tableId: 'Hq4ZpN8sXe',
on: 'order_lines.customer_id = customers.id',
relationship: 'MANY_TO_ONE'
}
],
verifiedQueries: [
{
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"
}
]
}
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/update-semantics',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'expectedVersion': 6,
'semantics': {
'description': 'Every order line since 2019, loaded nightly from the ERP.',
'grain': 'one row per order line',
'columns': {
'net_amount': {
'description': 'Line revenue after discounts, in USD.',
'synonyms': ['net sales']
}
},
'measures': [
{
'name': 'revenue',
'sql': 'SUM(net_amount)',
'description': 'Net revenue in USD.',
'format': 'currency'
}
],
'joins': [
{
'tableId': 'Hq4ZpN8sXe',
'on': 'order_lines.customer_id = customers.id',
'relationship': 'MANY_TO_ONE'
}
],
'verifiedQueries': [
{
'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"
}
]
}
}
)
data = response.json()
{
"semanticsVersion": 7,
"validationJobId": "0b7d4f9e-2c1a-4e63-8d5f-71a9c3e0b2d8"
}
Load from an AutessaDB table
/load-from-tableCopies rows from a regular AutessaDB table into the analytics table as a job, mapping source columns to target columns.
Permission: WRITE on the analytics table and READ on the source table, with access to all of its rows
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
resourceIdquery parameter.
- Name
sourceTableId- Type
- string
- Description
The regular table to copy from.
- Name
columnMapping- Type
- object
- Description
Map of source column name to analytics column name.
- Name
mode- Type
- string
- Description
APPEND(default) orREPLACE.
Response
- Name
jobId- Type
- string
- Description
The load job.
- Name
state- Type
- string
- Description
The job's state.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/load-from-table' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"sourceTableId": "Hq4ZpN8sXe",
"columnMapping": {
"order_number": "order_id",
"placed_on": "order_date",
"region": "region",
"total": "net_amount"
},
"mode": "APPEND"
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/load-from-table',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
sourceTableId: 'Hq4ZpN8sXe',
columnMapping: {
order_number: 'order_id',
placed_on: 'order_date',
region: 'region',
total: 'net_amount'
},
mode: 'APPEND'
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/load-from-table',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'sourceTableId': 'Hq4ZpN8sXe',
'columnMapping': {
'order_number': 'order_id',
'placed_on': 'order_date',
'region': 'region',
'total': 'net_amount'
},
'mode': 'APPEND'
}
)
data = response.json()
{
"jobId": "9d3a1c7e-5b20-4f84-a6e9-2c8f0b1d4e73",
"state": "QUEUED"
}
Create agent tools
/create-agent-toolsCreates the three analytics tools for a set of tables in one call: ANALYTICS_DESCRIBE, ANALYTICS_QUERY, and ANALYTICS_GET_RESULT. Attach them to an agent to let it answer questions from the data.
Permission: READ on every table
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
resourceIdquery parameter.
- Name
tableIds- Type
- array<string>
- Description
Additional tables the tools may query.
- Name
namePrefix- Type
- string
- Description
Prefix for the tool names. Defaults to the primary table's name.
Response
- Name
toolIds- Type
- object
- Description
The new tools' IDs keyed by
describe,query, andgetResult.
- cURL
- JavaScript
- Python
curl -X POST 'https://api.autessa.com/autessa_poweruser/autessadb/analytics/create-agent-tools' \
-H "Authorization: $POWERUSER_KEY" \
-H "Content-Type: application/json" \
-d '{
"tableId": "V1StGXR8Z5",
"tableIds": [
"Hq4ZpN8sXe"
],
"namePrefix": "Sales data"
}'
const response = await fetch(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/create-agent-tools',
{
method: 'POST',
headers: {
'Authorization': process.env.POWERUSER_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tableId: 'V1StGXR8Z5',
tableIds: ['Hq4ZpN8sXe'],
namePrefix: 'Sales data'
})
}
);
const data = await response.json();
import os
import requests
response = requests.post(
'https://api.autessa.com/autessa_poweruser/autessadb/analytics/create-agent-tools',
headers={'Authorization': os.environ['POWERUSER_KEY']},
json={
'tableId': 'V1StGXR8Z5',
'tableIds': ['Hq4ZpN8sXe'],
'namePrefix': 'Sales data'
}
)
data = response.json()
{
"toolIds": {
"describe": "Zt5mW8qR1k",
"query": "Bn3xL6vD9p",
"getResult": "Cf7yH2jS4u"
}
}
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.
createandadd-columns:columns[].masked: true(STRING only).describe:columns[].encrypted,revealable, andmaskStrategy.query,preview,job-results, andjob-download-urlacceptreveal: trueto return plaintext for callers whose role shows the column; every reveal is recorded in the access log.job-resultsalso acceptsrevealRow(0-based row of the whole result) withrevealColumnand returnsrevealedCell {row, column, value}for a single cell.- Result
columns[]carrymasked,revealable,revealed, andmaskStrategy. - In SQL, masked columns support
=,<>,IN,IS NULL,GROUP BY,DISTINCT,COUNT(DISTINCT),MIN/MAX, joins with other masked columns, andORDER BY(by an internal code).LIKE, ranges, and other functions fail withFORBIDDEN_CONSTRUCTand 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:
{
"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 code | When |
|---|---|
PARSE_ERROR | The SQL could not be parsed. The message points at the position. |
FORBIDDEN_CONSTRUCT | The 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_TABLE | The query names a table that does not exist or that the caller cannot read. The two cases are reported the same way. |
UNKNOWN_COLUMN | The query names a column that does not exist or is hidden from the caller. The hint lists the available columns. |
SCAN_LIMIT | The query would scan more than the per-query limit, maxBytesScanned, or the remaining daily allowance. The hint names the partition columns to filter on. |
TIMEOUT | The query ran past the time limit. |
ROW_LIMIT | Too many rows were requested; lower maxRows or pageSize. |
QUOTA | A plan limit was reached: storage, concurrent queries, data loaded per day, or appended rows per minute. |
VERSION_CONFLICT | The semantic layer changed since expectedVersion. Describe again and retry. |
INVALID_SCHEMA | A column name, type, or partition spec is invalid, or a schema change is not a safe widening. |
FORBIDDEN | The caller lacks the table permission for the operation, or the job belongs to another caller. |
NOT_FOUND | The 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.
Related
- Poweruser API overview
- AutessaDB Tables API — sharing, ownership, and deletion work the same for analytics tables
- Client Analytics API
- AutessaDB Analytics Tables guide
- Analytics tool types