Text-to-Video Task Pattern
Extend the opt-in text-to-video demo with organization entitlements, quotas, credits, idempotency, and refunds.
Synced with starter commit
7580470.
Use this page as a reference for building a metered AI feature, not as a ready-made video product. What ships is a local-only mock screen plus the hard parts around tenancy, entitlements, monthly limits, pooled credits, idempotency, failure state, and refunds. Production ignores the demo flags, so no real video generation is enabled by cloning the repository.
Decide what your real provider contract needs
- Replace the adapter in
src/services/ai/video.ts; keep provider-specific code out of routes. - The shipped mock completes inside the request. For a provider that takes longer than a few seconds, enqueue durable work, persist the external job ID, verify callbacks, and make provider requests idempotent.
- Review the one-credit-per-second default, aspect multipliers, plan capability, monthly task limits, and included credit grants. These are example product economics, not recommended pricing.
Ready to launch means: the mock is absent from production, duplicate requests create one task and one spend, insufficient credits are explained, provider failure creates one refund, callbacks cannot cross organizations, and the UI communicates queued/running/failed states.
The text-to-video screen is an opt-in development pattern, not a production AI provider. It is unavailable unless demo features and the text-to-video mock are enabled; demo flags are ignored in production. Replace only src/services/ai/video.ts with your provider adapter.
POST /api/tasks/text-to-video requires same origin, rate limit, authentication, the organization tasks.text_to_video entitlement, the shared monthly task limit, and sufficient pooled credits. Supply Idempotency-Key in the header or body. The service inserts one organization-scoped task, spends credits, records the root ledger transaction, calls the provider, and marks success. Provider failure marks the task failed and appends a credit refund.
Cost is configured in src/config/tasks.ts by seconds and aspect ratio. Plus currently allows 50 organization tasks/month and 500 monthly credits; Max has unlimited task count and 2,500 credits; Free has neither capability. Fetch a task through GET /api/tasks/[uuid]; access is organization-scoped.
For a real long-running provider, keep these invariants but move execution to durable asynchronous work, use provider idempotency, verify callbacks, persist external IDs, and test duplicate requests, insufficient balance, timeout, callback replay, and refund failure.
Related: Set access and limits in Plans and Entitlements, account for spend and refunds in the Credit Ledger, and run long work through Durable Jobs.