> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zappway.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# VoiceFlux API

> Internal VoiceFlux architecture, routes, Prisma query shapes, model policy, worker delivery, billing, retention, and security contracts.

# VoiceFlux API

> Internal developer reference. The evidence baseline is the complete audit package in `docs/voiceflux/`, especially documents 01, 04, 07, 09, 11, and 12 plus `voiceflux-audit-manifest.json`.

## Route Map

| Method         | Route                          | Authorization                   | Indexed tenant query                                               |
| -------------- | ------------------------------ | ------------------------------- | ------------------------------------------------------------------ |
| `GET/PATCH`    | `/api/voiceflux/settings`      | read union / `billing.manage`   | unique `organizationId`                                            |
| `GET/POST`     | `/api/voiceflux/profiles`      | `agents.read` / `agents.write`  | `organizationId, enabled, createdAt`                               |
| `PATCH/DELETE` | `/api/voiceflux/profiles/[id]` | `agents.write`                  | direct `id` plus `organizationId` isolation                        |
| `GET`          | `/api/voiceflux/usage`         | `billing.read` or `agents.read` | `organizationId, periodEnd`                                        |
| `GET`          | `/api/voiceflux/jobs`          | `logs.read`                     | direct `conversationId, createdAt` plus `organizationId` isolation |

All profile IDs and agent IDs supplied by clients are revalidated against the active organization. Job diagnostics select only status, provider/model metadata, attempt counts, duration, safe failure code, and timestamps. They never return message text, `failureDetail`, `audioStorageKey`, or `audioUrl`.

`VoiceFluxSettingsUpdateSchema` intentionally excludes `includedAudioSeconds`; tenants cannot grant themselves provider allowance.

## Persistence

Core models:

* `OrganizationVoiceFluxSettings`: entitlement activation, Stripe subscription state, default profile, retention, included allowance.
* `VoiceFluxProfile`: organization/agent-scoped structured style.
* `VoiceFluxSynthesisJob`: idempotent lifecycle and safe diagnostics.
* `VoiceFluxUsagePeriod`: UTC monthly included, purchased, and used audio seconds.

Activation fields are `Agent.voiceRepliesEnabled` and `Conversation.voiceFluxEnabled`. The queue requires both fields plus `Conversation.isAiEnabled`.

Profile resolution performs separate indexed queries and applies `agent profile > organization default > built-in defaults`. Do not replace direct `organizationId`, `agentId`, `conversationId`, or `messageId` filters with relation filters.

## Runtime Flow

1. `handle-chat-message/handler.ts` persists the normal text answer.
2. `enqueueVoiceFluxForMessage(messageId)` validates emergency/provider state, three-layer activation, channel support, commercial entitlement, and available allowance.
3. A deterministic SHA-256 idempotency key includes message, selected profile/style, and fixed model policy.
4. BullMQ queue `voiceflux-synthesize` runs `processVoiceFluxJob` in `apps/workers-services`.
5. The worker synthesizes OGG/Opus, measures actual duration, reserves usage atomically, uploads privately, and delivers through the existing channel adapter.
6. Any safe failure delivers the already-persisted original text. An uncertain `DELIVERING` retry favors text over duplicate audio.

Supported delivery channels are Baileys, WhatsApp Cloud, Telegram `sendVoice`, Messenger audio attachment, and Instagram audio attachment.

## Fixed Model Policy

The worker calls the official Google Gemini Interactions REST endpoint directly:

* endpoint: `https://generativelanguage.googleapis.com/v1beta/interactions`
* auth: `x-goog-api-key` with server-only `GOOGLE_AI_API_KEY`
* provider fallback: none; OpenRouter is never used by VoiceFlux
* Google Cloud project/location variables and ADC are not required

Backend constants are hard-coded and not tenant- or environment-configurable:

```text theme={null}
attempt 1: gemini-3.1-flash-tts-preview
attempt 2: gemini-3.1-flash-tts-preview
recovery:  gemini-2.5-flash-tts (only after both 3.1 failures)
```

`gemini-3.1-flash-tts-preview` is treated as stable and operational and is the sole pricing/capacity baseline. No model branch beyond the two IDs listed above is permitted. Changes require updating the complete `docs/voiceflux` audit package and provider policy tests.

## Metering and Retention

Duration is measured from generated OGG/Opus output and rounded up to a whole second. `meterVoiceFluxAudioSeconds` uses a transaction and conditional `updateMany` to reserve allowance atomically. Provider consumption is still metered if synthesis completed after another concurrent request exhausted the delivery allowance.

