1126 lines
37 KiB
YAML
1126 lines
37 KiB
YAML
---
|
|
# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
|
|
openapi: 3.1.0
|
|
info:
|
|
title: agent-call Asterisk/SIP Management API
|
|
version: 1.0.0
|
|
description: >-
|
|
Independent Asterisk/SIP management backend. Admin write operations are
|
|
separate from the SaaS read-only Trunk directory and from ordinary
|
|
scheduling APIs. In mock mode publication records are intents only. In
|
|
real mode a publication is successful only after every selected Cell Agent
|
|
returns a matching mTLS acknowledgement.
|
|
servers:
|
|
- url: https://sip-admin.internal
|
|
description: Restricted operator management network
|
|
- url: https://sip-read.internal
|
|
description: SaaS read-only service network
|
|
tags:
|
|
- name: health
|
|
- name: admin-providers
|
|
- name: admin-trunks
|
|
- name: admin-cells
|
|
- name: admin-status
|
|
- name: admin-statistics
|
|
- name: admin-audit
|
|
- name: saas-readonly
|
|
paths:
|
|
/healthz/live:
|
|
get:
|
|
tags: [health]
|
|
operationId: live
|
|
responses:
|
|
'200':
|
|
description: Service is alive
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Health'
|
|
/admin/v1/providers:
|
|
get:
|
|
tags: [admin-providers]
|
|
operationId: listProviders
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Provider directory
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ProviderList'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/admin/v1/providers/{provider_id}:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/ProviderId'}
|
|
get:
|
|
tags: [admin-providers]
|
|
operationId: getProvider
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Provider
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ProviderResponse'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
put:
|
|
tags: [admin-providers]
|
|
operationId: upsertProvider
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/IfMatch'}
|
|
- {$ref: '#/components/parameters/RequestId'}
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ProviderInput'}
|
|
responses:
|
|
'200':
|
|
description: Updated provider
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ProviderResponse'}
|
|
'201':
|
|
description: Created provider
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ProviderResponse'}
|
|
'400': {$ref: '#/components/responses/BadRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'403': {$ref: '#/components/responses/Forbidden'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/trunks:
|
|
get:
|
|
tags: [admin-trunks]
|
|
operationId: listAdminTrunks
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/ProviderFilter'}
|
|
- {$ref: '#/components/parameters/CellIdFilter'}
|
|
- {$ref: '#/components/parameters/TrunkStatusFilter'}
|
|
responses:
|
|
'200':
|
|
description: All Trunks, including unpublished revisions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AdminTrunkList'
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'403': {$ref: '#/components/responses/Forbidden'}
|
|
/admin/v1/trunks/{trunk_id}:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
get:
|
|
tags: [admin-trunks]
|
|
operationId: getAdminTrunk
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Trunk configuration and revisions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/AdminTrunk'
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
put:
|
|
tags: [admin-trunks]
|
|
operationId: createTrunkRevision
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/IfMatch'}
|
|
- {$ref: '#/components/parameters/RequestId'}
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrunkConfig'
|
|
responses:
|
|
'200':
|
|
description: New draft revision for an existing Trunk
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
|
'201':
|
|
description: New Trunk with its first draft revision
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
|
'400': {$ref: '#/components/responses/BadRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/trunks/{trunk_id}/validate:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
post:
|
|
tags: [admin-trunks]
|
|
operationId: validateTrunk
|
|
security: [{SipAdminBearer: []}]
|
|
requestBody:
|
|
required: false
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: false
|
|
properties:
|
|
revision: {type: integer, minimum: 1}
|
|
responses:
|
|
'200':
|
|
description: Validation issues, compatible Cells, and impact preview
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/admin/v1/trunks/{trunk_id}/verifications:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
post:
|
|
tags: [admin-trunks]
|
|
operationId: addTrunkVerification
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/IfMatch'}
|
|
- {$ref: '#/components/parameters/RequestId'}
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/VerificationRequest'
|
|
responses:
|
|
'200':
|
|
description: Versioned verification record
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/trunks/{trunk_id}/publish:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
post:
|
|
tags: [admin-trunks]
|
|
operationId: publishTrunk
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/IfMatch'}
|
|
- {$ref: '#/components/parameters/RequestId'}
|
|
responses:
|
|
'200':
|
|
description: >-
|
|
Published revision after all selected Cell acknowledgements
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/trunks/{trunk_id}/disable:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
post:
|
|
tags: [admin-trunks]
|
|
operationId: disableTrunk
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/IfMatch'}
|
|
- {$ref: '#/components/parameters/RequestId'}
|
|
responses:
|
|
'200':
|
|
description: Trunk disabled after selected Cell acknowledgements
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/trunks/{trunk_id}/rollback:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
post:
|
|
tags: [admin-trunks]
|
|
operationId: rollbackTrunk
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/IfMatch'}
|
|
- {$ref: '#/components/parameters/RequestId'}
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [target_revision]
|
|
properties:
|
|
target_revision: {type: integer, minimum: 1}
|
|
responses:
|
|
'200':
|
|
description: >-
|
|
New revision copied from the target after Cell acknowledgements
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/AdminTrunk'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/trunks/{trunk_id}/publications:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
get:
|
|
tags: [admin-trunks]
|
|
operationId: listTrunkPublications
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Per-Cell publication intents
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [mode, publications]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
publications:
|
|
type: array
|
|
items: {$ref: '#/components/schemas/Publication'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/admin/v1/trunks/{trunk_id}/audit:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
get:
|
|
tags: [admin-trunks]
|
|
operationId: listTrunkAudit
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Immutable management audit entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [mode, audit]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
audit:
|
|
type: array
|
|
items: {$ref: '#/components/schemas/AuditEntry'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/admin/v1/cells:
|
|
get:
|
|
tags: [admin-cells]
|
|
operationId: listCells
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Registered multi-machine voice Cells
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [mode, cells]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
cells:
|
|
type: array
|
|
items: {$ref: '#/components/schemas/Cell'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/admin/v1/cells/{cell_id}:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/CellId'}
|
|
get:
|
|
tags: [admin-cells]
|
|
operationId: getCell
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Registered Cell
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Cell'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
put:
|
|
tags: [admin-cells]
|
|
operationId: registerCell
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/IfMatch'}
|
|
- {$ref: '#/components/parameters/RequestId'}
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/CellConfig'}
|
|
responses:
|
|
'200':
|
|
description: Updated Cell revision
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Cell'}
|
|
'201':
|
|
description: Registered Cell
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/Cell'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/cells/{cell_id}/observations:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/CellId'}
|
|
post:
|
|
tags: [admin-cells]
|
|
operationId: ingestCellObservation
|
|
security: [{SipAdminBearer: []}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ObservationInput'}
|
|
responses:
|
|
'201':
|
|
description: >-
|
|
Observation accepted for the current boot and monotonic sequence
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/admin/v1/egress-pools:
|
|
get:
|
|
tags: [admin-cells]
|
|
operationId: listEgressPools
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Fixed egress pool directory
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/admin/v1/sip-status:
|
|
get:
|
|
tags: [admin-status]
|
|
operationId: getSipStatus
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/CellIdsFilter'}
|
|
- {$ref: '#/components/parameters/CellIdFilter'}
|
|
- {$ref: '#/components/parameters/ProviderFilter'}
|
|
responses:
|
|
'200':
|
|
description: >-
|
|
Cell/trunk status matrix with freshness and missing sources
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/StatusResponse'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/admin/v1/cells/{cell_id}/sip-status:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/CellId'}
|
|
get:
|
|
tags: [admin-status]
|
|
operationId: getCellSipStatus
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkFilter'}
|
|
responses:
|
|
'200':
|
|
description: One Cell status
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/StatusItem'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/admin/v1/providers/{provider_id}/status:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/ProviderId'}
|
|
get:
|
|
tags: [admin-status]
|
|
operationId: getProviderStatus
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Provider status matrix
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/StatusResponse'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/admin/v1/statistics/outbound/summary:
|
|
get:
|
|
tags: [admin-statistics]
|
|
operationId: getOutboundSummary
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/From'}
|
|
- {$ref: '#/components/parameters/To'}
|
|
- {$ref: '#/components/parameters/StatsMode'}
|
|
- {$ref: '#/components/parameters/ProviderFilter'}
|
|
- {$ref: '#/components/parameters/TrunkFilter'}
|
|
- {$ref: '#/components/parameters/CellIdFilter'}
|
|
- {$ref: '#/components/parameters/EgressFilter'}
|
|
responses:
|
|
'200':
|
|
description: Cohort and interval metrics with completeness metadata
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/StatisticsSummary'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'422': {$ref: '#/components/responses/BadRequest'}
|
|
/admin/v1/statistics/outbound/timeseries:
|
|
get:
|
|
tags: [admin-statistics]
|
|
operationId: getOutboundTimeseries
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/From'}
|
|
- {$ref: '#/components/parameters/To'}
|
|
- {$ref: '#/components/parameters/StatsMode'}
|
|
- {$ref: '#/components/parameters/Granularity'}
|
|
- {$ref: '#/components/parameters/ProviderFilter'}
|
|
- {$ref: '#/components/parameters/TrunkFilter'}
|
|
- {$ref: '#/components/parameters/CellIdFilter'}
|
|
- {$ref: '#/components/parameters/EgressFilter'}
|
|
responses:
|
|
'200':
|
|
description: Bounded UTC time series
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/TimeseriesResponse'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'422': {$ref: '#/components/responses/BadRequest'}
|
|
/admin/v1/call-attempts:
|
|
get:
|
|
tags: [admin-statistics]
|
|
operationId: listCallAttempts
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/From'}
|
|
- {$ref: '#/components/parameters/To'}
|
|
- {$ref: '#/components/parameters/StatsMode'}
|
|
- {$ref: '#/components/parameters/ProviderFilter'}
|
|
- {$ref: '#/components/parameters/TrunkFilter'}
|
|
- {$ref: '#/components/parameters/CellIdFilter'}
|
|
- {$ref: '#/components/parameters/Limit'}
|
|
- {$ref: '#/components/parameters/Cursor'}
|
|
- {$ref: '#/components/parameters/EgressFilter'}
|
|
responses:
|
|
'200':
|
|
description: Redacted raw attempt facts
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/admin/v1/call-attempts/{attempt_id}:
|
|
parameters:
|
|
- name: attempt_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
get:
|
|
tags: [admin-statistics]
|
|
operationId: getCallAttempt
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: One redacted attempt fact
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/admin/v1/audit:
|
|
get:
|
|
tags: [admin-audit]
|
|
operationId: listAudit
|
|
security: [{SipAdminBearer: []}]
|
|
parameters:
|
|
- {$ref: '#/components/parameters/Limit'}
|
|
- {$ref: '#/components/parameters/ResourceFilter'}
|
|
- {$ref: '#/components/parameters/RequestFilter'}
|
|
- {$ref: '#/components/parameters/ActorFilter'}
|
|
responses:
|
|
'200':
|
|
description: Immutable audit entries
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/admin/v1/operations/{operation_id}:
|
|
parameters:
|
|
- name: operation_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
get:
|
|
tags: [admin-audit]
|
|
operationId: getOperation
|
|
security: [{SipAdminBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Durable operation state for retry/recovery
|
|
content:
|
|
application/json:
|
|
schema: {type: object}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/readonly/v1/sip/trunks:
|
|
get:
|
|
tags: [saas-readonly]
|
|
operationId: listAuthorizedTrunks
|
|
security: [{SaasTrunkReadBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Published Trunks authorized for this SaaS principal
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ReadonlyTrunkList'
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/readonly/v1/sip/trunks/{trunk_id}:
|
|
parameters:
|
|
- {$ref: '#/components/parameters/TrunkId'}
|
|
get:
|
|
tags: [saas-readonly]
|
|
operationId: getAuthorizedTrunk
|
|
security: [{SaasTrunkReadBearer: []}]
|
|
responses:
|
|
'200':
|
|
description: Published, sanitized Trunk metadata
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ReadonlyTrunk'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
components:
|
|
securitySchemes:
|
|
SipAdminBearer:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: opaque
|
|
description: >-
|
|
Dedicated operator/backend credential for SIP management writes. It is
|
|
not accepted by the SaaS read-only API or ordinary scheduling API.
|
|
SaasTrunkReadBearer:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: opaque
|
|
description: >-
|
|
Dedicated SaaS read-only credential. It cannot publish, modify, disable,
|
|
rollback, or access Cell management.
|
|
parameters:
|
|
ProviderId:
|
|
name: provider_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'}
|
|
TrunkId:
|
|
name: trunk_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'}
|
|
CellId:
|
|
name: cell_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'}
|
|
IfMatch:
|
|
name: If-Match
|
|
in: header
|
|
required: true
|
|
description: Exact latest revision required for CAS; quotes are accepted.
|
|
schema: {type: integer, minimum: 0}
|
|
CellIdsFilter:
|
|
name: cell_ids
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
CellIdFilter:
|
|
name: cell_id
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
ProviderFilter:
|
|
name: provider_id
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
TrunkFilter:
|
|
name: trunk_id
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
TrunkStatusFilter:
|
|
name: status
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
ResourceFilter:
|
|
name: resource_id
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
ActorFilter:
|
|
name: actor
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
From:
|
|
name: from
|
|
in: query
|
|
required: false
|
|
schema: {type: string, format: date-time}
|
|
To:
|
|
name: to
|
|
in: query
|
|
required: false
|
|
schema: {type: string, format: date-time}
|
|
StatsMode:
|
|
name: mode
|
|
in: query
|
|
required: false
|
|
schema: {type: string, enum: [mock, mixed, real]}
|
|
EgressFilter:
|
|
name: egress_pool_id
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
Granularity:
|
|
name: granularity
|
|
in: query
|
|
required: false
|
|
schema: {type: string, enum: [minute, hour, day]}
|
|
Limit:
|
|
name: limit
|
|
in: query
|
|
required: false
|
|
schema: {type: integer, minimum: 1, maximum: 200}
|
|
Cursor:
|
|
name: cursor
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
RequestFilter:
|
|
name: request_id
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
RequestId:
|
|
name: X-Request-ID
|
|
in: header
|
|
required: true
|
|
schema: {type: string, minLength: 1, maxLength: 128}
|
|
responses:
|
|
BadRequest:
|
|
description: Invalid configuration or request
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
|
Unauthorized:
|
|
description: Missing or wrong authentication domain
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
|
Forbidden:
|
|
description: Credential lacks the required scope
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
|
Conflict:
|
|
description: CAS conflict or no compatible Cell
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
|
NotFound:
|
|
description: Resource is not visible or does not exist
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorResponse'}
|
|
schemas:
|
|
Mode:
|
|
type: string
|
|
enum: [mock, real]
|
|
StatsMode:
|
|
type: string
|
|
enum: [mock, mixed, real]
|
|
Health:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [status, mode]
|
|
properties:
|
|
status: {type: string, const: ok}
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
CodecProfile:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [allowed, preferred]
|
|
properties:
|
|
allowed:
|
|
type: array
|
|
minItems: 1
|
|
uniqueItems: true
|
|
items: {type: string, enum: [PCMA, PCMU]}
|
|
preferred: {type: string, enum: [PCMA, PCMU]}
|
|
SipConfig:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [host, port, transport, auth_mode, register]
|
|
properties:
|
|
host: {type: string, minLength: 1, maxLength: 253}
|
|
port: {type: integer, minimum: 1, maximum: 65535}
|
|
transport: {type: string, enum: [udp, tcp, tls]}
|
|
auth_mode: {type: string, enum: [ip, digest]}
|
|
register: {type: boolean}
|
|
credential_ref:
|
|
type: string
|
|
writeOnly: true
|
|
description: >-
|
|
Secret-store reference only; plaintext credentials are forbidden.
|
|
VerificationRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [revision, check_name, result]
|
|
properties:
|
|
revision: {type: integer, minimum: 1}
|
|
check_name:
|
|
type: string
|
|
enum:
|
|
- transport
|
|
- registration_auth
|
|
- caller_id_rules
|
|
- codec
|
|
- capacity
|
|
- whitelist
|
|
result:
|
|
type: string
|
|
enum: [confirmed, failed, unknown, not_applicable]
|
|
evidence_ref: {type: string, maxLength: 512}
|
|
checked_by: {type: string, maxLength: 128}
|
|
TrunkConfig:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- provider_id
|
|
- display_name
|
|
- enabled
|
|
- sip
|
|
- codec_profile
|
|
- caller_ids
|
|
- dial_prefix
|
|
- egress_pool_id
|
|
- max_concurrency
|
|
- max_cps
|
|
properties:
|
|
provider_id:
|
|
type: string
|
|
pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
|
display_name: {type: string, minLength: 1, maxLength: 256}
|
|
enabled: {type: boolean}
|
|
sip: {$ref: '#/components/schemas/SipConfig'}
|
|
codec_profile: {$ref: '#/components/schemas/CodecProfile'}
|
|
caller_ids:
|
|
type: array
|
|
minItems: 1
|
|
uniqueItems: true
|
|
items: {type: string, minLength: 1, maxLength: 128}
|
|
dial_prefix: {type: string, maxLength: 32}
|
|
egress_pool_id:
|
|
type: string
|
|
pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
|
max_concurrency: {type: integer, minimum: 1}
|
|
max_cps: {type: integer, minimum: 1}
|
|
CellConfig:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [egress_pool_id, codec_capabilities, status, max_concurrency]
|
|
properties:
|
|
egress_pool_id:
|
|
type: string
|
|
pattern: '^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$'
|
|
codec_capabilities:
|
|
type: array
|
|
minItems: 1
|
|
uniqueItems: true
|
|
items: {type: string, enum: [PCMA, PCMU]}
|
|
status: {type: string, enum: [healthy, draining, disabled]}
|
|
max_concurrency: {type: integer, minimum: 1}
|
|
management_url:
|
|
type: string
|
|
format: uri
|
|
pattern: '^https://'
|
|
description: >-
|
|
mTLS Cell Agent endpoint. Required when mode=real; credentials and
|
|
query strings are not allowed.
|
|
RevisionInfo:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [revision, state, created_at, created_by]
|
|
properties:
|
|
revision: {type: integer, minimum: 1}
|
|
state: {type: string, enum: [draft, publishing, published, superseded]}
|
|
config_sha256: {type: string, pattern: '^[a-f0-9]{64}$'}
|
|
created_at: {type: string, format: date-time}
|
|
created_by: {type: string}
|
|
AdminTrunk:
|
|
type: object
|
|
required:
|
|
- mode
|
|
- trunk_id
|
|
- provider_id
|
|
- latest_revision
|
|
- active_revision
|
|
- active_status
|
|
- status
|
|
- compatible_cell_ids
|
|
- latest
|
|
- active
|
|
- versions
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
trunk_id: {type: string}
|
|
provider_id: {type: string}
|
|
latest_revision: {type: integer, minimum: 1}
|
|
active_revision: {type: integer, minimum: 0}
|
|
active_status: {type: string, enum: [draft, published, disabled]}
|
|
status: {type: string, enum: [draft, published, disabled]}
|
|
updated_at: {type: string, format: date-time}
|
|
compatible_cell_ids: {type: array, items: {type: string}}
|
|
latest: {$ref: '#/components/schemas/TrunkView'}
|
|
active: {$ref: '#/components/schemas/TrunkView'}
|
|
versions:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RevisionInfo'
|
|
TrunkView:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/TrunkConfig'}
|
|
- type: object
|
|
properties:
|
|
trunk_id: {type: string}
|
|
credential_configured: {type: boolean}
|
|
asterisk_allow:
|
|
type: array
|
|
items: {type: string, enum: [alaw, ulaw]}
|
|
config_sha256: {type: string, pattern: '^[a-f0-9]{64}$'}
|
|
ReadonlyTrunk:
|
|
type: object
|
|
required:
|
|
- mode
|
|
- trunk_id
|
|
- provider_id
|
|
- revision
|
|
- status
|
|
- config
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
trunk_id: {type: string}
|
|
provider_id: {type: string}
|
|
revision: {type: integer, minimum: 1}
|
|
status: {type: string, const: published}
|
|
updated_at: {type: string, format: date-time}
|
|
config: {$ref: '#/components/schemas/TrunkView'}
|
|
AdminTrunkList:
|
|
type: object
|
|
required: [mode, trunks]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
trunks: {type: array, items: {$ref: '#/components/schemas/AdminTrunk'}}
|
|
ReadonlyTrunkList:
|
|
type: object
|
|
required: [mode, trunks]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
trunks:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ReadonlyTrunk'
|
|
Cell:
|
|
type: object
|
|
required: [mode, cell_id, revision, config, updated_at, updated_by]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
cell_id: {type: string}
|
|
revision: {type: integer, minimum: 1}
|
|
config: {$ref: '#/components/schemas/CellConfig'}
|
|
cloud_instance_id: {type: string}
|
|
instance_name: {type: string}
|
|
region: {type: string}
|
|
boot_id: {type: string}
|
|
updated_at: {type: string, format: date-time}
|
|
updated_by: {type: string}
|
|
Publication:
|
|
type: object
|
|
required: [trunk_id, revision, cell_id, status, updated_at]
|
|
properties:
|
|
trunk_id: {type: string}
|
|
revision: {type: integer, minimum: 1}
|
|
cell_id: {type: string}
|
|
status: {type: string, enum: [pending, applied, failed]}
|
|
error_code: {type: [string, 'null']}
|
|
applied_at: {type: [string, 'null'], format: date-time}
|
|
target_digest: {type: string}
|
|
local_revision: {type: integer, minimum: 0}
|
|
local_digest: {type: string}
|
|
operation_id: {type: string}
|
|
updated_at: {type: string, format: date-time}
|
|
AuditEntry:
|
|
type: object
|
|
required:
|
|
- audit_id
|
|
- resource_type
|
|
- resource_id
|
|
- action
|
|
- revision
|
|
- actor
|
|
- details_json
|
|
- created_at
|
|
properties:
|
|
audit_id: {type: string}
|
|
resource_type: {type: string, const: trunk}
|
|
resource_id: {type: string}
|
|
action:
|
|
type: string
|
|
enum:
|
|
[
|
|
upsert,
|
|
publish,
|
|
publish_failed,
|
|
disable,
|
|
disable_failed,
|
|
rollback,
|
|
rollback_failed,
|
|
]
|
|
revision: {type: integer, minimum: 0}
|
|
actor: {type: string}
|
|
request_id: {type: [string, 'null']}
|
|
details_json: {type: string}
|
|
created_at: {type: string, format: date-time}
|
|
ProviderInput:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [display_name, lifecycle]
|
|
properties:
|
|
display_name: {type: string, minLength: 1, maxLength: 256}
|
|
notes: {type: string, maxLength: 2000}
|
|
lifecycle: {type: string, enum: [active, archived]}
|
|
Provider:
|
|
allOf:
|
|
- {$ref: '#/components/schemas/ProviderInput'}
|
|
- type: object
|
|
required: [provider_id, revision, trunk_count, created_at, updated_at]
|
|
properties:
|
|
provider_id: {type: string}
|
|
revision: {type: integer, minimum: 1}
|
|
trunk_count: {type: integer, minimum: 0}
|
|
created_at: {type: string, format: date-time}
|
|
updated_at: {type: string, format: date-time}
|
|
updated_by: {type: string}
|
|
ProviderList:
|
|
type: object
|
|
required: [mode, providers]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
providers: {type: array, items: {$ref: '#/components/schemas/Provider'}}
|
|
ProviderResponse:
|
|
type: object
|
|
required: [mode, provider]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
provider: {$ref: '#/components/schemas/Provider'}
|
|
ObservationInput:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [cell_id, boot_id, sequence, observed_at, source, states]
|
|
properties:
|
|
observation_id: {type: string}
|
|
cell_id: {type: string}
|
|
trunk_id: {type: string}
|
|
boot_id: {type: string, minLength: 1}
|
|
sequence: {type: integer, minimum: 1}
|
|
observed_at: {type: string, format: date-time}
|
|
source: {type: string}
|
|
config_revision: {type: integer, minimum: 0}
|
|
states: {type: object}
|
|
occupancy: {type: object}
|
|
sample_id: {type: string}
|
|
StatusItem:
|
|
type: object
|
|
required: [mode, cell_id, availability, complete, missing_sources]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
cell_id: {type: string}
|
|
availability: {type: string, enum: [healthy, stale, unknown, disabled]}
|
|
complete: {type: boolean}
|
|
observed_at: {type: [string, 'null'], format: date-time}
|
|
received_at: {type: [string, 'null'], format: date-time}
|
|
observation_age_seconds: {type: [integer, 'null'], minimum: 0}
|
|
clock_skew: {type: boolean}
|
|
reason: {type: string}
|
|
boot_id: {type: string}
|
|
sequence: {type: integer, minimum: 1}
|
|
config_revision: {type: integer, minimum: 1}
|
|
config_status: {type: string}
|
|
egress_pool_id: {type: string}
|
|
eligibility: {type: string}
|
|
missing_sources: {type: array, items: {type: string}}
|
|
states: {type: object}
|
|
occupancy: {type: object}
|
|
trunks: {type: array, items: {type: object}}
|
|
publication: {type: object}
|
|
StatusResponse:
|
|
type: object
|
|
required: [mode, complete, cells]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/Mode'}
|
|
complete: {type: boolean}
|
|
generated_at: {type: string, format: date-time}
|
|
data_as_of: {type: [string, 'null'], format: date-time}
|
|
coverage: {type: object}
|
|
cells: {type: array, items: {$ref: '#/components/schemas/StatusItem'}}
|
|
StatisticsSummary:
|
|
type: object
|
|
required: [mode, from, to, complete, metrics]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/StatsMode'}
|
|
from: {type: string, format: date-time}
|
|
to: {type: string, format: date-time}
|
|
timezone: {type: string}
|
|
definition_version: {type: string}
|
|
filters: {type: object}
|
|
complete: {type: boolean}
|
|
missing_sources: {type: array, items: {type: string}}
|
|
unresolved_count: {type: integer, minimum: 0}
|
|
data_as_of: {type: [string, 'null'], format: date-time}
|
|
metrics: {type: object}
|
|
failure_reasons: {type: array, items: {type: object}}
|
|
realtime: {type: object}
|
|
TimeseriesResponse:
|
|
type: object
|
|
required: [mode, from, to, granularity, complete, series]
|
|
properties:
|
|
mode: {$ref: '#/components/schemas/StatsMode'}
|
|
from: {type: string, format: date-time}
|
|
to: {type: string, format: date-time}
|
|
timezone: {type: string}
|
|
definition_version: {type: string}
|
|
filters: {type: object}
|
|
granularity: {type: string, enum: [minute, hour, day]}
|
|
complete: {type: boolean}
|
|
series: {type: array, items: {type: object}}
|
|
ErrorResponse:
|
|
type: object
|
|
required: [error]
|
|
properties:
|
|
error:
|
|
type: object
|
|
required: [code, message]
|
|
properties:
|
|
code: {type: string}
|
|
message: {type: string}
|
|
fields: {type: object}
|
|
request_id: {type: string}
|