Skip to content
maskostudioDocs

All pages

  • Overview/docs/use-cases
  • Mobile app/docs/use-cases#mobile
  • Website/docs/use-cases#website
  • Desktop/docs/use-cases#desktop
  • AI agents/docs/use-cases#agents
  • Videos/docs/use-cases#videos
  • Brand/docs/use-cases#brand
  • Start building/docs/ai-agents
  • Set up once/docs/ai-agents#set-up-once
  • Ask in plain words/docs/ai-agents#ask-in-plain-words
  • What your agent does/docs/ai-agents#what-your-agent-does
  • MCP server/docs/mcp
  • Masko for Cursor/docs/ai-tools/cursor
  • Masko in ChatGPT/docs/ai-tools/chatgpt
  • Masko in Lovable/docs/ai-tools/lovable
  • Masko in Devin/docs/ai-tools/devin
  • Masko in n8n/docs/ai-tools/n8n
  • Masko in Hermes Agent/docs/ai-tools/hermes
  • Masko in OpenClaw/docs/ai-tools/openclaw
  • Start here/docs/tutorials#start-here
  • All tutorials/docs/tutorials
  • Create your first mascot/docs/tutorials/first-mascot
  • Create an animated character/docs/tutorials/first-animation
  • Make a character talk/docs/tutorials/make-it-talk
  • Put your mascot on your website/docs/tutorials/mascot-on-your-website
  • Guide onboarding with a talking mascot/docs/tutorials/web-onboarding-mascot
  • Add a mascot that celebrates progress and welcomes users back/docs/tutorials/web-progress-companion
  • Add a talking support mascot in the bottom right/docs/tutorials/web-support-mascot
  • Show a mascot while your AI thinks/docs/tutorials/ai-loading-mascot
  • Give your AI agent a face/docs/tutorials/ai-agent-face
  • Animate the mascot you already have/docs/tutorials/animate-your-mascot
  • How to make Telegram stickers/docs/tutorials/telegram-stickers
  • How to make Discord stickers/docs/tutorials/discord-stickers
  • Quickstart: your first animation/docs/quickstart
  • Terminal quickstart/docs/terminal
  • API keys and workspaces/docs/authentication
  • CLI browser login/docs/authentication/cli
  • How mascots work/docs/how-mascots-work
  • Credits and costs/docs/credits
  • From text/docs/create/from-text
  • From an image/docs/create/from-image
  • From a website/docs/create/from-website
  • From a brand book/docs/create/from-brand-book
  • Reference images/docs/manage/references
  • What you can generate/docs/generation
  • Pose-to-animation walkthrough/docs/generate/workflow
  • Images and poses/docs/generate/images
  • Animations/docs/generate/animations
  • Talking animations/docs/generate/talking
  • Write good requests/docs/generate/requests
  • Logos, backgrounds and stickers/docs/generate/design-assets
  • Cursor follower/docs/generate/cursor-follower
  • Batch generation/docs/generate/batch
  • Image and video exports/docs/manage/media-exports
  • Canvases and releases/docs/canvas
  • Build a canvas/docs/canvas/build
  • Canvas templates/docs/canvas/templates
  • Generate canvas assets/docs/canvas/generate-all
  • Export a canvas/docs/canvas/export
  • Overview and demo/docs/player
  • Play one animation/docs/player/one-animation
  • Play a canvas/docs/player/canvas
  • Ship in an app with an app key/docs/player/app-keys
  • Hosting and file formats/docs/generate/cdn
  • File sizes/docs/generate/file-sizes
  • Float a mascot on your Mac/docs/integrations/desktop
  • Jobs and polling/docs/manage/jobs
  • Webhooks/docs/manage/webhooks
  • Manage mascots and assets/docs/manage/collections
  • All endpoints/docs/reference
  • Requests and responses/docs/reference/conventions
  • Errors and recovery/docs/reference/errors
  • Command line reference/docs/terminal/commands
  • TypeScript SDK/docs/sdk/typescript
  • Changelog/docs/reference/changelog
  • Migrate to mascots and canvases/docs/manage/studio-migration
Get an API key
Documentation

Ship your mascot in an app

An app key lets an app without a backend, such as a desktop or mobile app, play your mascot. You put the key inside the app. It belongs to one mascot and can only read that mascot's released canvases, so it never exposes your account: someone who digs it out of the app gets what the app already has.

How it works

  1. Release the canvas with Update on the canvas page. An app key never sees drafts.
  2. Create an app key for the mascot, in Get Links → App keys or with the API. The key is shown once.
  3. Ship the key and the canvas ID in your app.
  4. The app asks for the canvas's latest release, downloads its files, keeps them and plays them with the Masko player. On iPhone, iPad and Mac, the player does all of this from the canvas's URL and the key.
  5. Release again whenever you like: the app gets the new release the next time it asks, for example every hour. No new app version is needed.

Play it with the Masko player

