Changelog
Changes to the Masko API are recorded here, newest first. Breaking changes are flagged clearly with a migration note.
Read the notes for any version that is newer than when you last integrated, then update your REST client against the current OpenAPI specification.
Size variant backfills add only missing files, AV1 included (October 27, 2026, behavior change)
POST /v1/mascots/{id}/size-variants with {} now makes every file an animation lacks, format by format: WebM, HEVC, stacked MP4 and stacked AV1, at the animation's own width and at each size. Before, it skipped a size once its WebM and HEVC files existed, so animations made before AV1 never got their AV1 files. Files that exist are never remade and keep their links. force: true still remakes every sized file.
Send feedback to the Masko team (October 27, 2026, additive)
POST /v1/feedback and the MCP tool send_feedback send feedback to the Masko team about a Masko feature, the MCP server, the REST API or the docs. Only summary is required; feedback_type, sentiment, friction_points, suggested_improvement, details, task_completed, resource_id and agent are optional. Read-only keys and connections can send it. Each account can send 5 a minute and 30 a day; more returns 429 rate_limited. The MCP server now also sends instructions to every app that connects, telling agents when to use it. See send feedback to Masko.
File sizes in job results, assets and webhooks (October 27, 2026, additive)
GET /v1/jobs/{id} and the job.completed webhook add file_sizes: each file's size in bytes, under the same key as its link in urls, or null when the file cannot be read. Every asset (GET /v1/assets, GET /v1/mascots/{id}/assets, GET /v1/assets/{id}) adds file_size, in bytes once the file is completed. It gives a quick idea of what a mascot weighs before you download anything.
AV1 files for app players (October 27, 2026, additive)
Every animation made from now on also gets a stacked AV1 file (stacked_video_av1): colour above, transparency below, like the stacked MP4, two to three times lighter than HEVC or the stacked MP4 at the same look. GET /v1/canvases/{canvasId}/releases/{releaseId}/delivery takes formats=av1: with target=apple or target=android, each clip that has the file comes as videos.av1 in place of hevc or stacked. Without formats, and with other targets, deliveries are unchanged. Masko player 0.1.6 plays it on Apple devices (with the device's AV1 chip or dav1d inside the player) and on Android phones with an AV1 decoder, and gives the value to send as MaskoPlayer.formats; React Native gets it as maskoFormats() in 0.1.7. The CDN export lists the file as transparent_video_av1. Animations made earlier keep their files.
The Masko player plays clips' own voices by default (October 26, 2026, behavior change)
Masko player 0.1.3 plays a clip's own voice (hasAudio) unless your app turns sound off: sound is now on by default, and sound: false (setSound(false) on the web) mutes it. Browsers allow sound only after the person's first click or key press on the page; until then the player plays muted, and the voice is heard from the next clip or loop. One animation played with clip plays its file's own voice too. To keep 0.1.2's silence, pass sound: false.
The Masko player plays one animation from its files (October 25, 2026, additive)
Masko player 0.1.2 plays one looping animation without a canvas: give it the animation's hosted files in place of a delivery, clip: { webm, hevc } on the web and in React, MaskoPlayer(clip:) with the HEVC file on Apple, loadClip with the stacked MP4 on Android, and clip: { hevc, stacked } in React Native. It plays the file each platform shows with transparency and loops it. See play one animation. Releases play as before.
Release ids and clip voices in deliveries (October 25, 2026, additive)
GET /v1/canvases/{canvasId}/releases/{releaseId}/delivery and GET /v1/canvases/{canvasId}/export?delivery=1 write release.id, a fingerprint of the canvas that plays, without its links: a fresh delivery with the same id only renews the links. A clip with its own voice carries hasAudio: true, so a player with sound on unmutes it; a release compiled earlier gets it the next time its mascot version is compiled. Empty condition groups and sounds without a link are left out, and manifest size variants list only the formats of the requested target. Players of contract 1 need no change.
Turn on hosting with the API (October 23, 2026, documentation)
POST /v1/mascots/{id}/publish is now in the OpenAPI specification and the docs: it turns on asset hosting, the same switch as Get Links in Studio, so a mascot made in Studio or through the MCP server gets permanent public links. See turn on hosting. The call itself is unchanged. The 409 cdn_export_not_ready message from GET /v1/mascots/{id}/cdn-export now says whether hosting is off or no file is hosted yet, and names this call. The status, code and details are unchanged.
.mkpk exports for ESP32 boards (October 23, 2026, additive)
POST /v1/assets/{id}/exports accepts format: "mkpk": one animation as a .mkpk pack, the format the ESP32 Masko SDK plays. size is required and is the exact frame width, a multiple of 16 from 32 to 1024. The new optional mkpk object sets screen_width and screen_height (together; the frames are centred on that screen), fps (default 24), quality (default 75) and background_color (default #000000). Export receipts for this format include the complete settings under mkpk. Mascot settings accept publish_params.mkpk_exports to give every future forward animation one pack with the same settings. Existing formats and fields are unchanged.
Release delivery for players (October 23, 2026, additive)
GET /v1/canvases/{canvasId}/releases/{releaseId}/delivery and GET /v1/canvases/{canvasId}/export?delivery=1 accept target=apple, which returns only the HEVC links an iPhone, iPad or Mac app plays, and target=android, which returns only the stacked MP4 links (colour above, transparency below) an Android app plays. Releases made from now on carry the stacked files; an Android delivery of an older release has no clip links, so release the canvas again. An edge can set speedInput, the name of a number input its clip speed follows (speed times the value the app sets, kept between 0.2 and 4), through PATCH /v1/canvases/{canvasId}/edges/{edgeId}; releases carry it. Every delivery now carries playerContract (the version of the playback rules, 1) and requires (the graph features it uses: any-state, condition-groups). A player refuses a delivery whose playerContract it does not know or whose requires names a feature it does not implement. Existing targets and fields are unchanged. The JSON Schema describes the whole envelope.
Silent Standard animations (October 21, 2026)
Standard animations no longer carry a soundtrack. The video model invented one for every clip, so the video, WebM, HEVC and stacked files played sounds nobody asked for. New animations have no audio track, and every picture frame is unchanged. Talking animations keep their voice. Animations made before this date keep their sound.
Applications removed (October 21, 2026, breaking)
GET /v1/applications, POST /v1/applications, GET /v1/applications/{id} and POST /v1/applications/{id}/keys are removed and return 404. Application secret keys (masko_sk_) have had no endpoint that accepts them since playback sessions were removed on September 27, 2026, and no account served a mascot through one.
Migration: call the REST API from your backend with an API key, and connect AI apps through the MCP server. Your app plays exported files or hosted links and needs no Masko credential.
Shorter Standard animations (October 18, 2026, additive)
Under API version 2026-09-26, animation_model: "standard" accepts 2 to 15 whole seconds instead of 5 to 15, still at 2 credits per second, so a 3 second animation costs 6 credits. Requests that worked before are unchanged.
Voices for every account (October 10, 2026)
Under API version 2026-09-26, every account can add a voice. The voice calls (suggestions, adjust, samples and keeping a voice with PUT) no longer return 403 with details.reason: "voice_locked"; request and response shapes are unchanged.
Mascots from a brand book (October 9, 2026, additive)
Under API version 2026-09-26.
- New
POST /v1/mascots/from-brand-book: send a brand book as public links (a PDF up to 50 MB, or page images) or uploads, at most 30 pages, and one job reads it for free, draws every mascot view and prop for 1 credit each (at most 17), and creates the mascot with its references, description, colors, style, don'ts and props. Optionalmax_creditscaps the spend. Nothing is charged when the brand book has no mascot, costs more than the cap, or the balance is short. - Jobs of type
mascot_brand_bookreportstepwhile running andresultwithmascot_idonce completed. POST /v1/uploadaccepts JSON{ "content_type": "application/pdf", "size": BYTES }and returns a signedupload_urlto PUT a PDF of up to 50 MB straight to storage. The returnedasset_idworks infilesofPOST /v1/mascots/from-brand-book.
Talking animation price reduction (October 6, 2026)
Under API version 2026-09-26, talking animations cost 2 credits per second instead of 3. One minute costs 120 credits. Estimates and refunds use the reduced rate; request and response shapes are unchanged.
Talking animations up to 5 minutes (additive)
Under API version 2026-09-26.
- A talking animation now holds a talk of up to 5 minutes of video, instead of 2 minutes. A talk longer than 5 minutes returns
400. speech.scriptaccepts up to 15,000 characters andspeech.textup to 7,500.
Talking animations up to 2 minutes (additive)
Under API version 2026-09-26.
- A talking animation now holds a talk of up to 2 minutes of video, instead of about 14 seconds of speech. A talk longer than 15 seconds is recorded in one go and cut in its real pauses into takes that start and end on the start image, then joined into one video. The voice stays as recorded; the video model can lengthen the pause at a cut by a fraction of a second, and the transcript's times include it.
speech.scriptaccepts up to 6,000 characters andspeech.textup to 3,000. A talk longer than 2 minutes returns400.- Movements are performed in place: a move toward the viewer, such as leaning in close, no longer changes the framing, and spoken words are never drawn on screen.
Talking animations (additive)
Under API version 2026-09-26. Adding a voice unlocks once the account has spent $50 on Masko; until then the voice design calls return 403 with details.reason: "voice_locked".
POST /v1/mascots/{id}/generateacceptsspeechwithtype: "animation": the mascot says a line in its voice, with movements written in square brackets. Costs 3 credits per second; the request charges the longest the line could need and refunds unused seconds once the voice is recorded.dry_run: truereturns the estimate for free. The receipt addsestimate,script, andaudioandtranscriptasset IDs.- New voice endpoints under
/v1/mascots/{id}/voiceand/v1/mascots/{id}/variants/{variantId}/voice: get, keep (PUT), remove,suggestions,adjust, andsamples(1 credit for three). - New asset types
audio(MP3) andtranscript(JSON). Video metadata of talking animations reportshas_audio: true.
See talking animations.
Generation response privacy
Public job and asset responses now omit internal generation execution details for all API versions and credentials. Customer-authored mascot descriptions, styles, references, requested edits and public generation tiers remain available. Stored generation records are unchanged.
Migration: remove the former include=prompts query option; it no longer changes the response. Do not depend on raw execution fields in job input_data, output_data or asset metadata. Mask-refinement quality is now returned as original or pro; older input values are still accepted. Use job IDs and request IDs when contacting support about failures.
Direct image animation
Available in the production OpenAPI specification as of September 28, 2026, under API version 2026-09-26.
-
New
POST /v1/animationsanimates an uploaded image under an existingmascot_id, or explicitly creates a mascot viacreate_mascot: {project_id, name?}in the same request. An omitted mascot name is supplied by AI; no character description is generated. Returns the mascot ID for reuse alongside the job receipt. Defaults to Standard, 5 seconds, 10 credits. SupportsIdempotency-Keyacross mascot creation and generation. -
Input-framing behavior change: existing horizontal and vertical image sources are now center-cropped to square before animation, including item-only sources and transition end frames. Previously the full image reached the video model and only the resulting animation was cropped. Square inputs are unchanged. Originals remain intact and cropping adds no credits. To retain a specific framing, upload a prepared square image or set the new
source_image_crop/end_image_croppixel rectangles. See image framing. -
Animate an unattached image from
/v1/uploaddirectly under an existing mascot, without generating another pose or changing mascot references. The source import preserves the original file and selected variant context. Only animation credits are charged.
How versions work
The API path stays /v1. Each set of changes is named by a date, and the current version is 2026-09-26. Send it as the Masko-API-Version header (or api_version query parameter); every response returns the version it used in the same header. Additive changes, such as new fields, endpoints or optional headers, ship inside the current version. A change that could break a working client gets a new date and a migration note here. The OpenAPI specification's info.version always equals the current version.
Media exports (additive)
Available in the production OpenAPI specification as of September 28, 2026, under API version 2026-09-26.
- New POST/GET
/v1/assets/{id}/exportscreate and list image/video exports, with reusable jobs, signed downloads, resizing and optional regeneration. - Mascot settings add
publish_params.image_exportsfor PNG/WebP versions and sizes. New POST/v1/mascots/{id}/exportsexplicitly backfills saved settings. - POST
/v1/projects/{id}/export-settingsapplies settings to current project/folder mascots, with optional backfill. Existing video routes and settings remain compatible. - Image exports preserve source files, transparency and aspect ratio, without upscaling or generation credits. See media exports.
2026-09-26
Deployed on 2026-09-27. The API contract date remains 2026-09-26.
Mascots and canvases
- Canonical routes
/v1/mascotsand/v1/canvasesreturnmascot_id. Existing/v1/collectionsroutes keep working with their legacy fields and are marked deprecated. See the migration guide. - New
GET /v1/canvases/{canvasId}/status: generation progress withgeneration(ready plus node and edge counts),preview,variants,failed_nodesandfailed_edges. - Canvas responses contain only public fields:
object,id,project_id,mascot_id,name,graph,graph_content_hash,created_at,updated_at. GET /v1/canvasespages like other lists when you sendlimit,offsetorcursor, and returns400withparam: "project_id"whenproject_idis missing.generate-allreturnspoll_urlon each job, and409 appearance_unavailablewhen a mascot has no published appearance to generate with.- Breaking in this version: the hosted character registry and its plans, runs, versions and playback issuer are retired. Existing credentials and installed releases are preserved. See terminal setup.
Conventions (additive)
- Every response has a
Request-Idheader and theMasko-API-Versionit used. - Errors add
doc_url,request_idand, when a field is at fault,param. Validation errors list every problem indetails.issues. Existingcodevalues are unchanged. See error codes. - Standard authenticated resource
POSTendpoints acceptIdempotency-Key(/v1/auth/*and/v1/admin/*are excluded). Completed results, including500errors, replay for 24 hours with the same workspace, API version and exact request bytes. See conventions. - Lists return
meta.pagination.next_cursor; pass it back ascursor.offsetkeeps working. - Resources carry an
objectfield naming their type, for example"object": "mascot"or"object": "job". - Error messages on mascot routes say "Mascot not found" instead of "Collection not found". The
not_foundcode is unchanged.
Retry fixes
- Both canonical and legacy collection canvas DELETE return
409 conflictwhen checkpoints or releases retain history. Generated assets remain stored. - Canonical canvas operations accept idempotency keys through their nested handlers without rejecting their own reservation.
- Replays recheck resource access and preserve the original API representation. A key cannot retrieve a response from another credential workspace or API version.
- Multipart uploads preserve binary bytes. Reusing an expired completed key no longer fails on a consumed body, and concurrent retries cannot remove a replacement reservation.
- Errors after execution retain their keys, preventing a retry from repeating committed writes. If the receipt cannot be saved, the API returns
503 idempotency_persistence_failedand keeps the reservation blocked. Retry with the same key and check the operation outcome before starting another request.
Jobs
GET /v1/jobs/{id}andGET /v1/jobsinitially omitted internal execution details by default. The generation response privacy change above makes that omission unconditional. Customer-authored mascot prompts, styles, references, variants and transition endpoints remain available.
Webhooks (additive)
- Deliveries add
id(stable across retries) andobject: "event", plusMasko-Event-Idand a timestamp-boundMasko-Signature: t=...,v1=...header next to the existing signature headers. - Failed deliveries retry for about 21 hours with increasing delays. A webhook is disabled after 100 consecutive failures. Deleting a webhook also deletes its delivery history. See webhooks.
Marketplace listings
-
Organization mascots publish under a team profile with a shared handle, name, logo and bio. Team owners/admins manage publishing, existing creator eligibility and review still apply, and earnings go to the team wallet. Publication state now includes the seller workspace and management permission.
-
Marketplace purchases can belong to Personal or the selected organization. Organization purchases spend team credits and are shared with current team members inside that workspace. Personal purchases stay personal. Library API reads and canvas creation require a license in the credential/project workspace.
-
Publication supports
withdraw, returnslisting_previewandsalesto the owner, makes the description optional, and requires at least 5 finished animations and a creator handle before submitting. -
Studio Marketplace prices and purchase amounts use credits from your existing balance. The catalog returns
price_credits. Existing purchases and ownership remain unchanged; older Desktop versions retain their compatible price fields.
1.14.0 - 2026-08-20
Added
GET /v1/collections/:id/canvases/:canvasIdnow returnsstatus.nodes.failedandstatus.failed_nodes. Failed node and edge entries include the related job ID and a customer-safe error message.
Compatibility
status.nodes.pendingstill counts all incomplete nodes, including failed nodes. Existing polling clients keep their previous behavior and can adoptstatus.nodes.failedwhen ready.
1.6.0 - 2026-05-23
Added
GET /v1/collections/:id/cdn-exportreturns the same published CDN JSON shape as the collection page Get Links export modal. Use this for copy-paste app manifests; use/itemsand/assetsfor raw IDs, prompts, metadata, and status checks.
Changed
- CDN export requests now fail clearly with
409 cdn_export_not_readywhen asset hosting is disabled, the collection is not published, or no CDN assets have been published yet.
1.5.0 - 2026-05-16
Added
GET /v1/assetsandGET /v1/collections/:id/assetsnow accept optionalinclude_file_urls=falsefor faster metadata-only lists. Defaults are unchanged, so existing callers still receive signedfile_urlvalues.
1.2.0 - 2026-04-19
API cleanup pass. Applies one consistent convention across every endpoint: plural resources, verb endpoints only for one-shot actions, {data, meta?} response envelope, generation responses with data.poll_url, and path-parameter IDs instead of bodies.
Added
POST /v1/analyze- unified analysis endpoint. Body:{type: "image" | "url", image_url?, url?}. Replaces the two legacy endpoints.GET /v1/collections/:id/suggestions- AI-suggested action names for a mascot collection. Read-only, no credits.GET /v1/assetsandGET /v1/assets/:id- first-class access to assets. Filter bycollection_id,type,is_archived.DELETE /v1/assets/:id- archive an asset (soft delete).PATCH /v1/collections/:id/items/:itemId- update an item's name or prompt.DELETE /v1/collections/:id/items/:itemId- archive an item.DELETE /v1/collections/:id/canvases/:canvasId- delete a canvas.PATCH /v1/canvas-templates/:idandGET /v1/canvas-templates/:id.DELETE /v1/collections/:id/references/:assetId- remove a reference by path param.
Changed (breaking)
POST /v1/collections/:id/generate-batch- returns202 Acceptedwithdata.jobs,data.total_cost, anddata.poll_url.DELETE /v1/collections/:id/references- the asset ID moves from the body to the URL path. Old:DELETE /referenceswith{asset_id}in body. New:DELETE /references/:assetId.POST /v1/collections/:id/canvases- now accepts an optionaltemplate_id(plusnode_overrides,edge_overrides). The legacy/canvases/:canvasId/from-templateendpoint is removed - apply templates at creation time instead.PUT /v1/collections/:id/canvases/:canvasId- nowPATCH /v1/collections/:id/canvases/:canvasId. Body unchanged.GET /v1/collections/:id/canvases/:canvasId/status- removed. Thestatusobject is now on the canvas GET response.PATCH /v1/collections/:id/cdn-slug- removed. SetslugviaPATCH /v1/collections/:idwith{slug}in the body.GET /v1/collections/:id/cdn-status- removed. Thecdn_statusarray is now onGET /v1/collections/:id.GET /v1/collections/:id/urls- removed. UseGET /v1/collections/:id/assets- URLs are already attached to each asset.- Paginated responses - pagination now lives under
meta.paginationinstead of top-levelpagination. Shape is unchanged:{total, limit, offset, has_more}. - Async responses -
poll_urlnow lives insidedata(previously top-level). Clients that construct the poll URL fromjob_idare unaffected.
Removed
POST /v1/analyze-image- usePOST /v1/analyzewith{type: "image", image_url}.POST /v1/analyze-url- usePOST /v1/analyzewith{type: "url", url}.POST /v1/collections/:id/suggest-actions- useGET /v1/collections/:id/suggestions.
Not changed
POST /v1/collections/:id/generate- URL, body, and response are unchanged.POST /v1/upload- unchanged.GET /v1/jobs/:id- unchanged. Still supports?wait=true&timeout=120.- Authentication and credit costs - all unchanged.
Migration checklist
POST /analyze-imagecallers: swap toPOST /analyzewith{type: "image", image_url}.POST /analyze-urlcallers: swap toPOST /analyzewith{type: "url", url}.POST /suggest-actionscallers: swap toGET /suggestions. No body needed.DELETE /referencesbody callers: moveasset_idfrom body to URL path.cdn-slug/cdn-status/urlscallers: read and write via the main collection endpoints.- Canvas
from-templatecallers: passtemplate_idonPOST /canvasesinstead. - Canvas
PUTcallers: change the method toPATCH.
Most customers will not need code changes if they only use POST /generate and GET /jobs/:id with the documented request and response shapes.
1.1.0 - 2026-04-10
- Envelope enforcement: every v1 response now wraps data in
{data}or{error: {code, message}}. Lists includepaginationmetadata. - Introduced the
api-keypermission levels:read,write,admin. New keys default towrite.
1.0.0 - 2025-12-01
Initial public release of the Masko v1 API covering projects, collections, items, canvases, generation, jobs, webhooks, and credits.
How to follow updates
- Follow @masko_ai on X for breaking-change notifications.
- The OpenAPI spec is published at live OpenAPI specification; its
info.versionidentifies the deployed schema revision.
