import {z} from 'zod' export type CampaignTargetStatus = 'Pending' | 'Scheduled' | 'In Progress' | 'Post-processing' | 'Finished' | 'Failed' | 'Waiting' | 'SMS Scheduled'; export type GetApiApiV1CampaignsCampaignIdTargetsArgs = {campaign_id: string, page?: number | undefined, limit?: number | undefined, status?: (CampaignTargetStatus | null) | undefined, from_date?: (string | null) | undefined, to_date?: (string | null) | undefined, from_last_call_date?: (string | null) | undefined, to_last_call_date?: (string | null) | undefined, patient_external_id?: (Array | null) | undefined, external_id?: (Array | null) | undefined, phone_number?: (Array | null) | undefined}; export type GetApiApiV1CampaignsCampaignIdTargetsOptions = {baseUrl: string, fetch?: typeof fetch | undefined}; export const campaignTargetStatus = z.enum(["Pending", "Scheduled", "In Progress", "Post-processing", "Finished", "Failed", "Waiting", "SMS Scheduled"]); export const campaignTargetPayorResolution = z.enum(["retrieved", "not_retrieved"]); export const campaignTargetPatientResolution = z.enum(["successful", "unsuccessful"]); export const payorCallCategory = z.enum(["GOOD", "NO_RESPONSE", "TRANSFER", "TRANSFER_FAILED", "VOICEMAIL", "SERVICE_NOT_AVAILABLE", "HUMAN_ONLY", "AFTER_HOURS", "CLOSED_FOR_HOLIDAYS", "IVR_LOOP", "INPUT_DATA_ISSUE", "WRONG_PHONE_NUMBER", "NOT_FOUND", "UNPROCESSABLE_BY_PHONE", "DISCONNECTED", "NOT_ALL_DATA_POINTS_RETRIEVED", "MEMBER_CONSENT_REQUIRED", "SLA_EXPIRED", "PAYOR_NOT_SUPPORTED", "NO_OPERATING_HOURS", "INVALID_PHONE_NUMBER"]); export const patientCallCategory = z.enum(["GOOD", "NO_RESPONSE", "TRANSFER", "TRANSFER_FAILED", "VOICEMAIL", "SERVICE_NOT_AVAILABLE", "HUMAN_ONLY", "CALLBACK_REQUESTED", "MANAGER_REQUESTED", "DISCONNECTED", "DNC_REQUESTED", "WRONG_USER", "NOT_INTERESTED_RIGHT_NOW", "BLACKLISTED_PHONE", "INVALID_PHONE_NUMBER"]); export const providerCallCategory = z.enum(["GOOD", "WRONG_USER", "PROVIDER_NO_LONGER_AT_LOCATION", "DISCONNECTED", "WRONG_PHONE_NUMBER", "HUMAN_ONLY", "DATA_ISSUE", "CALLBACK_REQUESTED", "TRANSFER_HANG_UP", "UNPROCESSABLE_BY_PHONE", "MEMBER_CONSENT_REQUIRED", "IVR_LOOP", "CLOSED_FOR_HOLIDAYS", "NO_RESPONSE", "VOICEMAIL", "AFTER_HOURS", "TRANSFER", "TRANSFER_FAILED", "BLACKLISTED_PHONE", "INVALID_PHONE_NUMBER"]); export const patientIncomingCallCategory = z.enum(["TRANSFER_BY_USER", "TRANSFER_BY_ASSISTANT", "INSTANT_TRANSFER", "TRANSFER", "TRANSFER_FAILED", "CALL_DROPPED", "SUCCESSFUL_CALL", "UNSUCCESSFUL_CALL", "NO_RESPONSE", "NOT_CONNECTED"]); export const patientIncomingSchedulingCallCategory = z.enum(["SWITCHBOARD", "DEFLECTED", "NO_RESPONSE", "USER_EARLY_DISCONNECT", "FAST_USER_HANG_UP", "TRANSFER_SOP", "UNRESOLVED", "AUTOMATICALLY_BYPASSED"]); export const patientOutgoingSchedulingCallCategory = z.enum(["SWITCHBOARD", "DEFLECTED", "NO_RESPONSE", "USER_EARLY_DISCONNECT", "FAST_USER_HANG_UP", "TRANSFER_SOP", "UNRESOLVED", "VOICEMAIL", "CALLBACK_REQUESTED"]); export const patientBillingCallCategory = z.enum(["NO_RESPONSE", "VOICEMAIL", "WRONG_USER", "PATIENT_NOT_FOUND", "RESOLVED", "CALLBACK_REQUESTED", "SWITCHBOARD", "TRANSFER_SOP", "FAST_USER_HANG_UP", "UNRESOLVED"]); export const notFoundSubCategory = z.enum(["PROVIDER", "MEMBER", "FACILITY", "REQUEST", "OTHER"]); export const transferSubCategory = z.enum(["HUMAN_REQUESTED", "INTEGRATION_ERROR", "INSURANCE_REJECTED", "TRANSFER_REQUESTED", "NATURAL_TRANSFER"]); export const billingResolvedSubCategory = z.enum(["PAY_OVER_THE_PHONE", "PAYMENT_PLAN", "PAYMENT_LINK_SENT", "USER_WILL_PAY", "INQUIRY_RESOLVED"]); export const billingUnresolvedSubCategory = z.enum(["PATIENT_NOT_FOUND", "BALANCE_DISPUTE", "ALREADY_PAID", "REFUSE_TO_PAY", "CANNOT_PAY", "OTHER"]); export const iVRLoopSubCategory = z.enum(["NOT_RECOGNIZE_DATA", "NOT_FOUND", "LONG_WAITING_PERIOD", "BAD_INTERACTION_WITH_IVR", "IVR_ONLY_NUMBER", "VOICEMAIL", "CALLBACK_OFFERED"]); export const serviceNotAvailableSubCategory = z.enum(["PHONE_NUMBER_NOT_AVAILABLE", "CLOGGED_SERVICE", "TECHNICAL_ISSUE", "OTHER"]); export const unprocessableByPhoneSubCategory = z.enum(["FAX", "INSURANCE_PORTAL", "AUTOMATED_SYSTEM"]); export const inputDataIssueSubCategory = z.enum(["MISSING_INFORMATION", "INCORRECT_INFORMATION"]); export const humanOnlySubcategory = z.enum(["STARTING_CALL", "MID_CALL"]); export const voicemailSubCategory = z.enum(["DELIVERED", "NOT_DELIVERED", "NO_MAILBOX"]); export const campaignTargetResponse = z.object({id: z.string(), target_url: z.string(), organization_id: z.string(), campaign_id: z.string(), created_at: z.string(), execution_minutes: z.number().int().nullable(), input_data: z.record(z.string(), z.unknown()), output_data: z.record(z.string(), z.unknown()), status: campaignTargetStatus, resolution: z.union([campaignTargetPayorResolution, campaignTargetPatientResolution]).nullable(), category: z.union([payorCallCategory, patientCallCategory, providerCallCategory, patientIncomingCallCategory, patientIncomingSchedulingCallCategory, patientOutgoingSchedulingCallCategory, patientBillingCallCategory]).nullable(), subcategory: z.union([notFoundSubCategory, transferSubCategory, billingResolvedSubCategory, billingUnresolvedSubCategory, iVRLoopSubCategory, serviceNotAvailableSubCategory, unprocessableByPhoneSubCategory, inputDataIssueSubCategory, humanOnlySubcategory, voicemailSubCategory, payorCallCategory, z.string()]).nullable(), call_log_ids: z.array(z.number().int()).nullable(), last_call_date: z.string().nullable(), phone_number: z.string().nullable(), fax_links: z.array(z.string()).nullable(), payor_api_data: z.record(z.string(), z.unknown()).nullable(), external_id: z.string().nullable(), pre_call_ehr_ids: z.record(z.string(), z.unknown()).nullable().optional(), updated_at: z.string().nullable().optional(), retries: z.number().int().nullable().optional(), scheduled_time: z.string().nullable().optional(), categorization: z.record(z.string(), z.unknown()).nullable().optional(), outcome: z.string().nullable().optional(), statistics: z.record(z.string(), z.unknown()).nullable().optional()}); export const paginatedCampaignTargetsResponse = z.object({targets: z.array(campaignTargetResponse), page_count: z.number().int().nullable().optional(), next_page: z.number().int().nullable().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get Campaign Targets * * GET /api/v1/campaigns/{campaign_id}/targets */ export const getApiApiV1CampaignsCampaignIdTargets = async (args: GetApiApiV1CampaignsCampaignIdTargetsArgs, options: GetApiApiV1CampaignsCampaignIdTargetsOptions) => { const {baseUrl, fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.page != null) query.append("page", String(args.page)) if (args.limit != null) query.append("limit", String(args.limit)) if (args.status != null) query.append("status", String(args.status)) if (args.from_date != null) query.append("from_date", String(args.from_date)) if (args.to_date != null) query.append("to_date", String(args.to_date)) if (args.from_last_call_date != null) query.append("from_last_call_date", String(args.from_last_call_date)) if (args.to_last_call_date != null) query.append("to_last_call_date", String(args.to_last_call_date)) for (const item of args.patient_external_id ?? []) query.append("patient_external_id", String(item)) for (const item of args.external_id ?? []) query.append("external_id", String(item)) for (const item of args.phone_number ?? []) query.append("phone_number", String(item)) const url = `${baseUrl.replace(/\/+$/, '')}/api/v1/campaigns/${encodeURIComponent(String(args.campaign_id))}/targets${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(paginatedCampaignTargetsResponse, await res.json()) };