Uploaded objects receive `expiresAt`. The VoiceFlux worker scans the indexed expiration column hourly, deletes expired S3 objects in bounded 100-row batches, and clears storage references. A Redis ownership lock prevents cleanup overlap across replicas. Missing storage configuration disables cleanup without deleting job audit records.

## Worker Resilience

The VoiceFlux entrypoint follows the same operational contract as the mature workers-services workers:

* separate Redis connections isolate BullMQ blocking work from health, queue inspection, cleanup locks, and realtime logs;
* reconnect uses bounded backoff with connect, reconnect, error, and end telemetry;
* concurrency, rate limiting, Bull locks, stalled recovery, health cadence, cleanup cadence, and shutdown timeout are validated environment-tunable integers;
* health includes active/waiting/delayed work, failures, stalls, real average latency, cleanup outcomes, Redis connection states, memory, and uptime;
* retention cleanup is non-overlapping within a process and uses a distributed token-checked lock across replicas;
* shutdown is idempotent, drains with a timeout, force-closes only after the deadline, and closes the queue, both Redis connections, and Prisma;
* uncaught exceptions and unhandled rejections enter the same fatal shutdown path.

BullMQ remains configured with one synthesis processing attempt. This is intentional: restarting the processor would create another provider sequence and could violate the strict maximum of two 3.1 calls followed by one 2.5 Flash recovery call per synthesis job. Redis reconnect and stalled-lock recovery protect infrastructure without creating a second provider-attempt budget.

Each provider call is claimed atomically in `VoiceFluxSynthesisJob` before the external request. A worker restart resumes from `primaryAttempts` and `fallbackUsed`; exhausted jobs never restart the model sequence. This conservative reservation also prevents concurrent replicas from issuing the same attempt.

## Billing and Stripe

VoiceFlux is a `level_2+` growth module. Checkout copies `organizationId` and `growthModuleKey` into subscription metadata. Checkout completion and subscription webhook events synchronize the base subscription module list and `OrganizationVoiceFluxSettings.stripeSubscriptionId/status`. Inactive or deleted add-on subscriptions disable organization VoiceFlux.

The webhook remains the commercial source of truth. The UI cannot activate VoiceFlux when plan eligibility or add-on state is missing.

## Frontend Contract

The localized Pages Router surface is `/voiceflux`. `ExpandedNavigation` and the collapsed `Navigation` place VoiceFlux immediately after Livia and before ZappFlux. The page reads the settings, usage, profiles, and agent-table APIs; it does not duplicate backend state or introduce a client-only profile contract.

Permissions remain intentionally split: `agents.read` controls visibility, `agents.write` controls profile CRUD, and `billing.manage` controls organization policy. Voice names and all style option arrays are exported from `@zappway/lib/voiceflux/contracts` and shared by the dedicated page, agent editor, and Zod schemas.

Required Playwright targets:

| Surface                                   | Selector                          |
| ----------------------------------------- | --------------------------------- |
| Conversation Logs below AI enable/disable | `logs-voiceflux`                  |
| Existing AI Employee settings             | `agent-settings-voiceflux`        |
| New AI Employee modal                     | `new-agent-voiceflux`             |
| Agent voice profile editor                | `agent-voiceflux-profile`         |
| Expanded VoiceFlux navigation             | `expanded-navigation-voiceflux`   |
| Dedicated VoiceFlux page                  | `voiceflux-page`                  |
| Create voice character                    | `voiceflux-create-profile`        |
| Voice character dialog                    | `voiceflux-profile-dialog`        |
| Organization settings                     | `voiceflux-organization-settings` |
| Latest safe conversation diagnostic       | `logs-voiceflux-diagnostic`       |

## Gotchas

* Never suppress the normal text response unless the VoiceFlux job was successfully queued.
* Never log raw reply text, credentials, provider payloads, audio URLs, or internal error details.
* Do not retry BullMQ synthesis jobs independently of the provider adapter; the adapter owns the exact model-attempt ceiling.
* Do not expose model IDs as product settings.
* Do not add allowance writes to the public settings schema.
* Keep Stripe cancellation handling synchronized with organization activation.

## Verification

Run the VoiceFlux Jest suites, dashboard/worker/lib typechecks, practical Playwright checks for all required selectors, Prisma validation, docs translation/navigation scripts, and finally the required Graphify forced update.
