Build with code · API reference
API
A JSON API under /api/v1/console/. Everything the console's screens do goes through these doors; the ones below are the ones a program most often wants.
Authentication
Mint a personal access token in the console (Settings › Tokens) or with the API, then send it on every call:
curl -s https://console.ductileai.com/api/v1/console/tokens \
-H "Content-Type: application/json" --cookie "$SESSION" \
-d '{"name":"ci deploy","ttlDays":90}'
# => { "token": "dpt_…", "expiresAt": "…" } shown once
curl -s https://console.ductileai.com/api/v1/console/businessProcesses \
-H "Authorization: Bearer dpt_…"
A token carries its owner's permissions, intersected with an optional scope at minting (one environment, one folder, one process). It cannot mint tokens, step up, or change sign-in settings. GET /api/v1/console/tokens lists yours; DELETE /api/v1/console/tokens/:id revokes one.
Conventions
- Requests and answers are JSON; a body needs
Content-Type: application/json. - Errors answer
{ "error": "snake_case_code", "detail": … }with the matching status:400invalid body,401not signed in,403not allowed,404not found,409a state that refuses the act,429rate-limited (withretry-after). - Lists page with
?limit=and acursorreturned asnextCursor. - Every write is audited to your tenant's ledger with the token's owner as the actor.
Business processes
| Door | Purpose |
|---|---|
GET /businessProcesses | List, paged, with summaries. |
POST /businessProcesses | Create from a definition (the JSON the canvas and the MCP compiler produce). |
GET /businessProcesses/:id | One process with its definition. |
PUT /businessProcesses/:id | Replace the definition; validated on the way in. |
DELETE /businessProcesses/:id | Delete. |
POST /businessProcesses/:id/versions | Cut a version (what deploys). |
GET /businessProcesses/:id/versions | The version ledger. |
POST /businessProcesses/:id/preflight | Validate and check readiness before a deploy: credentials bound, wires typed, gates in place. |
GET /businessProcesses/:id/cell-check | Which runtime cell (runtime × process type) the process needs and whether the tenant has one. |
Drafting
| Door | Purpose |
|---|---|
POST /assist/generate | One-shot: { "brief": "…", "model": "default" } → a validated draft, its plan summary and what is still to fill. model is an id from GET /assist/models. |
GET /assist/models | The planner and speech models a person may pick: "Default" plus what your operator offers. |
POST /api/authoring/conversations | Start a conversation: { "goal": "…", "model"?: id }. Answers the conversation with its checkpoint (approve, revise, answer a question) and, when it has one, the draft. |
POST /api/authoring/conversations/:id/reply | Answer the checkpoint: { "kind": "CONTINUE" | "REVISE" | "APPROVE" | "DENY" | "ANSWER" | "CANCEL", "text"?: "…" }. |
GET /api/authoring/conversations?scope=recent&source=own|others|all | Recent conversations, finished ones too. |
DELETE /api/authoring/conversations/:id | Stop it; add ?purge=1 to delete your own for good. |
POST /api/authoring/transcribe?model= | Speech to text: post the audio bytes with their content type. |
Runs and deployments
| Door | Purpose |
|---|---|
GET /runs, GET /runs/:runId | Runs and one run's record. |
GET /runs/:runId/output | What a run produced. |
GET /runs/:runId/compute | What it cost: events by class, duration, the credit line. |
GET /pods, POST /pods | The runtime pods of the tenant, and enrolling one (on-premises installs). |
GET /deployments, POST /deployments | Where a version runs, and placing one. |
Connectors, credentials, people
| Door | Purpose |
|---|---|
GET /connectors | The catalogue as your plan entitles it. |
POST /connectors/publish, /takedown, /fork | A tenant's own connectors: publish one, withdraw it, fork a platform one. |
GET /connector-credentials, POST /connector-credentials | Connections by name and vendor; the secret is written once and never read back. |
GET /tenant/members, POST /tenant/members/invites | Who is in the tenant and inviting someone; grants per member. |
GET /settings/dapps | Which vendor groups this tenant may use, and why not when not. |
AI gateway
Every model call and every MCP tool call a process makes goes through the gateway on your pods: which providers and models, what leaves the pod, what a day or a month may cost, and a line of audit per call. The organisation sets it once, here or in Settings › AI gateway, and every running pod picks it up within one heartbeat.
| Door | Purpose |
|---|---|
GET /settings/ai-gateway | The settings, the models, the keys and the MCP servers, in one answer. |
PUT /settings/ai-gateway | The settings: the default, light and fallback model (by alias); providers allowed; kinds of tool refused; redaction of identifiers before text leaves (emails, card numbers, phone numbers, SSNs, IBANs, keys become [email], [card]…); tokens a day, a budget a month for the organisation and for each job, tokens per call; seconds to answer an identical request from the gateway. 0 is no limit; the plan's ceiling caps the monthly budget. |
PUT /settings/ai-gateway/models/:alias, DELETE …/models/:alias | A model behind a name your steps use - strong, light - over a provider's model and the credential that holds its key; an optional price per million tokens in and out, for the spend figures. |
POST /settings/ai-gateway/keys, DELETE …/keys/:id | A virtual key (dai_ak_…) for your own application, shown once; scoped to a job, with the aliases it may use and a monthly budget. Only its hash is kept. |
GET /settings/ai-gateway/usage?from=&to= | Spend by day, provider and model or tool - calls, refusals, tokens, dollars - as your pods report it. |
GET /settings/ai-gateway/pod-properties | Exactly what a pod reads from these settings, for an administrator to check. |
Webhooks and triggers
A deployed process can start from a schedule, an inbound webhook or a vendor event; the console issues the webhook URL and its secret when the trigger is created (GET /triggers, POST /triggers). Inbound requests are verified against that secret and rate-limited per trigger.
A process whose job is called by your own application can be called with a gateway key instead of the trigger's secret: Authorization: Bearer dai_ak_…. A revoked, expired or out-of-project key is refused like any bad key, and the key's last use is recorded. That is the door for an enterprise app that wants a model answer, an MCP tool result, or both, behind one policy and one audit trail: a process with Ask AI with tools or Call an MCP tool, called by key.
Calling a process
Your app calls a process at the address the console shows for it. A process is Sandbox or Reserved; Reserved comes with Team and higher plans. We keep every call to a Reserved process until it has been answered, and try again when it could not be. A call that still cannot be answered waits On hold, where you can run it again or remove it.
| Door | Purpose |
|---|---|
GET /on-hold | The calls on hold. |
POST /on-hold:run-again | Run them again. |
POST /on-hold:remove | Remove them. |
The operator's doors (/api/v1/operator/…) are a separate plane with its own sign-in and are not part of the tenant API.
Last updated October 29, 2026