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.dev.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.dev.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

Business processes

DoorPurpose
GET /businessProcessesList, paged, with summaries.
POST /businessProcessesCreate from a definition (the JSON the canvas and the MCP compiler produce).
GET /businessProcesses/:idOne process with its definition.
PUT /businessProcesses/:idReplace the definition; validated on the way in.
DELETE /businessProcesses/:idDelete.
POST /businessProcesses/:id/versionsCut a version (what deploys).
GET /businessProcesses/:id/versionsThe version ledger.
POST /businessProcesses/:id/preflightValidate and check readiness before a deploy: credentials bound, wires typed, gates in place.
GET /businessProcesses/:id/cell-checkWhich runtime cell (runtime × process type) the process needs and whether the tenant has one.

Drafting

DoorPurpose
POST /assist/generateOne-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/modelsThe planner and speech models a person may pick: "Default" plus what your operator offers.
POST /api/authoring/conversationsStart 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/replyAnswer the checkpoint: { "kind": "CONTINUE" | "REVISE" | "APPROVE" | "DENY" | "ANSWER" | "CANCEL", "text"?: "…" }.
GET /api/authoring/conversations?scope=recent&source=own|others|allRecent conversations, finished ones too.
DELETE /api/authoring/conversations/:idStop 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

DoorPurpose
GET /runs, GET /runs/:runIdRuns and one run's record.
GET /runs/:runId/outputWhat a run produced.
GET /runs/:runId/computeWhat it cost: events by class, duration, the credit line.
GET /pods, POST /podsThe runtime pods of the tenant, and enrolling one (on-premises installs).
GET /deployments, POST /deploymentsWhere a version runs, and placing one.

Connectors, credentials, people

DoorPurpose
GET /connectorsThe catalogue as your plan entitles it.
POST /connectors/publish, /takedown, /forkA tenant's own connectors: publish one, withdraw it, fork a platform one.
GET /connector-credentials, POST /connector-credentialsConnections by name and vendor; the secret is written once and never read back.
GET /tenant/members, POST /tenant/members/invitesWho is in the tenant and inviting someone; grants per member.
GET /settings/dappsWhich vendor groups this tenant may use, and why not when not.

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.

The operator's doors (/api/v1/operator/…) are a separate plane with its own sign-in and are not part of the tenant API.