Files

170 lines
5.6 KiB
YAML

# yaml-language-server: $schema=https://json-schema.org/draft/2020-12/schema
openapi: 3.1.0
info:
title: agent-call SaaS Recording Handoff API
version: 1.0.0
description: >-
Internal storage handshake. Business results still return through RabbitMQ.
servers:
- url: https://saas.internal
security:
- bearerAuth: []
paths:
/internal/v1/outbound/recording-uploads:
post:
operationId: createRecordingUpload
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/RequestId'
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/UploadRequest'}
responses:
'201':
description: Upload session created or existing session returned
headers: {Cache-Control: {schema: {const: no-store}}}
content:
application/json:
schema: {$ref: '#/components/schemas/UploadSession'}
'200':
description: Existing upload session
content:
application/json:
schema: {$ref: '#/components/schemas/UploadSession'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
/internal/v1/outbound/recording-uploads/{upload_id}/complete:
post:
operationId: completeRecordingUpload
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/RequestId'
- $ref: '#/components/parameters/IdempotencyKey'
- name: upload_id
in: path
required: true
schema: {$ref: '#/components/schemas/Id'}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CompleteRequest'}
responses:
'200':
description: Object independently verified
content:
application/json:
schema: {$ref: '#/components/schemas/VerifiedUpload'}
'409': {$ref: '#/components/responses/Conflict'}
'410': {$ref: '#/components/responses/Expired'}
'422': {$ref: '#/components/responses/Unprocessable'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
components:
securitySchemes:
bearerAuth: {type: http, scheme: bearer}
parameters:
TenantId:
name: X-Tenant-ID
in: header
required: true
schema: {type: string}
RequestId:
name: X-Request-ID
in: header
required: true
schema: {type: string}
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
schema: {type: string}
schemas:
Id:
type: string
minLength: 1
maxLength: 128
pattern: '^[^\s/\\]+$'
UploadRequest:
type: object
additionalProperties: false
required:
- recording_id
- call_id
- content_type
- size_bytes
- checksum_algorithm
- checksum
- channels
- sample_rate_hz
- duration_ms
properties:
recording_id: {$ref: '#/components/schemas/Id'}
call_id: {$ref: '#/components/schemas/Id'}
content_type: {type: string, const: audio/wav}
size_bytes: {type: integer, minimum: 1}
checksum_algorithm: {type: string, const: SHA-256}
checksum: {type: string, pattern: '^[0-9a-f]{64}$'}
channels: {type: integer, const: 1}
sample_rate_hz: {type: integer, minimum: 8000}
duration_ms: {type: integer, minimum: 1}
UploadSession:
type: object
required:
- upload_id
- recording_id
- expires_at
- upload_method
- upload_url
- required_headers
- constraints
properties:
upload_id: {$ref: '#/components/schemas/Id'}
recording_id: {$ref: '#/components/schemas/Id'}
expires_at: {type: string, format: date-time}
upload_method: {const: PUT}
upload_url: {type: string, format: uri}
required_headers: {type: object}
constraints: {type: object}
oss_id: {type: [string, 'null']}
CompleteRequest:
type: object
additionalProperties: false
required: [recording_id, size_bytes, checksum_algorithm, checksum]
properties:
recording_id: {$ref: '#/components/schemas/Id'}
size_bytes: {type: integer, minimum: 1}
checksum_algorithm: {const: SHA-256}
checksum: {type: string, pattern: '^[0-9a-f]{64}$'}
etag: {type: [string, 'null']}
VerifiedUpload:
type: object
required: [upload_id, recording_id, status, oss_id, verified_at]
properties:
upload_id: {$ref: '#/components/schemas/Id'}
recording_id: {$ref: '#/components/schemas/Id'}
status: {const: verified}
oss_id: {type: string}
verified_at: {type: string, format: date-time}
Problem:
type: object
required: [type, title, status, code, detail, request_id, retryable]
properties:
type: {type: string}
title: {type: string}
status: {type: integer}
code: {type: string}
detail: {type: string}
request_id: {type: string}
retryable: {type: boolean}
responses:
Unauthorized: {description: Unauthorized}
Forbidden: {description: Forbidden}
Conflict: {description: Idempotency conflict}
Expired: {description: Upload expired}
Unprocessable: {description: Object failed independent verification}