API data schemas
Current release · Updated October 2, 2026
Shared request and response shapes. Field descriptions include bounds and state-dependent requirements. See each endpoint for permissions and additional validation.
Error
| Field | Type | Required | Details |
|---|---|---|---|
error | object | Yes |
{
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Recovery message"
},
"request_id": {
"type": "string",
"description": "Request correlation ID; may be absent on a rate limit response"
}
},
"required": [
"message"
]
}
},
"required": [
"error"
]
}OK
| Field | Type | Required | Details |
|---|---|---|---|
ok | true | Yes |
{
"type": "object",
"properties": {
"ok": {
"type": "boolean",
"const": true
}
},
"required": [
"ok"
]
}Record
| Field | Type | Required | Details |
|---|---|---|---|
id | uuid | Yes | |
tenant_id | uuid | No | |
object_key | string | Yes | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
data | object | Yes | Object field values. Only keys in the workspace object definition are allowed; required fields and field types are validated. |
version | integer | Yes | Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes. Min 1. |
created_by | uuid | No | |
created_at | date-time | No | |
updated_at | date-time | No |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"tenant_id": {
"type": "string",
"format": "uuid"
},
"object_key": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "Object field values. Only keys in the workspace object definition are allowed; required fields and field types are validated."
},
"version": {
"type": "integer",
"description": "Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes.",
"minimum": 1
},
"created_by": {
"type": "string",
"format": "uuid"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"object_key",
"data",
"version"
]
}RecordPage
| Field | Type | Required | Details |
|---|---|---|---|
items | Record[] | Yes | |
total | integer | Yes | Number matching the full query, before cursor |
next_cursor | string or null | Yes | Opaque cursor for the next page; null ends pagination. |
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Record"
}
},
"total": {
"type": "integer",
"description": "Number matching the full query, before cursor"
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Opaque cursor for the next page; null ends pagination."
}
},
"required": [
"items",
"total",
"next_cursor"
]
}Field
| Field | Type | Required | Details |
|---|---|---|---|
key | string | Yes | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
name | string | Yes | Field label Max 80 characters. |
type | text | email | phone | number | currency | boolean | date | select | multi_select | relation | json | Yes | Field type |
required | boolean | No | Defaults false |
options | string[] | No | Max 100 items. |
object | string | No | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
{
"type": "object",
"properties": {
"key": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"name": {
"type": "string",
"description": "Field label",
"maxLength": 80
},
"type": {
"type": "string",
"enum": [
"text",
"email",
"phone",
"number",
"currency",
"boolean",
"date",
"select",
"multi_select",
"relation",
"json"
],
"description": "Field type"
},
"required": {
"type": "boolean",
"description": "Defaults false"
},
"options": {
"type": "array",
"items": {
"type": "string",
"description": "Option",
"maxLength": 80
},
"minItems": 0,
"maxItems": 100
},
"object": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
}
},
"required": [
"key",
"name",
"type"
]
}Object
| Field | Type | Required | Details |
|---|---|---|---|
key | string | Yes | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
name | string | Yes | Plural label Max 80 characters. |
singular_name | string | Yes | Singular label Max 80 characters. |
fields | Field[] | Yes | Min 1 items. Max 100 items. |
{
"type": "object",
"properties": {
"key": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"name": {
"type": "string",
"description": "Plural label",
"maxLength": 80
},
"singular_name": {
"type": "string",
"description": "Singular label",
"maxLength": 80
},
"fields": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Field"
},
"minItems": 1,
"maxItems": 100
}
},
"required": [
"key",
"name",
"singular_name",
"fields"
]
}Filter
| Field | Type | Required | Details |
|---|---|---|---|
match | all | any | Yes | Combine conditions |
conditions | object[] | Yes | Min 1 items. Max 12 items. |
{
"type": "object",
"properties": {
"match": {
"type": "string",
"enum": [
"all",
"any"
],
"description": "Combine conditions"
},
"conditions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"operator": {
"type": "string",
"enum": [
"eq",
"ne",
"contains",
"not_contains",
"gt",
"gte",
"lt",
"lte",
"empty",
"not_empty"
],
"description": "Supported operators depend on field type. Relations and JSON are excluded."
},
"value": {
"type": [
"string",
"number",
"boolean"
],
"description": "Typed comparison value; omit for empty/not_empty."
}
},
"required": [
"field",
"operator"
]
},
"minItems": 1,
"maxItems": 12
}
},
"required": [
"match",
"conditions"
]
}SmartList
| Field | Type | Required | Details |
|---|---|---|---|
id | uuid | Yes | |
object_key | string | No | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
name | string | Yes | Unique name per object Max 80 characters. |
filter | Filter | Yes | |
version | integer | Yes | Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes. Min 1. |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"object_key": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"name": {
"type": "string",
"description": "Unique name per object",
"maxLength": 80
},
"filter": {
"$ref": "#/components/schemas/Filter"
},
"version": {
"type": "integer",
"description": "Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes.",
"minimum": 1
}
},
"required": [
"id",
"name",
"filter",
"version"
]
}ListInput
| Field | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Nonblank list name Max 80 characters. |
filter | Filter | Yes |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Nonblank list name",
"maxLength": 80
},
"filter": {
"$ref": "#/components/schemas/Filter"
}
},
"required": [
"name",
"filter"
]
}Import
| Field | Type | Required | Details |
|---|---|---|---|
csv | string | Yes | UTF-8 CSV content, not a file path. Header required; <=500 data rows. Max 300000 characters. |
mapping | string or null[] | No | Max 100 items. |
duplicates | skip | update | error | No | People email duplicate policy, default skip. Blank update cells preserve existing values. |
{
"type": "object",
"properties": {
"csv": {
"type": "string",
"description": "UTF-8 CSV content, not a file path. Header required; <=500 data rows.",
"maxLength": 300000
},
"mapping": {
"type": "array",
"items": {
"type": [
"string",
"null"
],
"description": "Field key per CSV column, null skips a column. Omit to match field keys/labels."
},
"minItems": 0,
"maxItems": 100
},
"duplicates": {
"type": "string",
"enum": [
"skip",
"update",
"error"
],
"description": "People email duplicate policy, default skip. Blank update cells preserve existing values."
}
},
"required": [
"csv"
]
}ImportReport
| Field | Type | Required | Details |
|---|---|---|---|
headers | string[] | No | |
mapping | string or null[] | No | |
rows | integer | No | Data rows |
created | integer | No | Planned creates |
updated | integer | No | Planned updates |
skipped | integer | No | Planned skips |
error_count | integer | No | All errors |
errors | object[] | No | |
preview | object[] | No | |
can_import | boolean | No | True only if the whole import is valid |
{
"type": "object",
"properties": {
"headers": {
"type": "array",
"items": {
"type": "string",
"description": "CSV heading"
}
},
"mapping": {
"type": "array",
"items": {
"type": [
"string",
"null"
]
}
},
"rows": {
"type": "integer",
"description": "Data rows"
},
"created": {
"type": "integer",
"description": "Planned creates"
},
"updated": {
"type": "integer",
"description": "Planned updates"
},
"skipped": {
"type": "integer",
"description": "Planned skips"
},
"error_count": {
"type": "integer",
"description": "All errors"
},
"errors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"line": {
"type": "integer",
"description": "CSV line"
},
"message": {
"type": "string",
"description": "Validation error"
}
},
"required": []
}
},
"preview": {
"type": "array",
"items": {
"type": "object",
"properties": {
"line": {
"type": "integer",
"description": "CSV line"
},
"action": {
"type": "string",
"description": "create, update or skip"
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "Object field values. Only keys in the workspace object definition are allowed; required fields and field types are validated."
}
},
"required": []
}
},
"can_import": {
"type": "boolean",
"description": "True only if the whole import is valid"
}
},
"required": []
}Pipeline
| Field | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Pipeline name Max 100 characters. |
stages | object[] | Yes | Min 1 items. Max 30 items. |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Pipeline name",
"maxLength": 100
},
"stages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9_-]{1,40}$"
},
"name": {
"type": "string",
"description": "Stage label",
"maxLength": 80
},
"probability": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"color": {
"type": "string",
"pattern": "^#[0-9a-fA-F]{6}$"
}
},
"required": [
"id",
"name",
"probability",
"color"
]
},
"minItems": 1,
"maxItems": 30
}
},
"required": [
"name",
"stages"
]
}Widget
| Field | Type | Required | Details |
|---|---|---|---|
id | string | Yes | Unique widget ID Max 80 characters. |
title | string | Yes | KPI title Max 120 characters. |
object | string | Yes | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
operation | count | sum | avg | Yes | Aggregation |
field | string | No | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
group_by | string | No | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
display | metric | bar | donut | Yes | Presentation |
currency | string | No | Currency for monetary results |
filter | object | No |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique widget ID",
"maxLength": 80
},
"title": {
"type": "string",
"description": "KPI title",
"maxLength": 120
},
"object": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"operation": {
"type": "string",
"enum": [
"count",
"sum",
"avg"
],
"description": "Aggregation"
},
"field": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"group_by": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"display": {
"type": "string",
"enum": [
"metric",
"bar",
"donut"
],
"description": "Presentation"
},
"currency": {
"type": "string",
"description": "Currency for monetary results"
},
"filter": {
"type": "object",
"properties": {
"field": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"value": {
"type": "string",
"description": "Exact text comparison",
"maxLength": 200
}
},
"required": [
"field",
"value"
]
}
},
"required": [
"id",
"title",
"object",
"operation",
"display"
]
}FinanceProfile
| Field | Type | Required | Details |
|---|---|---|---|
business_name | string | Yes | Nonblank issuer name Max 160 characters. |
email | email or | No | |
address | string | No | Issuer address Max 2000 characters. |
tax_id | string | No | Tax reference Max 100 characters. |
payment_instructions | string | No | Payment instructions Max 2000 characters. |
invoice_prefix | string | No | Pattern: ^[A-Z0-9-]{1,12}$. |
{
"type": "object",
"properties": {
"business_name": {
"type": "string",
"description": "Nonblank issuer name",
"maxLength": 160
},
"email": {
"oneOf": [
{
"type": "string",
"format": "email",
"maxLength": 200
},
{
"const": ""
}
]
},
"address": {
"type": "string",
"description": "Issuer address",
"maxLength": 2000
},
"tax_id": {
"type": "string",
"description": "Tax reference",
"maxLength": 100
},
"payment_instructions": {
"type": "string",
"description": "Payment instructions",
"maxLength": 2000
},
"invoice_prefix": {
"type": "string",
"pattern": "^[A-Z0-9-]{1,12}$",
"default": "INV"
}
},
"required": [
"business_name"
]
}InvoiceData
Draft inputs; custom optional fields are allowed if defined. Quantity >0 to 1,000,000 with <=3 decimals. Discount is a line amount, tax_rate is 0-100 percent with <=2 decimals. Due date cannot precede issue date. Totals/status/issuer/number are server managed.
| Field | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Required title |
customer_name | string | Yes | Required customer name |
customer_email | No | Max 200 characters. | |
billing_address | string | No | Address |
contact_id | uuid | No | |
deal_id | uuid | No | |
currency | string | Yes | Enabled currency code |
issue_date | date | Yes | Valid calendar date, YYYY-MM-DD. |
due_date | date | Yes | Valid calendar date, YYYY-MM-DD. |
items | object[] | Yes | Min 1 items. Max 100 items. |
notes | string | No | Notes |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Required title"
},
"customer_name": {
"type": "string",
"description": "Required customer name"
},
"customer_email": {
"type": "string",
"format": "email",
"maxLength": 200
},
"billing_address": {
"type": "string",
"description": "Address"
},
"contact_id": {
"type": "string",
"format": "uuid"
},
"deal_id": {
"type": "string",
"format": "uuid"
},
"currency": {
"type": "string",
"description": "Enabled currency code"
},
"issue_date": {
"type": "string",
"format": "date",
"description": "Valid calendar date, YYYY-MM-DD."
},
"due_date": {
"type": "string",
"format": "date",
"description": "Valid calendar date, YYYY-MM-DD."
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {
"type": "string",
"description": "Nonblank description",
"maxLength": 500
},
"quantity": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply."
},
"unit_price": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply."
},
"discount": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply."
},
"tax_rate": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply."
}
},
"required": [
"description",
"quantity",
"unit_price"
]
},
"minItems": 1,
"maxItems": 100
},
"notes": {
"type": "string",
"description": "Notes"
}
},
"required": [
"name",
"customer_name",
"currency",
"issue_date",
"due_date",
"items"
],
"description": "Draft inputs; custom optional fields are allowed if defined. Quantity >0 to 1,000,000 with <=3 decimals. Discount is a line amount, tax_rate is 0-100 percent with <=2 decimals. Due date cannot precede issue date. Totals/status/issuer/number are server managed."
}ExpenseData
Amount must be positive; tax is included in amount and cannot exceed it. Custom optional fields are allowed if defined. Status/approval/totals are server managed.
| Field | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Required title |
vendor | string | Yes | Required vendor |
category | string | No | Category |
spent_on | date | Yes | Valid calendar date, YYYY-MM-DD. |
currency | string | Yes | Enabled currency code |
amount | string or number | Yes | Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply. |
tax | string or number | No | Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply. |
receipt_url | uri | No | HTTP(S) reference; no receipt upload endpoint. |
notes | string | No | Notes |
deal_id | uuid | No |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Required title"
},
"vendor": {
"type": "string",
"description": "Required vendor"
},
"category": {
"type": "string",
"description": "Category"
},
"spent_on": {
"type": "string",
"format": "date",
"description": "Valid calendar date, YYYY-MM-DD."
},
"currency": {
"type": "string",
"description": "Enabled currency code"
},
"amount": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply."
},
"tax": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply."
},
"receipt_url": {
"type": "string",
"format": "uri",
"description": "HTTP(S) reference; no receipt upload endpoint."
},
"notes": {
"type": "string",
"description": "Notes"
},
"deal_id": {
"type": "string",
"format": "uuid"
}
},
"required": [
"name",
"vendor",
"spent_on",
"currency",
"amount"
],
"description": "Amount must be positive; tax is included in amount and cannot exceed it. Custom optional fields are allowed if defined. Status/approval/totals are server managed."
}Payment
| Field | Type | Required | Details |
|---|---|---|---|
id | uuid | Yes | |
version | integer | Yes | Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes. Min 1. |
amount | string or number | Yes | Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply. |
paid_on | date | Yes | Valid calendar date, YYYY-MM-DD. |
method | Bank transfer | Cash | Card | Other | Yes | Payment handled outside DryKraft |
reference | string | Yes | Nonblank payment reference Max 200 characters. |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"version": {
"type": "integer",
"description": "Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes.",
"minimum": 1
},
"amount": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Major currency units, nonnegative. Use decimal strings to retain precision. Currency-specific decimal places apply."
},
"paid_on": {
"type": "string",
"format": "date",
"description": "Valid calendar date, YYYY-MM-DD."
},
"method": {
"type": "string",
"enum": [
"Bank transfer",
"Cash",
"Card",
"Other"
],
"description": "Payment handled outside DryKraft"
},
"reference": {
"type": "string",
"description": "Nonblank payment reference",
"maxLength": 200
}
},
"required": [
"id",
"version",
"amount",
"paid_on",
"method",
"reference"
]
}NodeData
Fields are conditional on kind; publish enforces the required node settings. Extra runtime context fields may exist.
| Field | Type | Required | Details |
|---|---|---|---|
kind | trigger.manual | trigger.event | trigger.schedule | trigger.webhook | condition | wait | set | crm.create | crm.update | finance.create | http | log | Yes | Outreach kinds are managed and rejected by the general editor. |
label | string | Yes | Nonempty node label Max 100 characters. |
event | string | No | Required for trigger.event Max 100 characters. |
intervalMinutes | integer | No | Required for trigger.schedule Min 1. Max 525600. |
seconds | integer | No | Required for wait Min 1. Max 2592000. |
object | string | No | Required for crm.create/update; finance.create only invoices or expenses Pattern: ^[a-z][a-z0-9_]{1,39}$. |
values | object | No | Required for set or record create/update; interpolated context values |
recordId | string | No | Required for crm.update; UUID or context expression |
field | string | No | Required context path for condition Max 100 characters. |
operator | eq | neq | gte | gt | lte | lt | contains | exists | No | Required for condition |
value | string or number or boolean or object or array or null | No | Condition comparison value, interpolated |
url | uri | No | Required for http; public destination only |
method | GET | POST | PUT | PATCH | DELETE | No | http method, default GET |
credentialId | uuid | No | Optional saved outbound credential. Headers are server-managed, not arbitrary draft headers. |
body | string or object or array or null | No | http body; interpolated |
message | string | No | log message; context expressions supported |
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": [
"trigger.manual",
"trigger.event",
"trigger.schedule",
"trigger.webhook",
"condition",
"wait",
"set",
"crm.create",
"crm.update",
"finance.create",
"http",
"log"
],
"description": "Outreach kinds are managed and rejected by the general editor."
},
"label": {
"type": "string",
"description": "Nonempty node label",
"maxLength": 100
},
"event": {
"type": "string",
"description": "Required for trigger.event",
"maxLength": 100
},
"intervalMinutes": {
"type": "integer",
"description": "Required for trigger.schedule",
"minimum": 1,
"maximum": 525600
},
"seconds": {
"type": "integer",
"description": "Required for wait",
"minimum": 1,
"maximum": 2592000
},
"object": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$",
"description": "Required for crm.create/update; finance.create only invoices or expenses"
},
"values": {
"type": "object",
"additionalProperties": true,
"description": "Required for set or record create/update; interpolated context values"
},
"recordId": {
"type": "string",
"description": "Required for crm.update; UUID or context expression"
},
"field": {
"type": "string",
"description": "Required context path for condition",
"maxLength": 100
},
"operator": {
"type": "string",
"enum": [
"eq",
"neq",
"gte",
"gt",
"lte",
"lt",
"contains",
"exists"
],
"description": "Required for condition"
},
"value": {
"description": "Condition comparison value, interpolated",
"type": [
"string",
"number",
"boolean",
"object",
"array",
"null"
]
},
"url": {
"type": "string",
"format": "uri",
"description": "Required for http; public destination only"
},
"method": {
"type": "string",
"enum": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE"
],
"description": "http method, default GET"
},
"credentialId": {
"type": "string",
"format": "uuid",
"description": "Optional saved outbound credential. Headers are server-managed, not arbitrary draft headers."
},
"body": {
"description": "http body; interpolated",
"type": [
"string",
"object",
"array",
"null"
]
},
"message": {
"type": "string",
"description": "log message; context expressions supported"
}
},
"required": [
"kind",
"label"
],
"description": "Fields are conditional on kind; publish enforces the required node settings. Extra runtime context fields may exist."
}Graph
| Field | Type | Required | Details |
|---|---|---|---|
nodes | object[] | Yes | Min 1 items. Max 100 items. |
edges | object[] | Yes | Max 150 items. |
{
"type": "object",
"properties": {
"nodes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique nonempty node ID",
"maxLength": 80
},
"type": {
"const": "workflow"
},
"position": {
"type": "object",
"properties": {
"x": {
"type": "number"
},
"y": {
"type": "number"
}
},
"required": [
"x",
"y"
]
},
"data": {
"$ref": "#/components/schemas/NodeData"
}
},
"required": [
"id",
"type",
"position",
"data"
]
},
"minItems": 1,
"maxItems": 100
},
"edges": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Edge ID"
},
"source": {
"type": "string",
"description": "Source node"
},
"target": {
"type": "string",
"description": "Target node"
},
"sourceHandle": {
"type": [
"string",
"null"
]
},
"targetHandle": {
"type": [
"string",
"null"
]
},
"label": {
"type": "string",
"description": "Optional label"
}
},
"required": [
"id",
"source",
"target"
]
},
"minItems": 0,
"maxItems": 150
}
},
"required": [
"nodes",
"edges"
]
}Workflow
| Field | Type | Required | Details |
|---|---|---|---|
id | uuid | No | |
name | string | No | Name |
description | string | No | Description |
draft | Graph | No | |
status | string | No | draft, active or paused |
published_version_id | string or null | No | |
created_at | string | No | Timestamp |
updated_at | string | No | Timestamp |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"description": "Name"
},
"description": {
"type": "string",
"description": "Description"
},
"draft": {
"$ref": "#/components/schemas/Graph"
},
"status": {
"type": "string",
"description": "draft, active or paused"
},
"published_version_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"created_at": {
"type": "string",
"description": "Timestamp"
},
"updated_at": {
"type": "string",
"description": "Timestamp"
}
},
"required": []
}Execution
| Field | Type | Required | Details |
|---|---|---|---|
id | uuid | No | |
workflow_id | uuid | No | |
version_id | uuid | No | |
state | string | No | queued, running, waiting, retrying, succeeded, failed or cancelled |
input | object | No | Object field values. Only keys in the workspace object definition are allowed; required fields and field types are validated. |
context | object | No | Object field values. Only keys in the workspace object definition are allowed; required fields and field types are validated. |
current_node | string or null | No | |
error | string or null | No | |
created_at | string | No | Timestamp |
completed_at | string or null | No |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"workflow_id": {
"type": "string",
"format": "uuid"
},
"version_id": {
"type": "string",
"format": "uuid"
},
"state": {
"type": "string",
"description": "queued, running, waiting, retrying, succeeded, failed or cancelled"
},
"input": {
"type": "object",
"additionalProperties": true,
"description": "Object field values. Only keys in the workspace object definition are allowed; required fields and field types are validated."
},
"context": {
"type": "object",
"additionalProperties": true,
"description": "Object field values. Only keys in the workspace object definition are allowed; required fields and field types are validated."
},
"current_node": {
"type": [
"string",
"null"
]
},
"error": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"description": "Timestamp"
},
"completed_at": {
"type": [
"string",
"null"
]
}
},
"required": []
}Connection
| Field | Type | Required | Details |
|---|---|---|---|
id | uuid | No | |
name | string | No | Name |
channel | email | sms | voice | whatsapp | No | Channel |
provider | smtp | google | microsoft | curl | qcall | whatsapp | No | Provider |
config | object | No | Public provider metadata; no private credentials |
enabled | boolean | No | Connection enabled |
verified_at | string or null | No | |
last_error | string or null | No | |
daily_limit | integer | No | Rolling daily allowance Min 1. Max 10000. |
hourly_limit | integer | No | Rolling hourly allowance Min 1. Max 2000. |
created_at | string | No | Timestamp |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"description": "Name"
},
"channel": {
"type": "string",
"enum": [
"email",
"sms",
"voice",
"whatsapp"
],
"description": "Channel"
},
"provider": {
"type": "string",
"enum": [
"smtp",
"google",
"microsoft",
"curl",
"qcall",
"whatsapp"
],
"description": "Provider"
},
"config": {
"type": "object",
"description": "Public provider metadata; no private credentials"
},
"enabled": {
"type": "boolean",
"description": "Connection enabled"
},
"verified_at": {
"type": [
"string",
"null"
]
},
"last_error": {
"type": [
"string",
"null"
]
},
"daily_limit": {
"type": "integer",
"description": "Rolling daily allowance",
"minimum": 1,
"maximum": 10000
},
"hourly_limit": {
"type": "integer",
"description": "Rolling hourly allowance",
"minimum": 1,
"maximum": 2000
},
"created_at": {
"type": "string",
"description": "Timestamp"
}
},
"required": []
}SMTPSecret
| Field | Type | Required | Details |
|---|---|---|---|
email | Yes | Max 200 characters. | |
host | string | Yes | Public SMTP hostname |
port | 465 | 587 | Yes | |
user | string | Yes | Username |
password | string | Yes | Password/app password |
imap | object | No |
{
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"maxLength": 200
},
"host": {
"type": "string",
"description": "Public SMTP hostname"
},
"port": {
"enum": [
465,
587
]
},
"user": {
"type": "string",
"description": "Username"
},
"password": {
"type": "string",
"description": "Password/app password"
},
"imap": {
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Public IMAP hostname; TLS port 993"
},
"user": {
"type": "string",
"description": "Username"
},
"password": {
"type": "string",
"description": "Password/app password"
}
},
"required": [
"host",
"user",
"password"
]
}
},
"required": [
"email",
"host",
"port",
"user",
"password"
]
}SMSSecret
| Field | Type | Required | Details |
|---|---|---|---|
curl | string | Yes | One literal HTTPS:443 POST JSON cURL. No execution or file input. Max 50000 characters. |
recipientPath | string | Yes | Existing body path, e.g. recipients.0.mobiles Max 150 characters. |
messagePath | string | No | Optional message body path Max 150 characters. |
{
"type": "object",
"properties": {
"curl": {
"type": "string",
"description": "One literal HTTPS:443 POST JSON cURL. No execution or file input.",
"maxLength": 50000
},
"recipientPath": {
"type": "string",
"description": "Existing body path, e.g. recipients.0.mobiles",
"maxLength": 150
},
"messagePath": {
"type": "string",
"description": "Optional message body path",
"maxLength": 150
}
},
"required": [
"curl",
"recipientPath"
]
}VoiceSecret
| Field | Type | Required | Details |
|---|---|---|---|
apiKey | string | Yes | Workspace QCall API key |
{
"type": "object",
"properties": {
"apiKey": {
"type": "string",
"description": "Workspace QCall API key"
}
},
"required": [
"apiKey"
]
}WhatsAppSecret
| Field | Type | Required | Details |
|---|---|---|---|
accessToken | string | Yes | Meta access token |
appSecret | string | Yes | Meta app secret |
wabaId | string | Yes | Pattern: ^\d{5,40}$. |
phoneId | string | Yes | Pattern: ^\d{5,40}$. |
version | string | No | Pattern: ^v\d{2}\.0$. |
{
"type": "object",
"properties": {
"accessToken": {
"type": "string",
"description": "Meta access token"
},
"appSecret": {
"type": "string",
"description": "Meta app secret"
},
"wabaId": {
"type": "string",
"pattern": "^\\d{5,40}$"
},
"phoneId": {
"type": "string",
"pattern": "^\\d{5,40}$"
},
"version": {
"type": "string",
"pattern": "^v\\d{2}\\.0$",
"default": "v23.0"
}
},
"required": [
"accessToken",
"appSecret",
"wabaId",
"phoneId"
]
}ConnectionInput
| Field | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Nonblank name Max 100 characters. |
provider | smtp | curl | qcall | whatsapp | Yes | Use native OAuth endpoints for Google/Outlook. |
daily_limit | integer | No | Defaults 100 Min 1. Max 10000. |
hourly_limit | integer | No | Defaults 20 Min 1. Max 2000. |
secret | SMTPSecret or SMSSecret or VoiceSecret or WhatsAppSecret | Yes | Choose the schema matching provider. Secret is encrypted and never returned. |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Nonblank name",
"maxLength": 100
},
"provider": {
"type": "string",
"enum": [
"smtp",
"curl",
"qcall",
"whatsapp"
],
"description": "Use native OAuth endpoints for Google/Outlook."
},
"daily_limit": {
"type": "integer",
"description": "Defaults 100",
"minimum": 1,
"maximum": 10000
},
"hourly_limit": {
"type": "integer",
"description": "Defaults 20",
"minimum": 1,
"maximum": 2000
},
"secret": {
"oneOf": [
{
"$ref": "#/components/schemas/SMTPSecret"
},
{
"$ref": "#/components/schemas/SMSSecret"
},
{
"$ref": "#/components/schemas/VoiceSecret"
},
{
"$ref": "#/components/schemas/WhatsAppSecret"
}
],
"description": "Choose the schema matching provider. Secret is encrypted and never returned."
}
},
"required": [
"name",
"provider",
"secret"
]
}Step
All optional fields default to empty except language. Email requires subject/body; SMS needs body or variables; voice requires assistant/dialer; WhatsApp requires template/language. Interpolate {{record.data.name}} and other context paths.
| Field | Type | Required | Details |
|---|---|---|---|
waitHours | integer | No | Wait before this step, default 0 Min 0. Max 720. |
subject | string | No | Email subject; nonblank for email Max 300 characters. |
body | string | No | Email/SMS body; email requires nonblank Max 10000 characters. |
variables | object | No | Keys: 1-40 letters, digits or underscores |
template | string | No | Approved WhatsApp template name Max 100 characters. |
language | string | No | WhatsApp language, default en Max 20 characters. |
parameters | string[] | No | Max 20 items. |
assistantId | string | No | QCall assistant ID Max 100 characters. |
dialerId | string | No | QCall dialer ID Max 100 characters. |
{
"type": "object",
"properties": {
"waitHours": {
"type": "integer",
"description": "Wait before this step, default 0",
"minimum": 0,
"maximum": 720
},
"subject": {
"type": "string",
"description": "Email subject; nonblank for email",
"maxLength": 300
},
"body": {
"type": "string",
"description": "Email/SMS body; email requires nonblank",
"maxLength": 10000
},
"variables": {
"type": "object",
"additionalProperties": {
"type": "string",
"description": "SMS template variable, max 1,000 characters",
"maxLength": 1000
},
"description": "Keys: 1-40 letters, digits or underscores"
},
"template": {
"type": "string",
"description": "Approved WhatsApp template name",
"maxLength": 100
},
"language": {
"type": "string",
"description": "WhatsApp language, default en",
"maxLength": 20
},
"parameters": {
"type": "array",
"items": {
"type": "string",
"description": "WhatsApp body parameter",
"maxLength": 1000
},
"minItems": 0,
"maxItems": 20
},
"assistantId": {
"type": "string",
"description": "QCall assistant ID",
"maxLength": 100
},
"dialerId": {
"type": "string",
"description": "QCall dialer ID",
"maxLength": 100
}
},
"required": [],
"description": "All optional fields default to empty except language. Email requires subject/body; SMS needs body or variables; voice requires assistant/dialer; WhatsApp requires template/language. Interpolate {{record.data.name}} and other context paths."
}CampaignInput
| Field | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Nonblank name Max 100 characters. |
kind | campaign | sequence | Yes | A campaign has exactly one step; a sequence has 1-20. |
channel | email | sms | voice | whatsapp | Yes | One channel per campaign/sequence |
object_key | string | No | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
list_id | string or null | No | |
connection_id | uuid | Yes | |
steps | Step[] | Yes | Min 1 items. Max 20 items. |
{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Nonblank name",
"maxLength": 100
},
"kind": {
"type": "string",
"enum": [
"campaign",
"sequence"
],
"description": "A campaign has exactly one step; a sequence has 1-20."
},
"channel": {
"type": "string",
"enum": [
"email",
"sms",
"voice",
"whatsapp"
],
"description": "One channel per campaign/sequence"
},
"object_key": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$",
"default": "people"
},
"list_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"default": null
},
"connection_id": {
"type": "string",
"format": "uuid"
},
"steps": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Step"
},
"minItems": 1,
"maxItems": 20
}
},
"required": [
"name",
"kind",
"channel",
"connection_id",
"steps"
]
}Campaign
| Field | Type | Required | Details |
|---|---|---|---|
id | uuid | No | |
name | string | No | Name |
kind | string | No | campaign or sequence |
channel | string | No | Channel |
object_key | string | No | Pattern: ^[a-z][a-z0-9_]{1,39}$. |
list_id | string or null | No | |
connection_id | uuid | No | |
workflow_id | uuid | No | |
steps | Step[] | No | |
status | string | No | draft, active, paused or cancelled |
version | integer | No | Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes. Min 1. |
created_at | string | No | Timestamp |
updated_at | string | No | Timestamp |
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"description": "Name"
},
"kind": {
"type": "string",
"description": "campaign or sequence"
},
"channel": {
"type": "string",
"description": "Channel"
},
"object_key": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]{1,39}$"
},
"list_id": {
"type": [
"string",
"null"
]
},
"connection_id": {
"type": "string",
"format": "uuid"
},
"workflow_id": {
"type": "string",
"format": "uuid"
},
"steps": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Step"
}
},
"status": {
"type": "string",
"description": "draft, active, paused or cancelled"
},
"version": {
"type": "integer",
"description": "Positive optimistic version returned by the latest read. Refresh on 409; do not overwrite stale changes.",
"minimum": 1
},
"created_at": {
"type": "string",
"description": "Timestamp"
},
"updated_at": {
"type": "string",
"description": "Timestamp"
}
},
"required": []
}