#Projects
List projects, retrieve project details, manage partner project lifecycle/profile/assignment state, update draft runtime workspaces, run controlled release operations, access legacy project billing configuration.
- Production API:
https://api.aidial.ai - Version prefix:
/v1
This page omits environment-specific host names, internal topology, and deployment details.
Protected project routes use shared authentication unless the endpoint states a stricter scope. Shared authentication resolves credentials in this order:
X-API-KeyAuthorization: Bearer <jwt>
Both modes resolve to an AuthContext. Bearer authentication requires ZITADEL_ISSUER, ZITADEL_AUDIENCE, and ZITADEL_JWKS_URL; these settings are required and have no fallback defaults.
Project metadata, lifecycle state, drafts, published versions, legacy project billing configuration are stored server-side. Project-secret values are handled by server-side secret writers and are not returned by project responses. Project responses are scoped to the authenticated client_id; out-of-scope projects return 404 Not Found to avoid tenant enumeration. Missing or invalid authentication returns 401 Unauthorized.
#Response Shapes
The projects router has these current response families:
- Project list/detail responses use project detail, draft, published version, pagination, and partner error envelopes.
- Partner lifecycle/profile/assignment responses use the lifecycle snapshot shape.
- Workspace subresources return safe domain snapshots or validation findings for draft configuration sections.
- Controlled release routes return validation reports, publish outcomes, safe revision diffs, or runtime drift reports.
- Project-secret routes return metadata and reference previews only; plaintext secret values are write-only.
- Legacy billing-focused endpoints use the older project and billing response models and may return the general
HTTPExceptionerror shape.
#Project Detail
Used by partner/admin project lifecycle endpoints.
| Field | Type | Description |
|---|---|---|
project_id | string | Unique project identifier |
client_id | string | Client identifier |
display_name | string | Project display name |
timezone | string | Project timezone (IANA format) |
lifecycle_state | string | active when is_active=true, otherwise archived |
has_draft | boolean | Whether a current draft exists |
latest_published_version_number | integer or null | Latest published runtime version number |
created_at | string (ISO 8601) | Creation timestamp |
updated_at | string (ISO 8601) | Last update timestamp |
created_by | string | Actor identifier recorded at project creation |
initial_draft_etag | string or null | Nullable model field; current lifecycle create responses use the lifecycle snapshot shape instead |
testing_override_summary | object or null | Testing override production summary when the router attaches it |
#Lifecycle Snapshot
Used by POST /v1/projects, lifecycle/profile routes, archive/restore, and project assignment routes.
| Field | Type | Description |
|---|---|---|
project | object | Lifecycle project metadata |
project.project_id | string | Unique project identifier |
project.client_id | string | Client identifier |
project.display_name | string | Project display name |
project.timezone | string | Project timezone (IANA format) |
project.lifecycle_state | string | setup, active, or archived |
project.revision_token | string | Lifecycle concurrency token |
project.latest_published_version | integer or null | Latest published runtime version |
project.draft_status | string | draft when a draft exists, otherwise none |
project.publish_status | string | published or not_published |
profile | object | Safe project profile fields |
permissions | object | Current caller permissions for lifecycle operations |
assignments | array | Project visibility assignments |
available_members | array or null | Eligible assignment targets when included for partner admins |
updated_at | string (ISO 8601) | Snapshot update timestamp |
#Legacy Project
Used by the legacy project list/detail/update response path.
| Field | Type | Description |
|---|---|---|
project_id | string | Unique project identifier |
client_id | string | Client identifier |
display_name | string or null | Project display name |
rate_per_minute | number | Call rate per minute |
currency | string | Billing currency (ISO 4217) |
billing_model | string | Billing model, such as per_minute, per_call, or tiered |
minimum_billable_seconds | integer | Minimum billable duration per call |
is_active | boolean | Whether the project is active |
timezone | string | Project timezone (IANA format) |
created_at_utc | string (ISO 8601) | Creation timestamp |
updated_at_utc | string (ISO 8601) | Last update timestamp |
#GET /v1/projects
Returns projects for the authenticated client.
Authentication: Required (X-API-Key or Authorization: Bearer <jwt>)
For partner_admin, partner_user, aidial_admin, and aidial_operator scopes, the response is paginated and uses the project detail shape. Partner read scopes are assignment-aware. Internal admin/operator scopes list projects for the resolved AuthContext.client_id. For other authenticated legacy scopes, the response is { "projects": [...] } using the legacy project shape.
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
include_inactive | query | boolean | No | false | Include inactive projects. For partner/admin list responses this also includes archived projects |
include_archived | query | boolean | No | false | Include archived projects in partner/admin list responses |
data_env | query | string | No | Auth context data environment | Partner assignment data environment. Supported values: prod, staging, dev |
sort_by | query | string | No | created_at_utc | Partner/admin sort field: display_name, created_at_utc, updated_at_utc, or project_id |
sort_order | query | string | No | desc | Partner/admin sort direction: asc or desc |
page | query | integer | No | 1 | Partner/admin page number, minimum 1 |
page_size | query | integer | No | 20 | Partner/admin page size, 1 to 100 |
#Partner/Admin Response
| Field | Type | Description |
|---|---|---|
items | array | Project detail objects |
pagination | object | Pagination metadata |
pagination.page | integer | Current page |
pagination.page_size | integer | Results per page |
pagination.total_records | integer | Total matching records |
pagination.total_pages | integer | Total pages |
#Example
Request:
curl -X GET "https://api.aidial.ai/v1/projects?page=1&page_size=20" \
-H "X-API-Key: sk_live_YOUR_API_KEY_HERE"Response (200 OK):
{
"items": [
{
"project_id": "client_example_001-Reception_AI-a1b2c3d4",
"client_id": "client_example_001",
"display_name": "Reception AI",
"timezone": "Australia/Brisbane",
"lifecycle_state": "active",
"has_draft": true,
"latest_published_version_number": 2,
"created_at": "2026-01-15T00:00:00Z",
"updated_at": "2026-04-01T00:00:00Z",
"created_by": "apikey:42"
}
],
"pagination": {
"page": 1,
"page_size": 20,
"total_records": 1,
"total_pages": 1
}
}#POST /v1/projects
Creates a new project lifecycle row for the authenticated client and creates an initial draft containing display_name and timezone.
Authentication: partner_admin scope required
#Headers
| Name | Required | Description |
|---|---|---|
Idempotency-Key | Conditional | Required unless idempotency_key is supplied in the request body; 1 to 128 characters |
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | Yes | Project display name, 3 to 120 characters |
timezone | string | Yes | IANA timezone identifier |
managed_client_id | string | Yes | Must match the authenticated client_id |
profile | object | No | Optional lifecycle profile fields |
idempotency_key | string | Conditional | Alternative idempotency-key location when the header is not supplied |
#Response
Returns a lifecycle snapshot. The generated project_id is based on managed_client_id, a sanitized display name, and a short random suffix.
#Example
Request:
curl -X POST "https://api.aidial.ai/v1/projects" \
-H "Authorization: Bearer YOUR_PORTAL_JWT" \
-H "Idempotency-Key: create-reception-ai-001" \
-H "Content-Type: application/json" \
-d '{"display_name": "Reception AI", "timezone": "Australia/Brisbane", "managed_client_id": "client_example_001"}'Response (201 Created):
{
"project": {
"project_id": "client_example_001-Reception_AI-a1b2c3d4",
"client_id": "client_example_001",
"display_name": "Reception AI",
"timezone": "Australia/Brisbane",
"lifecycle_state": "setup",
"revision_token": "1",
"latest_published_version": null,
"draft_status": "draft",
"publish_status": "not_published"
},
"profile": {},
"permissions": {
"can_create": true,
"can_edit": true,
"can_archive": true,
"can_restore": false,
"can_manage_assignments": true,
"read_only_reason": null
},
"assignments": [],
"updated_at": "2026-04-17T02:00:00Z"
}#GET /v1/projects/{project_id}
Returns details for a single project.
Authentication: partner_admin, partner_user, aidial_admin, or aidial_operator scope for the project detail response. Client portal scopes receive 404 Not Found from this route.
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Response
Returns a project detail object for partner/admin read scopes. Out-of-scope projects return 404 Not Found.
#Example
Request:
curl -X GET "https://api.aidial.ai/v1/projects/client_example_001-Reception_AI-a1b2c3d4" \
-H "X-API-Key: sk_live_YOUR_API_KEY_HERE"#GET /v1/projects/{project_id}/lifecycle
Returns the safe lifecycle/profile/assignment snapshot for a project.
Authentication: partner_admin, partner_user, aidial_admin, or aidial_operator scope required
#Response
Returns the lifecycle snapshot shape. Partner-member access is assignment-aware; out-of-scope projects return 404 Not Found.
#PATCH /v1/projects/{project_id}/lifecycle
Updates safe lifecycle/profile metadata using lifecycle revision-token concurrency.
Authentication: partner_admin scope required
#Request Body
At least one mutable field must be provided.
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | No | Project display name, 3 to 120 characters |
timezone | string | No | IANA timezone identifier |
lifecycle_notes | string | No | Lifecycle note, up to 500 characters |
profile | object | No | Lifecycle profile fields |
revision_token | string | Yes | Current lifecycle revision token |
#Response
Returns the updated lifecycle snapshot. A stale lifecycle revision returns 409 Conflict; archived projects are read-only until restored.
#PATCH /v1/projects/{project_id}
Closed legacy partner metadata route. Current code always returns non-enumerating 404 Not Found; use PATCH /v1/projects/{project_id}/lifecycle for lifecycle/profile metadata updates.
Authentication: Required, but no scope can use this route successfully
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Response
Always returns 404 Not Found through the partner error envelope.
#POST /v1/projects/{project_id}/archive
Archives a project by setting lifecycle state to archived and aidial_projects.is_active=false. The operation is idempotent.
Authentication: partner_admin scope required
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Headers
| Name | Required | Description |
|---|---|---|
Idempotency-Key | Conditional | Required unless idempotency_key is supplied in the request body |
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
revision_token | string | Yes | Current lifecycle revision token |
lifecycle_note | string | No | Optional transition note |
idempotency_key | string | Conditional | Alternative idempotency-key location when the header is not supplied |
#Response
Returns the updated lifecycle snapshot.
#POST /v1/projects/{project_id}/restore
Restores an archived project by setting lifecycle state back to setup and aidial_projects.is_active=true. The operation is idempotent.
Authentication: partner_admin scope required
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Headers
| Name | Required | Description |
|---|---|---|
Idempotency-Key | Conditional | Required unless idempotency_key is supplied in the request body |
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
revision_token | string | Yes | Current lifecycle revision token |
lifecycle_note | string | No | Optional transition note |
idempotency_key | string | Conditional | Alternative idempotency-key location when the header is not supplied |
#Response
Returns the updated lifecycle snapshot.
#POST /v1/projects/{project_id}/assignments
Grants safe project visibility to an eligible partner member.
Authentication: partner_admin scope with partner membership context required
#Headers
| Name | Required | Description |
|---|---|---|
Idempotency-Key | Conditional | Required unless idempotency_key is supplied in the request body |
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
member_id | string | Yes | Eligible partner member identifier |
role_visibility | string | Yes | read or manage |
assignment_note | string | No | Optional assignment note |
revision_token | string | Yes | Current project lifecycle revision token |
idempotency_key | string | Conditional | Alternative idempotency-key location when the header is not supplied |
#Response
Returns the updated lifecycle snapshot.
#DELETE /v1/projects/{project_id}/assignments/{assignment_id}
Removes a project visibility assignment.
Authentication: partner_admin scope with partner membership context required
#Headers
| Name | Required | Description |
|---|---|---|
Idempotency-Key | Conditional | Required unless idempotency_key is supplied in the request body |
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
assignment_revision_token | string | Yes | Current assignment revision token |
idempotency_key | string | Conditional | Alternative idempotency-key location when the header is not supplied |
#Response
Returns the updated lifecycle snapshot.
#Project Workspace Subresources
Several project configuration areas expose safe draft/published snapshots and save validation results under /v1/projects/{project_id}. These routes update the project draft in the configuration revision store and use the same project scoping and anti-enumeration behaviour as the core project routes.
| Route | Authentication | Purpose |
|---|---|---|
GET /dashboard-metadata?refresh=false | Client, partner, or internal read scopes | Return a safe dashboard metadata snapshot |
POST /dashboard-metadata/publish | Bearer client_admin | Publish safe API-managed dashboard analytics metadata; requires Idempotency-Key |
GET /governance | Bearer partner_admin or partner_user | Return governance snapshot |
PUT /governance/draft | Bearer partner_admin | Save governance draft; requires Idempotency-Key |
POST /governance/validate | Bearer partner_admin | Validate governance draft; requires Idempotency-Key |
GET /testing-overrides | Bearer partner_admin or partner_user | Return testing override contract snapshot |
PATCH /testing-overrides | Bearer partner_admin | Save or disable testing overrides; Idempotency-Key must be at least 8 characters |
GET /transfer-routing | Partner/internal read scopes | Return safe transfer-routing snapshot |
PUT /transfer-routing/draft | partner_admin | Save transfer-routing draft subset with optional If-Match |
POST /transfer-routing/validate | partner_admin | Validate current transfer-routing config; request body must be empty or {} |
POST /transfer-routing/test | partner_admin | Run a safe transfer-routing test override |
GET /provider-configuration | partner_admin or partner_user | Return provider configuration snapshot |
PUT /provider-configuration | partner_admin | Save provider configuration draft subset with optional If-Match |
POST /provider-configuration/validate | partner_admin or partner_user | Validate provider configuration; only partner_admin may supply an override body |
GET /llm-policy | partner_admin or partner_user | Return LLM policy snapshot |
PUT /llm-policy | partner_admin | Save LLM policy draft subset with optional If-Match |
POST /llm-policy/validate | partner_admin | Validate LLM policy |
GET /plugin-configuration | partner_admin or partner_user | Return plugin configuration snapshot |
PUT /plugin-configuration | partner_admin | Save plugin configuration draft subset with If-Match or body revision_token when a draft exists |
POST /plugin-configuration/validate | partner_admin | Validate plugin configuration with the same revision guard |
GET /identity-verification | partner_admin or partner_user | Return identity verification snapshot |
PUT /identity-verification | partner_admin | Save runtime-shaped identity verification draft subset with optional If-Match |
POST /identity-verification/validate | partner_admin | Validate runtime-shaped identity verification |
GET /booking | partner_admin or partner_user | Return booking posture and readiness snapshot |
PUT /booking | partner_admin | Save booking draft subset with optional If-Match |
POST /booking/validate | partner_admin | Validate booking posture and readiness |
GET /email-delivery | partner_admin or partner_user | Return email delivery snapshot |
PUT /email-delivery | partner_admin | Save email delivery draft subset with optional If-Match |
POST /email-delivery/validate | partner_admin | Validate email delivery |
GET /email-sms-policy | partner_admin or partner_user | Return combined email & SMS policy snapshot; draft state and edit controls are included only for partner_admin |
PUT /email-sms-policy | partner_admin | Save email & SMS policy draft subset with optional If-Match |
POST /email-sms-policy/validate | partner_admin | Validate email & SMS policy |
GET /outbound-compliance | Partner/internal read scopes | Return outbound compliance snapshot |
PUT /outbound-compliance | Bearer partner_admin, aidial_admin, or aidial_operator | Save outbound compliance draft subset; If-Match required |
POST /outbound-compliance/validate-recipient | Partner/internal read scopes | Preview recipient-local calling-window decisions |
GET /sms-policy | partner_admin or partner_user | Return SMS policy snapshot |
PUT /sms-policy | partner_admin | Save SMS policy draft subset; If-Match must match body revision_token |
POST /sms-policy/validate | partner_admin | Validate SMS policy; request body required |
#POST /v1/projects/{project_id}/test-call/request
Records an ops-mediated request for a guided test call on a project. This endpoint only records a request to operations: it does not place a call and returns no transcripts, recordings, audio, caller data, or provider credentials.
Authentication: partner_admin scope required (partner_user and any other scope receive 404 Not Found)
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Request Body
The request body carries only a free-text note. The project, client, and requester are resolved server-side from the authenticated, assignment-gated scope; no other field is read or echoed.
| Field | Type | Required | Description |
|---|---|---|---|
note | string | Yes | Description of what is needed for the guided test call, 1 to 2000 characters |
#Response
| Field | Type | Description |
|---|---|---|
status | string | requested |
project_id | string | Project identifier |
request_id | string | Generated request identifier |
#POST /v1/projects/{project_id}/dashboard-metadata/publish
Publishes API-managed dashboard analytics metadata for a scoped client project without exposing the generic partner runtime draft/publish surface.
Authentication: bearer client_admin scope required
#Headers
| Header | Required | Description |
|---|---|---|
Idempotency-Key | Yes | Prevents duplicate dashboard metadata publishes for the same client actor and payload |
#Request Body
Only the closed analytics subset below is accepted. Unsupported fields are rejected.
| Field | Type | Required | Description |
|---|---|---|---|
analytics.outcome_enum[] | array | No | Safe dashboard outcome keys and display labels |
analytics.caller_mix_supported | boolean | No | Whether caller-mix metrics may be shown when privacy thresholds are satisfied |
analytics.caller_mix.stable_caller_key_available | boolean | No | Whether a stable caller identity key exists for privacy-safe caller-mix aggregation |
At least one supported analytics field is required. The API rejects the request when the latest published runtime version is not already deployed, preserves the latest deployed runtime document, forces display_name and timezone from the project row, validates the merged config, inserts a normal published configuration-revision row, and records it as deployed because this metadata is API-managed and requires no runtime rollout.
#Response
Returns client_id, project_id, revision_id, version_number, deploy_status, source_revision, and a safe dashboard metadata snapshot derived from the committed config. The saved current snapshot refresh is attempted after commit as a best-effort side effect; refresh failure is logged and does not change the response.
#GET /v1/projects/{project_id}/draft
Returns the current draft configuration for a project.
Authentication: partner_admin, aidial_admin, or aidial_operator scope required
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Response Headers
| Header | Description |
|---|---|
ETag | Current draft ETag, quoted |
#Response
| Field | Type | Description |
|---|---|---|
id | integer | Draft revision identifier |
project_id | string | Project identifier |
revision_type | string | Always draft |
config_data | object | Draft runtime configuration document |
etag | string | Current draft ETag |
author_user_id | string | Actor identifier for the draft author |
author_role | string | Actor role recorded with the draft |
created_at | string (ISO 8601) | Draft timestamp |
If the project exists but has no draft, the route returns 404 Not Found with a contextual partner error message.
#PUT /v1/projects/{project_id}/draft
Saves or updates the draft configuration for a project.
Authentication: partner_admin scope required
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Headers
| Name | Required | Description |
|---|---|---|
If-Match | Conditional | Required when updating an existing draft. Use the current ETag returned by GET /v1/projects/{project_id}/draft |
#Request Body
The request body must be a JSON object and must not exceed 1 MB.
| Field | Type | Required | Description |
|---|---|---|---|
config_data | object | Yes | Draft runtime configuration document |
Draft saves validate mirrored project metadata fields when present. config_data.display_name, if present, must be a non-empty string no longer than 255 characters. config_data.timezone, if present, must be a valid IANA timezone.
#ETag Behaviour
| State | Behaviour |
|---|---|
Draft exists and If-Match is omitted | 428 Precondition Required |
Draft exists and If-Match: * is sent | 412 Precondition Failed |
| Draft exists and ETag does not match | 409 Conflict |
No draft exists and If-Match is omitted or * | Creates a new draft |
| No draft exists and a concrete stale ETag is sent | 409 Conflict |
#Response
Returns the saved draft response and a new ETag response header.
#POST /v1/projects/{project_id}/publish
Publishes the current draft through the controlled release flow. The route requires a current successful validation report, creates a published revision with a deploy_pending publish outcome, deletes the draft, and updates the project's latest published version number.
Authentication: partner_admin scope required
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
#Headers
| Name | Required | Description |
|---|---|---|
Idempotency-Key | Yes | Required idempotency key, 1 to 128 characters |
If-Match | Yes | Current draft ETag |
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
validation_report_id | string | Yes | Current successful validation report for the draft and runtime target |
target_runtime | string | No | Runtime target; current code supports default |
#Publish Validation
The draft config_data must be a non-empty JSON object with:
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | Yes | Non-empty display name |
timezone | string | Yes | Valid IANA timezone |
If config_data.agents is present, publish also validates the agent contract before inserting the published revision. Canonical runtime shape is an object keyed by runtime agent name, including agents.main. Portal editor list shape is accepted only when it compiles to the approved runtime contract. During compilation, an explicit portal agent_id: main is treated as the runtime entry agent even when it is not the first list item; otherwise the first portal agent becomes runtime main. mixin_keys are folded into runtime tools, and router route_targets become runtime routes with { to, when }. Portal voice_override_key values must resolve to a full runtime tts object through voice_overrides, voices, or an agent-level tts object. Route and handoff targets are resolved against the original portal agent IDs before this main renaming step. critical and high agent findings block publish and leave the draft intact. medium and low findings do not block publish by themselves and are omitted from the publish error response.
Agent publish validation covers:
| Code | Blocking | Description |
|---|---|---|
missing_agent_id | Yes | Agent row does not include a stable agent ID |
duplicate_agent_id | Yes | Agent ID is repeated in the draft |
missing_label | Yes | Agent label is empty |
unsupported_role | Yes | Agent role is not single_agent, generic_router, or generic_task |
missing_handoff_target | Yes | Handoff target does not exist in the same draft |
missing_route_target | Yes | Route target does not exist in the same draft |
self_route | Yes | Agent routes or hands off to itself |
unresolved_tool | Yes | Referenced tool key is not available in the project catalog |
unresolved_mixin | Yes | Referenced mixin key is not available in the project catalog |
invalid_voice_override | Yes | Voice override key is not available in the project catalog |
route_cycle_without_task | Yes | Route graph cycles without a terminal generic_task agent |
missing_runtime_agents | Yes | Runtime agent configuration is missing or empty |
missing_runtime_entry_agent | Yes | Runtime agent configuration does not include an entry agent |
missing_runtime_agent_type | Yes | Runtime agent does not declare agent_type |
missing_runtime_routes | Yes | Runtime router agent does not compile to any route |
missing_runtime_handoff_target | Yes | Runtime handoff target does not target an existing agent |
missing_runtime_route_target | Yes | Runtime route does not target an existing agent |
missing_runtime_route_when | Yes | Runtime route is missing the required when condition |
unresolved_runtime_tts | Yes | Portal voice override does not resolve to a full runtime tts object |
invalid_runtime_handoff_targets | Yes | Runtime handoff targets are not a list |
runtime_task_has_routes | Yes | Runtime task agent defines routes instead of being terminal |
runtime_route_cycle_without_task | Yes | Runtime route graph cycles without a terminal task agent |
empty_welcome_greeting | No | Welcome greeting is empty |
Publish also runs blocking checks for raw secret references, transfer routing, provider configuration, LLM policy, plugin configuration, email delivery, SMS policy, identity verification, and outbound compliance where those sections are present in the draft. Identity verification validation expects runtime keys such as caller_lookup.plugin and sms_code.input_modes; editor aliases such as plugin_instance_id and channels are blocking findings. Blocking validation errors are returned in the standard partner validation envelope under error.details.field_errors[]. Findings are partner-safe and must not include raw prompt instructions, bearer tokens, raw secret values, ciphertext, or other secret material.
The publish background task no longer marks a version as runtime deployed by itself. A published revision remains pending until the controlled deployment path records deployment evidence or marks the deployment failed.
#Response
| Field | Type | Description |
|---|---|---|
publish_outcome_id | string | Controlled release outcome identifier |
parent_publish_outcome_id | string or null | Parent outcome for deploy completion evidence |
status | string | deploy_pending on successful publish before deployment evidence is recorded |
operation | string | publish |
project_id | string | Project identifier |
target_revision_id | integer | Published revision identifier |
target_version_number | integer or null | Published version number |
restored_from_revision_id | integer or null | Source revision identifier when the outcome was created by rollback, otherwise null |
restored_from_version_number | integer or null | Source published version number when the outcome was created by rollback, otherwise null |
latest_completed_published_version_number | integer or null | Latest completed runtime version |
runtime_target | string | Runtime target, currently default |
validation_report_id | string or null | Validation report used for release |
runtime_artifact_ref | string or null | Safe runtime artifact reference |
failure_code | string or null | Failure code when applicable |
failure_message | string or null | Failure message when applicable |
summary | string | Human-readable release outcome summary |
created_at_utc | string (ISO 8601) | Outcome creation timestamp |
testing_override_summary | object or null | Testing override production summary when present |
#POST /v1/projects/{project_id}/validate
Validates a draft or published version against active release-governance rules.
Authentication: partner_admin scope required
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
target.type | string | Yes | draft or published_version |
target.revision_token | string | Conditional | Required when target.type=draft |
target.version_number | integer | Conditional | Required when target.type=published_version |
target_runtime | string | No | Runtime target; current code supports default |
#Response
Returns a validation report with validation_report_id, status (passed, warning, or failed), is_publish_current, fingerprint, findings, and checked_at_utc.
#POST /v1/projects/{project_id}/rollback
Creates a controlled rollback release by validating and copying a completed published version into a new pending published revision.
Authentication: partner_admin scope required
#Headers
| Name | Required | Description |
|---|---|---|
Idempotency-Key | Yes | Required idempotency key, 1 to 128 characters |
#Request Body
| Field | Type | Required | Description |
|---|---|---|---|
target_version_number | integer | Yes | Completed published version to roll back to |
validation_report_id | string | Yes | Current validation report for the rollback target |
target_runtime | string | No | Runtime target; current code supports default |
#Response
Returns the same controlled release outcome shape used by POST /v1/projects/{project_id}/publish, with operation set to rollback.
#POST /v1/projects/{project_id}/runtime-provenance
Records internal deploy completion or failure evidence for a controlled release outcome.
Authentication: Bearer aidial_admin only
This is an internal deploy-evidence route, not a partner integration endpoint. It requires an Idempotency-Key header and a RuntimeProvenanceRequest body. deploy_completed evidence must include supported observed revision/version, schema version, contract version, and artifact hash fields; deploy_failed evidence must include failure_code and failure_message.
#GET /v1/projects/{project_id}/versions
Returns paginated published version history for a project, sorted by version number descending.
Authentication: partner_admin, partner_user, aidial_admin, or aidial_operator scope required
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
page | query | integer | No | 1 | Page number, minimum 1 |
page_size | query | integer | No | 20 | Page size, 1 to 100 |
#Response
| Field | Type | Description |
|---|---|---|
items | array | Version list items |
items[].version_number | integer | Published version number |
items[].published_at | string (ISO 8601) | Publish timestamp |
items[].published_by | string | Display-safe actor label |
items[].validation_status | string | Validation status |
items[].deploy_status | string | Deployment status |
items[].latest_publish_outcome_status | string or null | Latest controlled release outcome status |
items[].rollback_eligible | boolean | Whether rollback is currently allowed |
items[].rollback_block_reason | string or null | Why rollback is blocked |
items[].testing_override_summary | object or null | Testing override production summary when present |
pagination | object | Pagination metadata |
#GET /v1/projects/{project_id}/versions/compare
Returns a safe redacted diff between a draft and/or published project revision.
Authentication: partner_admin, partner_user, aidial_admin, or aidial_operator scope required
#Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
from_type | string | Yes | draft or published_version |
from_version | integer | Conditional | Required when from_type=published_version |
to_type | string | Yes | draft or published_version |
to_version | integer | Conditional | Required when to_type=published_version |
The diff redacts sensitive values before returning before and after fields.
#GET /v1/projects/{project_id}/runtime-drift
Classifies runtime drift for the active project runtime target.
Authentication: partner_admin, partner_user, aidial_admin, or aidial_operator scope required
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
fresh | query | boolean | No | false | Request a fresh drift check; only partner_admin persists fresh checks |
#Response
Returns status, expected/observed/pending version numbers where known, summary, recommended_action, checked_at_utc, and optional testing_override_summary.
#GET /v1/projects/{project_id}/versions/{version_number}
Returns full detail for a published project configuration version.
Authentication: partner_admin, partner_user, aidial_admin, or aidial_operator scope required
#Parameters
| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
project_id | path | string | Yes | - | Unique project identifier |
version_number | path | integer | Yes | - | Published version number |
#Response
Returns the published version response shape with id, project_id, version_number, config_data, validation_status, published_at, display-safe published_by, deploy_status, optional deploy error/timestamp, release outcome status, rollback eligibility, release summary, and optional testing override summary.
#Error Semantics
| Condition | Status |
|---|---|
| Missing or invalid authentication | 401 Unauthorized |
| Valid authentication but project is outside the resolved client scope | 404 Not Found |
| Valid authentication but role is not allowed for partner lifecycle endpoints | 404 Not Found |
| Invalid partner lifecycle request body or query field | 422 Unprocessable Entity |
Missing Idempotency-Key where required | 400 Bad Request |
Duplicate lifecycle Idempotency-Key for the same operation and payload | Replays the stored response when available; otherwise 409 Conflict while the original request is still processing |
Duplicate controlled-release Idempotency-Key for the same operation and payload | 409 Conflict |
Reused Idempotency-Key with a different payload | 409 Conflict or 422 Unprocessable Entity, depending on the endpoint family |
| Stale draft ETag | 409 Conflict |
Missing required If-Match for existing draft update or publish | 428 Precondition Required |
If-Match: * used against an existing draft | 412 Precondition Failed |
| Missing current validation report before publish or rollback | 422 Unprocessable Entity |
| Controlled release already pending for the project | 409 Conflict |
| Stale lifecycle or secret revision token | 409 Conflict |
| Archived project draft save or publish | 422 Unprocessable Entity |
| Secret write failed during project update | 503 Service Unavailable |
#Data Scoping
All project metadata, lifecycle, draft, version, and legacy billing configuration responses are scoped to the authenticated client identity. You only see projects belonging to your organisation or assigned tenant scope.
Project paths use the API host's local API metadata store. Calls analytics endpoints use strict (client_id, data_env) routing through the tenant routing map; use the Calls Analytics and Billing pages for routed call and customer billing data. A missing tenant route is server misconfiguration and returns 500 Internal Server Error; a routed host, tunnel, or database outage returns 503 Service Unavailable.
Project responses do not expose raw encrypted fields, ciphertext, wrapped keys, plaintext secret values, or *_encrypted database fields. Version comparison responses redact secret-like fields before returning diffs.
#Related Pages
- Authentication - API key and bearer authentication
- Billing - customer billing overview and invoices
- Calls Analytics - routed call records and analytics
- Error Responses - error format details