AI disclosure: This article was generated by an authorized AI assistant on behalf of Ozil Goal AI operator Jimmy Allen. The public product is used as a concrete example. The state model below is a design proposal, not a claim about its deployed backend or a hands-on review of video quality.

A reference image and a finished AI video should not share a single “generated” flag. They have different costs, different outputs and different failure modes.

Ozil Goal AI illustrates the distinction: a verified account can create one free reference image, while videos are paid and may differ from the image. The person also chooses a scene and a resolution before generating a video. A still image is useful context, but it is not a video job, a payment receipt or a guarantee of a later result.

Give each deliverable its own state

A compact model can start with two independent job types:

type JobState = | 'created' | 'queued' | 'processing' | 'succeeded' | 'failed' | 'cancelled'; type MediaJob = { id: string; ownerId: string; kind: 'reference_image' | 'video'; state: JobState; scene: string; resolution: '480p' | '720p'; referenceJobId?: string; }; 

This type describes job identity and status. It deliberately does not make the browser’s submitted price authoritative, and it does not treat a successful image job as a successful video job. In a real application, validate the allowed scene/resolution combinations on the server rather than accepting every string this illustrative type permits.

A video can refer to a successful reference image without inheriting its success state. If the reference is regenerated or replaced, retain the particular reference identifier used for an existing video request. Otherwise the interface may show a new image beside a video that was requested from an older one.

Keep job state separate from financial state

“Queued” describes processing. “Paid” describes a financial event. “Succeeded” describes a usable output. These are different facts.

A robust design records the server-selected catalog option and its cost when a paid request is accepted. It then makes the creation of a job and any credit reservation atomic. Retrying the same request should resolve to the same job through an idempotency key, rather than charge again and create a second task.

That is an implementation requirement to verify with concurrency tests, not something a UI label can establish. The example type alone provides none of those guarantees.

A timeout is not a confirmed failure

Suppose a browser sends a render request and loses its connection before the response arrives. The server might already have accepted the job.

The safe recovery flow is to look up the existing request or job and show its current state. Automatically submitting a second paid request creates ambiguity. Automatically refunding a job just because one status request timed out can create a different inconsistency.

Use an explicit “status not yet confirmed” message when necessary. A confirmed failure can follow a documented refund or credit-release path; an unknown result needs reconciliation first.

Show a confirmation summary that matches the request

For a product offering several scenes and resolutions, show the selected combination beside the cost. A resolution by itself may not determine the price. In Ozil Goal AI’s current public packs, daylight and Halloween goals and the fake rabona option have distinct published credit rules; the fake rabona option uses 10 credits at either resolution.

Also state the boundary of the free allowance precisely: one reference image per verified account is different from a free finished video, or a daily free allowance. Link to current prices rather than embedding an old price into an evergreen confirmation message.

Permission and quality need separate checks

For personal-photo workflows, explain what input is allowed before the upload: an adult’s own photo or an adult photo they have permission to use. A consent statement does not guarantee that an output will preserve identity or physical details, and a sample result does not guarantee the same result for every photo.

These checks belong at different points in the flow. Input permission is a prerequisite. Output review happens after generation. Financial reconciliation follows authoritative job and payment records. Keeping them separate makes the system easier to explain and easier to debug.

No paid video was generated for this article. The useful engineering question is whether each action has one clear meaning: create a reference, request a specific render, inspect an existing job, or reconcile a confirmed outcome.