On iPhone, iPad and Mac (Masko player 0.1.12 and later), give the player the canvas's URL and the app key:

import MaskoPlayer

let player = MaskoPlayer(
  url: URL(string: "https://api.masko.ai/v1/canvases/CANVAS_ID/delivery")!,
  appKey: "masko_app_YOUR_APP_KEY")
MaskoView(player: player)  // or MaskoPlayerView(player: player)
player.set("pointerHover", true)

The player asks for the latest release, downloads every file once and keeps it, so the mascot plays offline. It asks again at launch and every hour. A new release is used once all its files are downloaded, and it takes over when the mascot's first pose starts its loop again, so nothing jumps; the values your app set carry over. The files live in the app's Application Support folder, left out of backups. Before the first release has arrived, the values you set choose the first pose and fire calls are dropped.

The rest of this page is what the player does for you, for other platforms or your own code.

What an app key can read

RequestWith an app key
GET /v1/canvases/{canvasId}/delivery, the canvas's latest releaseYes, for every canvas of its mascot
GET /v1/canvases/{canvasId}/releases/{releaseId}/delivery, one releaseYes, for every canvas of its mascot
A canvas of another mascot404, as if it did not exist
Anything else: the mascot's settings, its other images, stickers, drafts, generating, credits403

The app sees exactly what the canvas plays. For other files of the mascot, such as stickers or images that no canvas uses, use hosting or your own backend with your API key.

Create an app key

In Studio, open the mascot, click Get Links and open the App keys tab: name the key after the app (for example "My app for Mac"), create it and copy it. Or call the API with your API key:

curl -X POST https://api.masko.ai/v1/mascots/MASCOT_ID/app-keys \
  -H "Authorization: Bearer masko_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "My app for Mac"}'

key appears only in this response: Masko keeps a hash, never the key. A mascot can have 20 active app keys; make one per app so you can revoke them separately.

Read the latest release

The app sends its app key as a bearer token. Ask for your platform with target (apple for iPhone, iPad and Mac, android, web) and add formats=av1 for the lighter AV1 files the Masko player plays in apps. Masko-Install-Id is optional: a random UUID the installed copy keeps, so you can see how many copies are active. Nothing else about the device is recorded.

curl "https://api.masko.ai/v1/canvases/CANVAS_ID/delivery?target=apple&formats=av1" \
  -H "Authorization: Bearer masko_app_YOUR_APP_KEY" \
  -H "Masko-Install-Id: 6f0c0e5a-1f0b-4a57-9d0a-2b7c5c1d9e11"

GET /v1/canvases/{canvasId}/releases/{releaseId}/delivery returns one release in the same shape, to pin an app to it.

What a release holds

The delivery describes everything the mascot can do in the app:

  • Poses are runtimeGraph.nodes. Each has an id, a name and transparentThumbnailUrl, its still picture with a transparent background. initialNode is the pose it starts on.
  • Animations are runtimeGraph.edges. An edge from one pose to another is a move. An edge whose source and target are the same pose plays on that pose: the first one without conditions is the pose's loop, and the others play when their conditions hold, or now and then. videos holds the file for your target (av1, hevc, webm or stacked), duration its length in seconds. Edges with source: "*" have no file: they choose the pose to go to when an input is on.
  • Inputs are runtimeGraph.inputs: the names your app sends with set or fire, such as behavior::pointerHover while the pointer is over the mascot, or your own action::snack. conditions on each edge say which input plays it.
  • Capabilities, when the canvas has them, are runtimeGraph.capabilities: each behavior and action with a short name and description of what the mascot does, to show in your app's settings.

So an app lists its mascot's poses and animations from nodes and edges, and the Masko player runs the rules for it: your app only says what is happening. Canvas graphs explains every field.

Keep the files

The file links are signed and stop working after one to two days (deliveryAccess.signedUrlExpiresAt), so download the files when the delivery arrives and keep them:

  1. Name each file after its link's path, without the query: the path never changes, only the signature does.
  2. Download only the files you do not have yet.
  3. Rewrite the links in the delivery to your local file:// URLs, leave out deliveryAccess, and give that delivery to the player.
  4. Ask again later, for example at launch and every hour. The same release_id means nothing changed; a new one means a new release to download. Switch to it once every file is there.

Offline, the app keeps playing what it has. Ship the first pose's loop inside the app so the mascot appears before the first download.

See and revoke keys

GET /v1/mascots/MASCOT_ID/app-keys lists the active keys with their last_used_at and installs_7d, the installed copies that asked in the last 7 days. The App keys tab shows the same. Revoking a key stops it at once: apps that carry it keep what they downloaded and stop receiving new releases. Ship a new app version with a new key to bring them back.

curl -X DELETE https://api.masko.ai/v1/mascots/MASCOT_ID/app-keys/APP_KEY_ID \
  -H "Authorization: Bearer masko_YOUR_API_KEY"