API: Shared schemas
These shapes are defined once, in the shared contracts package the api, the web app and the pipelines worker all build against, and exported as JSON Schema (draft 2020-12). Response schemas describe what the api sends; request schemas describe what it accepts.
EntitlementSnapshot
Section titled “EntitlementSnapshot”The resolved product entitlements for the caller (GET /api/entitlements).
Used by: GET /api/entitlements (response)
| Field | Type | Required | Description |
|---|---|---|---|
bi |
object | yes | BI is always licensed; the tier sets its feature level. |
bi.tier |
"team" | "business" | "enterprise" |
yes | BI tier. enterprise comes only from a licence file. |
pipelines |
object | yes | Licensed by the licence, an active trial grant, or a plan row. |
pipelines.licensed |
boolean | yes | |
warehouse |
object | yes | Licensed by the licence, an active trial grant, or a plan row. |
warehouse.licensed |
boolean | yes | |
trialGrants |
map of string, keyed by bi, pipelines, warehouse |
yes | Product key to the YYYY-MM-DD date its trial grant expires (inclusive, UTC). Expired grants stay listed. |
availability |
object | no | The operator’s product switches (platform default + company override), apart from the plan, so an app can say “turned off for your company” rather than “not on your plan”. Set by GET /api/entitlements; absent from licence-derived snapshots. |
availability.pipelines |
boolean | yes | |
availability.warehouse |
boolean | yes |
JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "EntitlementSnapshot", "type": "object", "properties": { "bi": { "type": "object", "properties": { "tier": { "type": "string", "enum": [ "team", "business", "enterprise" ], "description": "BI tier. `enterprise` comes only from a licence file." } }, "required": [ "tier" ], "additionalProperties": false, "description": "BI is always licensed; the tier sets its feature level." }, "pipelines": { "default": { "licensed": false }, "description": "Licensed by the licence, an active trial grant, or a plan row.", "type": "object", "properties": { "licensed": { "type": "boolean" } }, "required": [ "licensed" ], "additionalProperties": false }, "warehouse": { "default": { "licensed": false }, "description": "Licensed by the licence, an active trial grant, or a plan row.", "type": "object", "properties": { "licensed": { "type": "boolean" } }, "required": [ "licensed" ], "additionalProperties": false }, "trialGrants": { "default": {}, "description": "Product key to the YYYY-MM-DD date its trial grant expires (inclusive, UTC). Expired grants stay listed.", "type": "object", "propertyNames": { "type": "string", "enum": [ "bi", "pipelines", "warehouse" ] }, "additionalProperties": { "type": "string" } }, "availability": { "description": "The operator's product switches (platform default + company override), apart from the plan, so an app can say \"turned off for your company\" rather than \"not on your plan\". Set by GET /api/entitlements; absent from licence-derived snapshots.", "type": "object", "properties": { "pipelines": { "type": "boolean" }, "warehouse": { "type": "boolean" } }, "required": [ "pipelines", "warehouse" ], "additionalProperties": false } }, "required": [ "bi", "pipelines", "warehouse", "trialGrants" ], "additionalProperties": false, "description": "The resolved product entitlements for the caller (GET /api/entitlements)."}ProductUsage
Section titled “ProductUsage”Per-product usage against plan allowances for one workspace (GET /api/usage/products).
Used by: GET /api/usage/products (response)
| Field | Type | Required | Description |
|---|---|---|---|
month |
string | yes | ‘YYYY-MM’ (UTC): the period the usage numbers cover. |
workspace_id |
string | yes | The workspace the cards describe. |
products |
object | yes | |
products.pipelines |
object | yes | The Pipelines usage card. |
products.pipelines.licensed |
boolean | yes | |
products.pipelines.planKey |
string | null | yes | The plan row that grants this product, or null without one. |
products.pipelines.overageOptIn |
boolean | null | yes | Metered overage consent on that plan row. false = hard cap at the allowance (the default). |
products.pipelines.draft |
boolean | null | yes | The plan’s pricing is still provisional (plans.config.draft). |
products.pipelines.allowance |
object | null | yes | null = no plan row, uncapped. |
products.pipelines.allowance.execution_hours |
number | null | yes | |
products.pipelines.allowance.execution_seconds |
number | null | yes | execution_hours × 3600, the unit the cap compares. |
products.pipelines.currentPeriod |
object | yes | Month to date: settled ledger days plus a live read of the last two days. |
products.pipelines.currentPeriod.execution_seconds |
number | yes | |
products.pipelines.currentPeriod.rows_moved |
number | yes | |
products.pipelines.currentPeriod.bytes_moved |
number | yes | |
products.pipelines.currentPeriod.runs |
number | yes | |
products.warehouse |
object | yes | The Warehouse usage card. |
products.warehouse.licensed |
boolean | yes | |
products.warehouse.planKey |
string | null | yes | The plan row that grants this product, or null without one. |
products.warehouse.overageOptIn |
boolean | null | yes | Metered overage consent on that plan row. false = hard cap at the allowance (the default). |
products.warehouse.draft |
boolean | null | yes | The plan’s pricing is still provisional (plans.config.draft). |
products.warehouse.allowance |
object | null | yes | null = no plan row, uncapped. |
products.warehouse.allowance.storage_gb |
number | null | yes | |
products.warehouse.allowance.storage_bytes |
number | null | yes | storage_gb × 1024³. |
products.warehouse.currentPeriod |
object | yes | Month to date. |
products.warehouse.currentPeriod.storage_bytes |
number | yes | The month’s storage peak: the metered figure. |
products.warehouse.currentPeriod.storage_bytes_current |
number | yes | What is stored right now. |
products.warehouse.currentPeriod.datasets |
number | yes |
JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "ProductUsage", "type": "object", "properties": { "month": { "type": "string", "pattern": "^\\d{4}-\\d{2}$", "description": "'YYYY-MM' (UTC): the period the usage numbers cover." }, "workspace_id": { "type": "string", "description": "The workspace the cards describe." }, "products": { "type": "object", "properties": { "pipelines": { "type": "object", "properties": { "licensed": { "type": "boolean" }, "planKey": { "description": "The plan row that grants this product, or null without one.", "type": [ "string", "null" ] }, "overageOptIn": { "description": "Metered overage consent on that plan row. false = hard cap at the allowance (the default).", "type": [ "boolean", "null" ] }, "draft": { "description": "The plan's pricing is still provisional (plans.config.draft).", "type": [ "boolean", "null" ] }, "allowance": { "anyOf": [ { "type": "object", "properties": { "execution_hours": { "type": [ "number", "null" ] }, "execution_seconds": { "description": "execution_hours × 3600, the unit the cap compares.", "type": [ "number", "null" ] } }, "required": [ "execution_hours", "execution_seconds" ], "additionalProperties": false }, { "type": "null" } ], "description": "null = no plan row, uncapped." }, "currentPeriod": { "type": "object", "properties": { "execution_seconds": { "type": "number" }, "rows_moved": { "type": "number" }, "bytes_moved": { "type": "number" }, "runs": { "type": "number" } }, "required": [ "execution_seconds", "rows_moved", "bytes_moved", "runs" ], "additionalProperties": false, "description": "Month to date: settled ledger days plus a live read of the last two days." } }, "required": [ "licensed", "planKey", "overageOptIn", "draft", "allowance", "currentPeriod" ], "additionalProperties": false, "description": "The Pipelines usage card." }, "warehouse": { "type": "object", "properties": { "licensed": { "type": "boolean" }, "planKey": { "description": "The plan row that grants this product, or null without one.", "type": [ "string", "null" ] }, "overageOptIn": { "description": "Metered overage consent on that plan row. false = hard cap at the allowance (the default).", "type": [ "boolean", "null" ] }, "draft": { "description": "The plan's pricing is still provisional (plans.config.draft).", "type": [ "boolean", "null" ] }, "allowance": { "anyOf": [ { "type": "object", "properties": { "storage_gb": { "type": [ "number", "null" ] }, "storage_bytes": { "description": "storage_gb × 1024³.", "type": [ "number", "null" ] } }, "required": [ "storage_gb", "storage_bytes" ], "additionalProperties": false }, { "type": "null" } ], "description": "null = no plan row, uncapped." }, "currentPeriod": { "type": "object", "properties": { "storage_bytes": { "type": "number", "description": "The month's storage peak: the metered figure." }, "storage_bytes_current": { "type": "number", "description": "What is stored right now." }, "datasets": { "type": "number" } }, "required": [ "storage_bytes", "storage_bytes_current", "datasets" ], "additionalProperties": false, "description": "Month to date." } }, "required": [ "licensed", "planKey", "overageOptIn", "draft", "allowance", "currentPeriod" ], "additionalProperties": false, "description": "The Warehouse usage card." } }, "required": [ "pipelines", "warehouse" ], "additionalProperties": false } }, "required": [ "month", "workspace_id", "products" ], "additionalProperties": false, "description": "Per-product usage against plan allowances for one workspace (GET /api/usage/products)."}PipelineDag
Section titled “PipelineDag”A pipeline definition: the dag field of POST /api/pipelines and PATCH /api/pipelines/{id}. Each step’s config is checked against its step type by validateDag, beyond this envelope.
Used by: POST /api/pipelines (dag in the request body) · PATCH /api/pipelines/{id} (dag in the request body)
| Field | Type | Required | Description |
|---|---|---|---|
version |
1 |
yes | |
steps |
array of object | yes | |
steps[].id |
string | yes | |
steps[].type |
"extract" | "load" | "transform_sql" | "transform_code" | "route" |
yes | |
steps[].config |
map of object | yes | |
steps[].dependsOn |
array of string | no | |
steps[].fromPorts |
map of string | no | |
steps[].retry |
object | no | |
steps[].retry.maxAttempts |
integer | no | |
steps[].retry.initialIntervalMs |
integer | no | |
steps[].retry.backoffCoefficient |
number | no | |
steps[].retry.nonRetryableErrors |
array of string | no | |
steps[].when |
object | no | |
steps[].when.param |
string | yes | |
steps[].when.op |
"eq" | "ne" | "in" | "not_in" | "truthy" | "falsy" |
yes | |
steps[].when.value |
one of 2 shapes | no | |
schedule |
object | no | |
schedule.cron |
string | no | |
schedule.everySeconds |
integer | no | |
schedule.timezone |
string | no | |
schedule.enabled |
boolean | no | |
trigger |
one of 3 shapes | no | |
concurrency |
object | no | |
concurrency.maxConcurrentRuns |
integer | no | |
concurrency.onOverlap |
"skip" | "queue" | "cancel_previous" |
no | |
parameters |
array of object | no | |
parameters[].name |
string | yes | |
parameters[].type |
"string" | "number" | "boolean" | "list" |
yes | |
parameters[].default |
one of 2 shapes | no | |
parameters[].required |
boolean | no | |
parameters[].description |
string | no | |
forEach |
array of object | no | |
forEach[].id |
string | yes | |
forEach[].items |
one of 2 shapes | yes | |
forEach[].steps |
array of string | yes |
JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "PipelineDag", "description": "A pipeline definition: the `dag` field of POST /api/pipelines and PATCH /api/pipelines/{id}. Each step's `config` is checked against its step type by validateDag, beyond this envelope.", "type": "object", "properties": { "version": { "type": "number", "const": 1 }, "steps": { "minItems": 1, "maxItems": 100, "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$" }, "type": { "type": "string", "enum": [ "extract", "load", "transform_sql", "transform_code", "route" ] }, "config": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} }, "dependsOn": { "default": [], "type": "array", "items": { "type": "string" } }, "fromPorts": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "type": "string" } }, "retry": { "type": "object", "properties": { "maxAttempts": { "default": 3, "type": "integer", "minimum": 1, "maximum": 10 }, "initialIntervalMs": { "default": 1000, "type": "integer", "minimum": 100, "maximum": 9007199254740991 }, "backoffCoefficient": { "default": 2, "type": "number", "minimum": 1 }, "nonRetryableErrors": { "default": [], "type": "array", "items": { "type": "string" } } }, "additionalProperties": false }, "when": { "type": "object", "properties": { "param": { "type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,63}$" }, "op": { "type": "string", "enum": [ "eq", "ne", "in", "not_in", "truthy", "falsy" ] }, "value": { "anyOf": [ { "anyOf": [ { "type": "string", "maxLength": 1024 }, { "type": "number" }, { "type": "boolean" } ] }, { "minItems": 1, "maxItems": 100, "type": "array", "items": { "anyOf": [ { "type": "string", "maxLength": 1024 }, { "type": "number" }, { "type": "boolean" } ] } } ] } }, "required": [ "param", "op" ], "additionalProperties": false } }, "required": [ "id", "type", "config" ], "additionalProperties": false } }, "schedule": { "type": "object", "properties": { "cron": { "type": "string", "minLength": 1 }, "everySeconds": { "type": "integer", "minimum": 15, "maximum": 86400 }, "timezone": { "default": "UTC", "type": "string" }, "enabled": { "default": true, "type": "boolean" } }, "additionalProperties": false }, "trigger": { "oneOf": [ { "type": "object", "properties": { "kind": { "type": "string", "const": "file_arrival" }, "sourceId": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "path": { "type": "string", "minLength": 1, "maxLength": 1024 }, "quietSeconds": { "default": 60, "type": "integer", "minimum": 0, "maximum": 3600 }, "minFiles": { "default": 1, "type": "integer", "minimum": 1, "maximum": 10000 } }, "required": [ "kind", "sourceId", "path" ], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "pipeline" }, "pipelineId": { "type": "string", "format": "uuid", "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$" }, "on": { "default": "success", "type": "string", "enum": [ "success", "completion" ] } }, "required": [ "kind", "pipelineId" ], "additionalProperties": false }, { "type": "object", "properties": { "kind": { "type": "string", "const": "webhook" } }, "required": [ "kind" ], "additionalProperties": false } ] }, "concurrency": { "default": { "maxConcurrentRuns": 1, "onOverlap": "skip" }, "type": "object", "properties": { "maxConcurrentRuns": { "default": 1, "type": "integer", "minimum": 1, "maximum": 10 }, "onOverlap": { "default": "skip", "type": "string", "enum": [ "skip", "queue", "cancel_previous" ] } }, "additionalProperties": false }, "parameters": { "maxItems": 50, "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,63}$" }, "type": { "type": "string", "enum": [ "string", "number", "boolean", "list" ] }, "default": { "anyOf": [ { "anyOf": [ { "type": "string", "maxLength": 1024 }, { "type": "number" }, { "type": "boolean" } ] }, { "maxItems": 100, "type": "array", "items": { "anyOf": [ { "type": "string", "maxLength": 256 }, { "type": "number" } ] } } ] }, "required": { "default": false, "type": "boolean" }, "description": { "type": "string", "maxLength": 500 } }, "required": [ "name", "type" ], "additionalProperties": false } }, "forEach": { "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "pattern": "^[a-zA-Z][a-zA-Z0-9]{0,15}$" }, "items": { "anyOf": [ { "minItems": 1, "maxItems": 100, "type": "array", "items": { "anyOf": [ { "type": "string", "maxLength": 256 }, { "type": "number" } ] } }, { "type": "string", "pattern": "^\\{\\{\\s*params\\.([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}$" } ] }, "steps": { "minItems": 1, "maxItems": 50, "type": "array", "items": { "type": "string" } } }, "required": [ "id", "items", "steps" ], "additionalProperties": false } } }, "required": [ "version", "steps" ], "additionalProperties": false}RunStatus
Section titled “RunStatus”Type: "queued" | "running" | "succeeded" | "failed" | "cancelled"
JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "RunStatus", "type": "string", "enum": [ "queued", "running", "succeeded", "failed", "cancelled" ]}StepStatus
Section titled “StepStatus”Type: "queued" | "running" | "succeeded" | "failed" | "cancelled" | "skipped"
JSON Schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "StepStatus", "type": "string", "enum": [ "queued", "running", "succeeded", "failed", "cancelled", "skipped" ]}