import { initContract } from '@ts-rest/core'; import { z } from 'zod'; import { callSessionSchema, initiateCallSchema, callStatusSchema, callLogQuerySchema, } from '../schemas/shopkeeper-telephony.schemas'; import { errorResponseSchema, insufficientTokensErrorSchema, paginationResponseSchema, } from '../schemas/common.schemas'; const c = initContract(); export const shopkeeperTelephonyContract = c.router({ incomingWebhook: { method: 'POST', path: '/shopkeeper/telephony/webhook', body: z.object({ sessionId: z.string(), callerNumber: z.string(), destinationNumber: z.string(), direction: z.string(), isActive: z.coerce.boolean(), dtmfDigits: z.string().optional(), /** When present (Africa's Talking recording callback), we run STT → intent → TTS → Play. */ recordingUrl: z.string().url().optional(), recording_url: z.string().url().optional(), }), responses: { 200: z.object({ action: z.string() }), 400: errorResponseSchema, }, summary: "Africa's Talking incoming call handler", }, callStatusWebhook: { method: 'POST', path: '/shopkeeper/telephony/status', body: callStatusSchema, responses: { 200: z.object({ received: z.boolean() }), 400: errorResponseSchema, }, summary: 'Call duration/cost status updates', }, initiateCall: { method: 'POST', path: '/shopkeeper/telephony/call', body: initiateCallSchema, responses: { 200: z.object({ callSession: callSessionSchema, tokensCharged: z.number().int(), }), 400: errorResponseSchema, 401: errorResponseSchema, 402: insufficientTokensErrorSchema, }, summary: 'Trigger outbound proactive call to shop owner', }, getCallLogs: { method: 'GET', path: '/shopkeeper/telephony/logs', query: callLogQuerySchema, responses: { 200: z.object({ calls: z.array(callSessionSchema), pagination: paginationResponseSchema, }), 401: errorResponseSchema, }, summary: 'Call history for shop', }, });