API referenceThe Licensed Likeness API
Generate with real, licensed people. Mirai checks the selected model's terms on every call, keeps drafts watermarked and records each licence. Version 1.0.0.
Manage keys in your brand account. API usage requires generation entitlement and follows the same watermark and licence rules as Studio. Character APIs below are experimental and disabled by default, not a live third-party catalogue.
Roster
The bookable model roster and per-model character sheets.
GET/modelsscope: read
List the bookable model roster
Public-safe fields only, no reference photos, likeness configuration, earnings, or contact details. Only models who are signed, available, have granted partner-distribution consent and have a complete six-photo reference kit appear; anyone else is omitted entirely rather than flagged. Each entry carries the model's binding restrictions (excluded_categories, excluded_brands, restricted_regions) so an integrator can refuse an out-of-scope brief before writing it, and references_available, which is false unless the reference lane is open for your key and that model. lanes.references says whether the reference lane is open for your key at all. The response also carries approved_renderers, the exhaustive list of engines a likeness may be sent to.
60/min per key
GET/models/{id}/referencesscope: read
Short-lived reference URLs for a consented model
Closed by default. Available only to a partner with a signed partner agreement that covers rendering on its own infrastructure, for a model whose consent covers the same; otherwise every call returns 403 references_lane_closed, and the lanes where Mirai renders (POST /generate, POST /briefs) are the ones to use. When open, returns signed, expiring proxy URLs to the model's canonical reference kit, for feeding into an APPROVED renderer as identity references. Both renderer and brand are required; category is required for a model with excluded categories, and brand_country for a model with territory restrictions: the declared renderer must be on the approved list (the 400 response enumerates it), and the declared brand is checked against the model's exclusions before anything is served, a brand they have excluded is refused outright. URLs expire in 15 minutes, every fetch is logged, and revocation applies to already-issued URLs immediately. The response carries their binding restrictions; they travel with the references.
60/min per key
Parameters
| idrequired | string (path) | |
| rendererrequired | string (query) | The exact endpoint id these references will be used with, e.g. bytedance/seedream/v5/pro/edit. Must be on the approved-renderer list; anything else is refused with the list attached. |
| brandrequired | string (query) | The brand this shoot is for. Checked against the model's excluded brands before any reference is issued. |
| category | string (query) | The product category of the shoot. Required when the model has excluded categories, and checked against them. |
| brand_country | string (query) | Two-letter country code where the brand is based. Required when the model has territory restrictions, and checked against them. |
GET/characters/{modelId}scope: read
Fetch a roster model's character sheet
The structured identity profile distilled at model approval, appearance descriptors, delivery notes, categories, for writing prompts that stay coherent with the real person. Visibility matches GET /models: only bookable models exist; unknown and unavailable ids 404 identically.
A roster model without a sheet yet also 404s with code character_sheet_not_ready, the sheet is enrichment, built at approval time.
60/min per key
Parameters
| modelIdrequired | string (path) | Model id from GET /models. |
Generation
Create draft images and video clips.
POST/generatescope: generate
Generate a draft image with a model's AI likeness
Renders a watermarked draft anchored to the model's canonical identity kit. Sparse prompts are automatically enhanced; every prompt receives Mirai's editorial house style and passes a safety scan before delivery.
Streaming transport: generation takes 1-5 minutes, so once it starts the HTTP status is ALWAYS 200 and the body streams heartbeat whitespace until the final JSON. Read the full body, then JSON.parse it (leading whitespace is valid JSON) and check for an error field before treating it as success. Pre-flight failures (auth, validation, entitlement) return real 4xx statuses with JSON bodies.
Supports the Idempotency-Key header.
20/min per key, 40/min per brand
Parameters
| Idempotency-Key | string (header) | Any string unique to this logical request. Retries with the same key replay the stored result instead of re-rendering. |
POST/videosscope: generate
Animate one of your generated images into a video clip
Starts an image-to-video render (Seedance 2.0; face-reveal prompts route to Kling v3 Pro with the model's canonical headshot as an identity anchor; both engines are named in the Model Release). The source is the asset_id of one of YOUR generated images, raw URLs are not accepted.
Open-IP sources: when the source asset came from POST /ip/{slug}/generate, the render follows the character sheet instead of the fashion pipeline, the sheet's Seedance motion notes are the default motion direction (your prompt overrides them), the era style lock replaces the photorealism clause, and the sheet's legal exclusions are enforced in the prompt.
Async contract: responds 202 immediately with an asset_id. Poll GET /assets/{asset_id} until status leaves processing (typically 1-5 minutes): ready delivers the watermarked draft_url; failed carries an error message and nothing was billed.
Billing: on Starter, Growth and Scale a clip is paid from your monthly credits, priced by its length (see Billing); Starter does not include video, and a prepaid video credit pack covers a clip when credits do not. Enterprise follows its order form. A failed render refunds any credit consumed. Supports the Idempotency-Key header, a replay returns the SAME asset_id.
6/min per key, 10/min per brand
Parameters
| Idempotency-Key | string (header) | Any string unique to this logical request. A replay returns the same 202 body (same asset_id) instead of starting a second render. |
GET/usagescope: read
Credits used and remaining this period
Starter, Growth and Scale pay for API generations from the account's monthly credits (see Billing). billing: credits returns credits_monthly, credits_used and credits_remaining for the current period. Enterprise accounts return billing: enterprise (not credit-metered; usage follows the order form) and accounts without a subscription return billing: none.
Response 200
| billingrequired | credits | enterprise | none | |
| plan | string,null | |
| status | string | |
| credits_monthly | integer | |
| credits_used | integer | |
| credits_remaining | integer | |
| period_start | string,null | |
| period_end | string,null | |
Licensing
License approved assets for commercial use via Stripe Checkout.
POST/usagescope: license
Record a licence for an image a partner rendered on its own pipeline
Approved generation partners only. Report each delivered asset here. Print, Print + OOH and Digital + OOH are recorded here like digital (at her print rate, and a region may be named) when the talent has print on demand switched on and has accepted the partner consent version that covers it; otherwise they are refused (403 individual_approval_required) and go through POST /briefs. The model must be signed, available, opted into partner licensing and have a complete reference kit, and the brand, category and country are checked against the model's restrictions. Mirai records a metered external licence priced from the model's rate table (video at the video rate, per 10 seconds of runtime) and computes the model's payout; settlement is invoiced periodically. Idempotent on external_asset_ref: re-reporting the same asset never double-bills.
Request body
| model_idrequired | string | |
| external_asset_refrequired | string | Your stable id for the delivered asset. |
| brandrequired | string | The brand the asset is for. Checked against the model's excluded brands. |
| category | string | Product category. Required when the model has excluded categories. |
| brand_country | string | Two-letter country code where the brand is based. Required when the model has territory restrictions. |
| media | image | video | Default image. |
| runtime_seconds | number | Video only, required: clip length in seconds. Priced per 10 seconds, 10 second minimum. |
| reference_token | string | The token from the reference URL used, so the licence ties to the exact references served. |
| format | string | Usage format, default Digital. Digital only. |
| duration | string | Licence duration, default 6 months. |
| territory | string | Global, the default. Digital licences are always Global. |
GET/licenses/quotescope: read
Price a licence without committing
Non-binding and side-effect free. Called with image_ids alone it returns the full priced option matrix for those assets (formats, durations, per-format territories) so no integrator ever holds a stale copy of the rate card; called with format and duration it returns the exact quote. Every gate the real POST /licenses enforces is evaluated here too and returned as blockers rather than errors, including the instant-scope boundary: images auto-approved under a model's standing digital consent can be licensed for digital use only unless she has print on demand switched on, and otherwise print / out-of-home requires their individual approval. Digital licences are always Global; regions exist for Print + OOH at the same price.
60/min per key
Parameters
| image_idsrequired | string (query) | Comma-separated asset ids from /generate. One model per quote. |
| format | string (query) | |
| duration | string (query) | |
| territory | string (query) | |
POST/licensesscope: license
Create a licence checkout for approved images
Creates a pending license plus a Stripe Checkout session; complete payment in a browser via checkout_url (the session and the pending license both expire after 1 hour). On payment, the license activates and the assets' clean URLs unlock on GET /assets/{id}.
The approval gate: only assets with approval_status: "approved" (the model's sign-off) can be licensed, this is the platform's load-bearing invariant and cannot be bypassed. All images in one license must be from the same model. Image licenses only on v1 (video licensing runs through the Studio).
Pricing: fee_cents = image_count x base(format) x multiplier(duration) x multiplier(territory). Base rates, Digital: $50/image; Print + OOH: $120/image; Social: $50/image; Print: $120/image. Duration multipliers, 6 months: x1; 12 months: x1.8; 24 months: x2.5; 10 years: x3.5.
10/min per key
Assets
Poll asset state and retrieve deliverable URLs.
GET/assets/{id}scope: read
Fetch the state of one of your generated assets
One id namespace covers images and videos; the response is discriminated by kind. Returns YOUR assets only, not-owned and not-found are both 404 so ids can't be probed.
The authenticated url is non-null IF AND ONLY IF the asset is licensed (model approval + paid license). It streams the original without exposing its permanent storage URL. Licensed image and video downloads carry signed C2PA Content Credentials; X-Content-Credentials on the download says whether they were embedded, and where Mirai enforces them a file that cannot be signed returns 503 credential_unavailable instead of an unsigned copy. Send the same bearer key when following it. draft_url is the watermarked deliverable before licensing, an image thumbnail afterwards, and null for licensed video.
For video assets this is the polling endpoint of the POST /videos async contract, watch status (processing → ready | failed).
60/min per key
Parameters
| idrequired | string (path) | Asset id returned by POST /generate or POST /videos. |
GET/assets/{id}/downloadscope: read
Download a licensed asset
Streams the licensed image or video without exposing its permanent storage URL. Images and videos (MP4) carry signed C2PA Content Credentials (X-Content-Credentials: embedded). Where Mirai enforces them, a file that cannot be signed returns 503 credential_unavailable, retry shortly; otherwise the header reads unavailable. The caller must own the asset and hold an active licence covering it. Send the same bearer key when following the URL returned by GET /assets/{id}.
60/min per key
Parameters
| idrequired | string (path) | Licensed image or video asset id. |
Enterprise lane
Approved generation partners. Brief a talent for images, video or both; the talent approves the brief, you render on your own stack, submit each final, and the talent approves it before it is licensed.
GET/briefsscope: license
Your briefs, newest first
POST/briefsscope: license
Submit a campaign brief for a talent's approval, before anything is created
Approved generation partners only. JSON, or multipart/form-data with the same fields plus up to 8 reference images. media says what the brief covers: image (default), video or both. Images and videos are counted separately (image_deliverables, video_deliverables), and a video brief sets video_seconds, the longest a single video may run. deliverables is still accepted as the old name for image_deliverables. advertiser_country (two-letter code) is required when the talent has territory restrictions. Checked at once against the talent's excluded advertisers, categories and territories, then waits for the talent's approval on Mirai. The talent sees the counts and the video length on the brief.
Request body
| model_idrequired | string | The talent, from GET /models. |
| advertiserrequired | string | The brand the campaign is for. |
| categoryrequired | string | Checked against the talent's excluded categories. |
| descriptionrequired | string | The creative idea, looks, settings and where it will run. |
| advertiser_country | string | Two-letter country code. Required when the talent has territory restrictions. |
| media | image | video | both | What the brief covers. Default image, so existing clients are unchanged. |
| image_deliverables | integer | Stills the brief covers, for image and both. Default 1. |
| video_deliverables | integer | Videos the brief covers, for video and both. Default 1. |
| video_seconds | integer | Required for video and both: the longest a single video may run, in seconds. |
| deliverables | integer | Deprecated: the old name for image_deliverables, still accepted. Not allowed on a video brief. |
| format | string | Images: Digital, Print + OOH. Video: Digital, Digital + OOH. Both: Digital. |
| duration | 6 months | 12 months | 24 months | 10 years | |
| territory | Global | Asia | Middle East | Europe | Australia | North America | South America | Africa | |
Examples
Images only (the default)
{
"model_id": "08975092-607e-47d9-b416-b2e456b0e011",
"advertiser": "Example Skincare",
"category": "Beauty",
"description": "Morning routine in natural window light, three looks.",
"media": "image",
"image_deliverables": 3,
"format": "Digital",
"duration": "6 months"
}
Video only
{
"model_id": "08975092-607e-47d9-b416-b2e456b0e011",
"advertiser": "Example Skincare",
"category": "Beauty",
"description": "Two short clips: applying serum, then a smile to camera.",
"media": "video",
"video_deliverables": 2,
"video_seconds": 15,
"format": "Digital",
"duration": "6 months"
}
Images and video
{
"model_id": "08975092-607e-47d9-b416-b2e456b0e011",
"advertiser": "Example Skincare",
"category": "Beauty",
"description": "Launch set: three stills and two 15 second clips.",
"media": "both",
"image_deliverables": 3,
"video_deliverables": 2,
"video_seconds": 15,
"format": "Digital",
"duration": "12 months"
}
GET/briefs/{id}scope: license
A brief's status and the finals submitted under it
POST/briefs/{id}/submissionsscope: license
Submit a final image or video rendered on your own stack, under an approved brief
multipart/form-data with file and external_asset_ref. The file is read from its bytes: an MP4 is a video final, anything else an image. An image must fit the brief's media (image or both) and is kept under 25 MB. A video must fit a video or both brief, be an MP4 in avc1, avc3, hvc1, hev1, av01, vp09, run no longer than the brief's video_seconds, and stay under 5 MB plus 3 MB per second of video_seconds (50 MB for a 15 second brief, 185 MB for 60 seconds). Images and videos count against their own deliverables. Waits for the talent's approval; once approved it is licensed (a video at the video rate, by runtime, per second with a ten-second minimum per clip) and available from /submissions/{id}/file. Re-submitting the same external_asset_ref returns the existing submission.
Request body
| filerequired | string | The final: an image, or an MP4 for video. |
| external_asset_refrequired | string | Your id for this asset. Idempotency key. |
GET/submissions/{id}scope: license
A final's status, media and duration_seconds; once approved, the licence, file_url and verify_url
GET/submissions/{id}/filescope: license
The approved final with signed C2PA Content Credentials
An image is served as image/jpeg (mirai-xxxxxxxx.jpg) with signed Content Credentials. A video is served as video/mp4 (mirai-xxxxxxxx.mp4). Video Content Credentials are not embedded yet: X-Content-Credentials reads unsigned, and where Mirai enforces credentials a video returns 503 credential_unavailable until video signing ships.
Open IP
Experimental catalogue, disabled by default and not a licensed third-party IP offering. Routes return 404 unless separately enabled for a reviewed partner pilot. Public-domain assessments are jurisdiction- and depiction-specific, not blanket commercial clearance.
GET/ipscope: read
List the open-IP character catalog
Experimental open-IP catalogue, not a commercial FAL partnership announcement or a signed third-party catalogue. Disabled unless OPEN_IP_PARTNER_API=1. Query filters: tier (A|B|C), risk (low|medium|high), franchise, commercial_use (true|false). Review the entry's rights assessment and intended jurisdiction before any use.
Tier C is a watchlist, entries not yet public domain; they always carry commercial_use: false and the detail route withholds prompt packs for them.
60/min per key
Parameters
| tier | string (query) | Filter by tier. |
| risk | string (query) | Filter by trademark risk. |
| franchise | string (query) | Filter by franchise key (e.g. oz, hundred-acre-wood). |
| commercial_use | string (query) | true = only licensable entries; false = only watchlist/restricted. |
GET/ip/{slug}scope: read
Fetch an open-IP character sheet with FAL prompt packs
Full character sheet (identity, legal dossier, visual DNA, voice spec) plus drop-in FAL prompt packs: image2 for openai/gpt-image-2/edit (including the 6-slot reference kit) and seedance for bytedance/seedance-2.0/reference-to-video. Legal avoid-lists are pre-merged into the negatives.
Watchlist (Tier C / commercial_use false) entries return prompt_packs: null and license_terms: null with a watchlist_note.
60/min per key
Parameters
| slugrequired | string (path) | Character slug from GET /ip. |
POST/ip/{slug}/generatescope: generate
Generate a licensed open-IP character image
One-call Mirai × FAL flow: name a catalog character, receive a watermarked, licensable draft generated by the same gpt-image-2 chain as POST /generate. The character sheet anchors identity (visual DNA, palette, era style lock) and its legal avoid-list is enforced as an exclusion clause on every render. prompt is optional scene direction.
Open-IP images are born approval_status "approved", there is no human likeness to consent, so the returned asset_id can go straight to POST /licenses. To animate, pass asset_id to POST /videos (Seedance); motion guidance lives in the character's prompt_packs.
Watchlist (Tier C / commercial_use false) slugs refuse with 403 ip_not_commercial and are never generated.
20/min per key, 40/min per brand
Parameters
| slugrequired | string (path) | Character slug from GET /ip. |
Errors
Inspect response bodies as well as HTTP status. Long-running generation can return an error in its final JSON body after HTTP 200 has already been sent.
| invalid_format | The format value is not in the accepted enum. |
| invalid_duration | The duration value is not in the accepted enum. |
| invalid_territory | The territory value is not in the accepted enum. |
| brand_country_missing | Set your brand's country in Settings before working with a region-restricted model. |
| region_restricted | This model is not available to brands based in your country. |
| images_not_approved | Only model-approved images can be licensed; unapprovedIds lists the offenders. |
| duplicate_license | An active or pending license already covers one of these images. |
| model_not_payout_ready | The model's payout account isn't ready; the booking is refused rather than stranding funds. |
| insufficient_credits | The plan's monthly credits do not cover this request. The body carries creditsNeeded and creditsRemaining. Nothing was reserved or charged. |
| video_quota_exceeded | Video is not included in the plan and no prepaid credit pack covers it, or (Enterprise) the video allowance is used up with no pack or overage. |
| source_has_watermark | The video source image only has a watermarked file; generate a fresh image. |
| character_sheet_not_ready | The model is on the roster but has no character sheet yet. |
| key_limit_reached | A brand can hold at most 10 active API keys. |
| invalid_media | Brief media must be "image", "video" or "both". |
| invalid_deliverables | A deliverables count is missing, out of range, or does not match the brief's media. |
| invalid_video_seconds | A video brief needs video_seconds from 5 to 60. |
| media_mismatch | A video was sent under an image-only brief, or an image under a video-only brief. |
| unsupported_video | The video is not a playable MP4 (avc1, avc3, hvc1, hev1, av01, vp09) with a readable runtime. |
| video_too_long | The video runs longer than the brief's video_seconds. |
| deliverables_exhausted | The brief's images or videos are used up. Ask the talent to approve a new brief. |