Files
agent-call/docs/contracts/sip-management.openapi.yaml
rogee d17bbe15d9
management-images / build-and-publish (push) Successful in 34s
fix recording timing and sync call contracts
2026-09-17 17:43:37 +08:00

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}