# Masko API - Complete Documentation
Base URL: https://api.masko.ai/v1
Auth: Authorization: Bearer masko_YOUR_API_KEY
OpenAPI spec: https://api.masko.ai/v1/openapi.json
---
---url: /docs/quickstart---
# Quickstart
%% animation https://assets.masko.ai/7fced6/spark-4735/waving-hello-54937ffb-360.webm https://assets.masko.ai/7fced6/spark-4735/waving-hello-0bf2a5b3-360.mov %%
Create your first mascot and get CDN URLs in 5 minutes.
Using an AI coding agent? The [CLI](/docs/ai-agents#cli) or [MCP server](/docs/ai-agents#mcp-server) may be faster than raw API calls.
Prerequisites: You need an API key. Create one in the [Developer dashboard](https://app.masko.ai/settings/developer).
## Step 1: Create a Project
Projects group related collections together. Create one to get started.
```bash
curl -X POST https://api.masko.ai/v1/projects \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "My App" }'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/projects', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'My App' }),
});
const project = await res.json();
```
## Step 2: Create a Collection
A collection represents a single mascot character. Give it a name and a description of the character you want.
```bash
curl -X POST https://api.masko.ai/v1/collections \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Felix the Fox",
"project_id": "PROJECT_ID",
"description": "A friendly orange fox mascot wearing a blue scarf"
}'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/collections', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Felix the Fox',
project_id: 'PROJECT_ID',
description: 'A friendly orange fox mascot wearing a blue scarf',
}),
});
const collection = await res.json();
// Save collection.id for the next steps
```
## Step 3: Generate an Animation
Request a generation by specifying the type and a prompt. The API returns a job ID you can poll for status.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"prompt": "waving hello",
"duration": 3
}'
```
```javascript
const res = await fetch(
'https://api.masko.ai/v1/collections/COLLECTION_ID/generate',
{
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'animation',
prompt: 'waving hello',
duration: 3,
}),
}
);
const { job_id } = await res.json();
```
## Step 4: Check the Result
Poll the job endpoint until the status is `completed`. The response includes download URLs for all generated assets.
```bash
curl https://api.masko.ai/v1/jobs/JOB_ID \
-H "Authorization: Bearer masko_YOUR_API_KEY"
# Response:
# {
# "id": "JOB_ID",
# "status": "completed",
# "assets": [
# { "type": "video", "url": "https://..." },
# { "type": "webm", "url": "https://..." }
# ]
# }
```
```javascript
async function pollJob(jobId) {
while (true) {
const res = await fetch(
`https://api.masko.ai/v1/jobs/${jobId}`,
{
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
},
}
);
const job = await res.json();
if (job.status === 'completed') {
return job.assets;
}
if (job.status === 'failed') {
throw new Error(job.error);
}
// Wait 2 seconds before polling again
await new Promise((r) => setTimeout(r, 2000));
}
}
const assets = await pollJob(job_id);
console.log(assets);
```
Once your assets are published to the CDN, the URLs are permanent and served from `assets.masko.ai` with global edge caching.
## CLI Alternative
The same flow with the Masko CLI (great for AI agents):
```bash
npx @masko/cli login
masko projects create --name "My App"
masko mascots create --project PROJECT_ID --prompt "A friendly orange fox mascot wearing a blue scarf"
masko generate --mascot MASCOT_ID --type animation --prompt "waving hello" --duration 3 --wait
```
## Next Steps
- [Generation](/docs/generate/images) - Deep dive into image, animation, and logo generation options.
- [Canvas](/docs/canvas/build) - Build interactive state machines with your mascot.
- [AI Agents](/docs/ai-agents) - Set up MCP, CLI, or the Claude Code skill.
---
---url: /docs/authentication---
# Authentication
%% animation https://assets.masko.ai/7fced6/spark-4735/holding-key-edbf1ecd-360.webm https://assets.masko.ai/7fced6/spark-4735/holding-key-4b043910-360.mov %%
All API requests require a Bearer token in the `Authorization` header. Unauthenticated requests return a `401` error.
## API Keys
API keys follow the format `masko_{64-hex-characters}`. When you create a key, only the SHA-256 hash is stored on our servers - the raw key is shown once and cannot be retrieved later.
```bash
curl https://api.masko.ai/v1/credits \
-H "Authorization: Bearer masko_YOUR_API_KEY"
```
```javascript
const res = await fetch('https://api.masko.ai/v1/credits', {
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
},
});
const { credits } = await res.json();
```
Keep your API key secret. Do not expose it in client-side code or public repositories. If a key is compromised, revoke it immediately from the dashboard.
## Creating API Keys
Create API keys from the [Developer dashboard](/api-keys) or programmatically. Each account can have up to 10 active keys per workspace.
### Personal vs Organization Keys
API keys are scoped to a workspace:
- **Personal keys** access your personal projects and deduct from your personal credits
- **Organization keys** access the team's projects and deduct from the team's credit pool
When you switch workspaces in the dashboard, the Developer page shows keys for that workspace. Organization keys can be created by admins and owners. Any team member can use an org key.
## Rate Limits
The API enforces rate limits to ensure fair usage. If you exceed the limits, requests return a `429 Too Many Requests` response.
- **60 requests per minute** per API key
- **1,000 requests per hour** per API key
Rate limit headers are included in every response: `X-RateLimit-Remaining` and `X-RateLimit-Reset`.
If you need higher rate limits for production use, reach out to [paul@masko.ai](mailto:paul@masko.ai).
## Credits
Each generation consumes credits from your account balance. Check your balance at any time via the `/v1/credits` endpoint.
| Type | Cost |
| --- | --- |
| Image | 1 credit |
| Animation | 5 credits per second |
| Logo | 5 credits |
| Edit | 1 credit |
## Error Codes
The API uses standard HTTP status codes for error responses.
| Code | Meaning |
| --- | --- |
| `401` | Invalid or missing API key |
| `402` | Insufficient credits - top up your balance to continue |
| `403` | Access denied - you do not own this resource |
| `429` | Rate limit exceeded - wait and retry |
| `500` | Internal server error - contact support if persistent |
---
---url: /docs/ai-agents---
# AI Agent Integration
Add AI mascots to your app without leaving your coding agent. Masko works with Claude Code, Cursor, VS Code, Codex, Gemini CLI, Windsurf, Goose, Kiro, and more.
## Choose Your Integration
| Method | Best For | Setup |
|--------|----------|-------|
| [**MCP Server**](/docs/ai-tools/mcp) | Native tool calls in your agent | 30 seconds |
| [**CLI**](/docs/ai-tools/cli) | Terminal commands, any agent with bash | 1 minute |
| [**AI Skills**](/docs/ai-tools/skills) | Teach your agent Masko workflows | 2 minutes |
| **Direct API** | Custom HTTP integrations | [Quickstart](/docs/quickstart) |
## Quick Setup
The fastest way to get started depends on your tool:
```bash
claude mcp add --transport http masko "https://masko.ai/api/mcp"
claude /mcp # authenticate
```
```bash
# Add MCP server to your config (see MCP Server page for exact format)
# Then install the AI skill for best results
```
```bash
npx @masko/cli login
masko generate --mascot ID --type animation --prompt "waving" --duration 4 --wait
```
## What You Can Do
- **Create mascots** from text descriptions in 38 art styles
- **Generate images** of any pose or action (1 credit)
- **Animate from scratch** - no need to create an image first (5 credits/sec)
- **Edit images** - add accessories, change colors, seasonal variations (1 credit)
- **Build canvases** - interactive state machines with transitions between poses
- **Get instant CDN URLs** - embed in code immediately, they work as placeholders
## Direct API
For agents that prefer raw HTTP calls:
| Resource | URL |
|----------|-----|
| LLM-friendly docs | [masko.ai/llms-full.txt](https://masko.ai/llms-full.txt) |
| Doc search | `GET /api/v1/docs?q=animation` |
| OpenAPI spec | [masko.ai/api/v1/openapi.json](https://masko.ai/api/v1/openapi.json) |
In the API, mascots are called "collections" (`POST /v1/collections`). The CLI and MCP use "mascot" but call the same endpoints.
---
---url: /docs/ai-tools/mcp---
# Masko MCP Server
The Masko MCP server gives your AI coding agent native tools to create mascots, generate images, animate characters, and build interactive canvases.
Server URL: `https://masko.ai/api/mcp`
## Install
Configure your client to connect with Masko.
%% clients %%
--- Claude Code ---
Add the MCP server to your project config using the command line:
```bash
claude mcp add --scope project --transport http masko "https://masko.ai/api/mcp"
```
Alternatively, add this configuration to `.mcp.json`:
```json
{
"mcpServers": {
"masko": {
"type": "http",
"url": "https://masko.ai/api/mcp"
}
}
}
```
After configuring the MCP server, you need to authenticate. In a regular terminal (not the IDE extension) run:
```bash
claude /mcp
```
Select the **masko** server, then **Authenticate** to begin the authentication flow.
--- Cursor ---
Add this configuration to `.cursor/mcp.json`:
```json
{
"mcpServers": {
"masko": {
"url": "https://masko.ai/api/mcp"
}
}
}
```
After saving, navigate to **Settings > Cursor Settings > Tools & MCP** to verify the server is connected.
--- VS Code ---
Add this configuration to `.vscode/mcp.json`:
```json
{
"servers": {
"masko": {
"type": "http",
"url": "https://masko.ai/api/mcp"
}
}
}
```
--- Codex ---
Add the Masko MCP server to Codex:
```bash
codex mcp add masko --url https://masko.ai/api/mcp
```
Alternatively, add this configuration to `~/.codex/config.toml`:
```toml
[mcp_servers.masko]
url = "https://masko.ai/api/mcp"
```
After adding the server, enable remote MCP client support by adding this to your `~/.codex/config.toml`:
```toml
[features]
rmcp_client = true
```
Then authenticate:
```bash
codex mcp login masko
```
Run `/mcp` inside Codex to verify authentication.
--- Gemini CLI ---
Requires Gemini CLI version 0.20.2 or higher.
Add the MCP server to Gemini CLI:
```bash
gemini mcp add -t http masko https://masko.ai/api/mcp
```
Alternatively, add this configuration to `.gemini/settings.json`:
```json
{
"mcpServers": {
"masko": {
"httpUrl": "https://masko.ai/api/mcp"
}
}
}
```
After installation, start the Gemini CLI and run the following command to authenticate:
```bash
/mcp auth masko
```
--- Antigravity ---
Add this configuration to `~/.gemini/antigravity/mcp_config.json`:
```json
{
"mcpServers": {
"masko": {
"serverUrl": "https://masko.ai/api/mcp"
}
}
}
```
After saving the config, restart Antigravity. It will prompt you to complete the OAuth flow to authenticate with Masko.
If you run into authentication issues, open the command palette and run **Authentication: Remove Dynamic Authentication Providers** to clear cached credentials.
--- Windsurf ---
Requires Windsurf version 0.1.37 or higher.
Add this configuration to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"masko": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://masko.ai/api/mcp"
]
}
}
}
```
Windsurf does not currently support remote MCP servers over HTTP transport. The `mcp-remote` package acts as a proxy.
--- Goose ---
Add this configuration to `~/.config/goose/config.yaml`:
```yaml
extensions:
masko:
name: Masko
type: streamable_http
url: https://masko.ai/api/mcp
enabled: true
timeout: 300
```
--- OpenCode ---
Add this configuration to `~/.config/opencode/opencode.json`:
```json
{
"mcp": {
"masko": {
"type": "remote",
"url": "https://masko.ai/api/mcp",
"enabled": true
}
}
}
```
After adding the configuration, run the following command to authenticate:
```bash
opencode mcp auth masko
```
--- Kiro ---
Add this configuration to `.kiro/settings/mcp.json`:
```json
{
"mcpServers": {
"masko": {
"url": "https://masko.ai/api/mcp"
}
}
}
```
%% /clients %%
## Authentication
Most clients will automatically prompt you to log in during setup. This opens a browser window where you can log in to your Masko account and confirm access.
For clients that don't auto-prompt, get your API key from the [Developer dashboard](https://masko.ai/settings/developer) and add it as a header in your config.
After authentication, verify the connection by asking your agent: **"Check my Masko credit balance"** - it should call the `get_credits` tool.
## Available Tools
Once connected, your agent has 16 tools:
### Mascots
| Tool | Description |
|------|-------------|
| `create_mascot` | Create a new mascot from a text description and art style |
| `list_mascots` | List your mascots to find IDs |
| `get_mascot` | Get all poses, assets, and CDN URLs for a mascot |
### Generation
| Tool | Description |
|------|-------------|
| `generate` | Generate an image, animation, edit, or logo. Returns CDN URLs instantly |
| `generate_batch` | Generate up to 10 items at once |
| `get_job` | Check generation status. Supports `wait=true` for long-polling |
| `list_jobs` | List recent generation jobs |
### Canvas
| Tool | Description |
|------|-------------|
| `create_canvas` | Create an interactive state machine |
| `create_canvas_from_template` | One-step canvas from a pre-built template |
| `generate_all_canvas` | Generate all images and animations for a canvas |
| `list_canvas_templates` | List available templates |
### Utilities
| Tool | Description |
|------|-------------|
| `get_credits` | Check credit balance before generating |
| `list_styles` | List all 38 art styles |
| `search_docs` | Search Masko docs by keyword |
| `create_project` | Create a project to group mascots |
| `list_projects` | List your projects |
## Key Concepts
**CDN URLs are instant.** Every `generate` call returns CDN URLs before generation finishes. They serve a placeholder that swaps to the real file automatically. Embed them in code right away.
**Animation from scratch.** You don't need to generate an image first. The agent passes both an `image_prompt` (the pose) and `animation_prompt` (the motion) to create everything in one step.
**Auto-resolved sources.** When animating an existing item, the agent just passes `item_id`. The server finds the correct source image automatically.
**Credits.** Image = 1, animation = 5/sec, edit = 1, logo = 5. Animations loop by default. Background removal and size variants are free.
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Tools not showing up | Restart your editor after adding the MCP server |
| Authentication failed | Re-run the auth step for your client (see Install above) |
| Token expired | Tokens last 30 days. Re-authenticate to get a new one |
| Insufficient credits | Call `get_credits` to check. Top up at masko.ai |
| Windsurf not connecting | Ensure `mcp-remote` is installed (`npx -y mcp-remote`) |
| Codex not connecting | Add `rmcp_client = true` to `[features]` in config.toml |
---
---url: /docs/ai-tools/cli---
# Masko CLI
Generate mascots, images, animations, and interactive canvases from the command line. Works standalone or with any AI agent that can run terminal commands.
## Install
```bash
npx @masko/cli login
```
Your browser opens, you log in with your Masko account, and the API key is saved automatically. No key to copy-paste.
Or set the key manually:
```bash
export MASKO_API_KEY=masko_YOUR_API_KEY
```
Get your API key from the [Developer dashboard](https://masko.ai/settings/developer).
## Quick Start
```bash
# Check your credits (image = 1, animation = 5/sec)
masko credits
# List art styles
masko styles
# Create a project and mascot
masko projects create --name "My App"
masko mascots create --project PROJECT_ID --prompt "a friendly pixel art robot" --style pixel
# Generate an image
masko generate --mascot MASCOT_ID --type image --prompt "waving hello" --wait
# Generate an animation from scratch (creates image + animates in one step)
masko generate --mascot MASCOT_ID --type animation --prompt "waving happily" --duration 4 --wait
# Animate an existing pose (just pass the item ID)
masko generate --mascot MASCOT_ID --type animation --item ITEM_ID --prompt "gentle breathing" --duration 4 --wait
```
After generating an image, the CLI prints the exact command to animate it. Just copy and run.
## Commands
### Authentication
```bash
masko login # Open browser, log in, key saved automatically
```
### Mascots
```bash
masko mascots create # Create a mascot
--project ID # Project ID (required)
--prompt TEXT # Character description
--style NAME # Art style (run masko styles to see options)
masko mascots list # List all mascots
--project ID # Filter by project
masko mascots get ID # Get mascot details, items, and CDN URLs
```
### Generation
```bash
masko generate # Generate image/animation/edit/logo
--mascot ID # Mascot ID (required)
--type TYPE # image | animation | edit | logo
--prompt TEXT # What to generate (sets both pose + motion for animations)
--image-prompt TEXT # Pose description (animation from scratch)
--animation-prompt TEXT # Motion description (animation from scratch)
--item ID # Animate/edit existing item (auto-resolves source)
--duration N # Animation seconds (3-10, default 4)
--wait # Wait for completion
--json # Raw JSON output
--name NAME # Name for the pose (e.g. "wave", "idle")
```
### Jobs
```bash
masko jobs get ID # Check job status
--wait # Long-poll until completion (up to 120s)
--timeout N # Custom timeout in seconds
masko jobs list # List recent jobs
--mascot ID # Filter by mascot
--status STATUS # pending | processing | completed | failed
```
### Canvas
```bash
masko templates # List available canvas templates
masko canvas from-template # Create canvas from a template
--mascot ID --template ID
masko canvas generate-all # Generate all canvas animations
--mascot ID --canvas ID
--duration N # Seconds per animation (default 4)
```
### Utilities
```bash
masko credits # Check credit balance
masko styles # List all 38 art styles
masko projects create --name X # Create a project
masko projects list # List projects
```
## Output Formats
By default, the CLI shows human-readable output. Add `--json` for raw JSON (useful for piping or when AI agents parse the output):
```bash
# Human-readable
masko credits
# Total: 14678
# Subscription: 0
# Top-up: 14678
# JSON
masko credits --json
# {"data":{"subscription":0,"topup":14678,"total":14678}}
```
## CDN URLs
Every `generate` command returns CDN URLs immediately - before the file is ready. These URLs serve a branded placeholder that swaps to the real file automatically when generation completes.
```bash
masko generate --mascot ID --type image --prompt "waving" --wait
# Output:
# CDN URLs (usable immediately):
# image: https://assets.masko.ai/abc123/my-mascot/wave-d017.png
# transparent_image: https://assets.masko.ai/abc123/my-mascot/wave-1b2c.png
```
Embed these URLs in your code right away. No need to wait.
## Animation Tips
**From scratch** (21 credits for 4s): `--prompt` sets both the pose and the motion. Use `--image-prompt` and `--animation-prompt` separately if you want different descriptions.
```bash
# Simple (same description for pose and motion)
masko generate --mascot ID --type animation --prompt "waving hello" --duration 4 --wait
# Specific (different pose vs motion)
masko generate --mascot ID --type animation \
--image-prompt "standing with right hand raised" \
--animation-prompt "waving hand back and forth" \
--duration 4 --wait
```
**From existing image** (20 credits, saves 1): Pass `--item` and the source image is auto-resolved.
```bash
masko generate --mascot ID --type animation --item ITEM_ID --prompt "breathing gently" --duration 4 --wait
```
Animations loop by default. Pass `--loop false` to disable.
## Credit Costs
| Type | Cost |
|------|------|
| Image | 1 credit |
| Animation | 5 credits/second |
| Edit | 1 credit |
| Logo | 5 credits |
Free: background removal, format conversion (webm/hevc), size variants.
---
---url: /docs/ai-tools/skills---
# AI Skills
AI skills are instruction files that teach your coding agent how to use Masko. Once installed, your agent knows all the commands, workflows, credit costs, and best practices - no need to explain anything.
## Install for Your Tool
```bash
# Copy the skill to your project
cp -r packages/skill/masko .claude/skills/masko
# Or create CLAUDE.md with Masko instructions at project root
```
```bash
# Create .cursor/rules/masko.mdc
# See content below
```
```bash
# Create .github/copilot-instructions.md
# Or .github/instructions/masko.instructions.md
```
```bash
# Add to AGENTS.md at project root
# Codex also reads CLAUDE.md as fallback
```
```bash
# Add to GEMINI.md at project root
```
```bash
# Add to .windsurfrules at project root
# Or .windsurf/rules/masko.md
```
```bash
# Add to .goosehints at project root
```
```bash
# Create .kiro/steering/masko.md
```
## Skill Content
Copy this into the file for your tool. For Claude Code, use the full SKILL.md from `packages/skill/masko/`. For other tools, use this condensed version:
```markdown
# Masko - AI Mascot Generation
Generate mascots, animations, logos, and interactive canvases via the Masko API.
## Setup
MCP (recommended): claude mcp add --transport http masko "https://masko.ai/api/mcp"
CLI: npx @masko/cli login
API key: https://masko.ai/settings/developer
## CLI Commands
masko credits # Check balance
masko styles # List 38 art styles
masko mascots create --project ID --prompt "description" --style pixel
masko generate --mascot ID --type image --prompt "waving hello" --wait
masko generate --mascot ID --type animation --prompt "waving" --duration 4 --wait
masko generate --mascot ID --type animation --item ITEM_ID --prompt "breathing" --duration 4 --wait
masko generate --mascot ID --type edit --item ITEM_ID --prompt "add a santa hat" --wait
masko jobs get JOB_ID --wait
## Key Facts
- Animation from scratch: --type animation + --prompt creates image + animates in one step
- Animate existing: --item ITEM_ID auto-resolves the source image
- CDN URLs returned immediately, work as placeholders until ready
- Animations loop by default
- Credits: image=1, animation=5/sec, edit=1, logo=5
- Free: background removal, format conversion, size variants
## API (direct HTTP)
Base URL: https://api.masko.ai/v1
Auth: Authorization: Bearer masko_YOUR_API_KEY
Docs: https://masko.ai/llms-full.txt
OpenAPI: https://masko.ai/api/v1/openapi.json
In the API, mascots are called "collections" (POST /v1/collections).
```
## Cursor-Specific Format
Cursor uses `.mdc` files with YAML frontmatter. Create `.cursor/rules/masko.mdc`:
```markdown
---
description: "Use Masko to generate AI mascots, animations, and interactive canvases"
alwaysApply: false
---
(paste the skill content above)
```
Setting `alwaysApply: false` with a `description` means Cursor's agent will include these rules only when it thinks they're relevant (when you mention mascots, animations, etc.).
## VS Code / Copilot Format
For path-specific instructions, create `.github/instructions/masko.instructions.md`:
```markdown
---
applyTo: "**/*"
---
(paste the skill content above)
```
Or add to `.github/copilot-instructions.md` for always-on instructions.
## Kiro Format
Kiro uses a steering directory. Create `.kiro/steering/masko.md`:
```markdown
(paste the skill content above)
```
## What the Skill Teaches
Once installed, your agent will know:
- **How to create a mascot** from a text description and art style
- **How to generate images** with prompts for poses and actions
- **How to animate** from scratch or from an existing image
- **How to use the CLI** with all flags and options
- **Credit costs** so it checks balance before generating
- **CDN URL behavior** so it embeds URLs immediately
- **Canvas workflows** for interactive state machines
- **All 38 art styles** available for generation
---
---url: /docs/how-mascots-work---
# How Mascots Work
Understanding the data model behind Masko's API.
## The Hierarchy
Every mascot in Masko follows a four-level hierarchy. Projects group your work, collections define characters, items represent poses or actions, and assets are the actual files.
```text
Project
└── Collection (= one mascot character)
├── Item: "Wave"
│ ├── Asset: image (pose.png)
│ ├── Asset: transparent_image (pose_nobg.png)
│ ├── Asset: video (wave.mp4)
│ ├── Asset: webm (wave.webm)
│ └── Asset: hevc (wave.mov)
├── Item: "Idle"
│ └── ...
└── Item: "Thumbs Up"
└── ...
```
## Collections (= Mascots)
A collection represents a single mascot character. In the API, mascots are stored as collections with `type: "mascot"`. The CLI and MCP server use the friendlier term "mascot" (`masko mascots create`, `create_mascot`), but they call the same API endpoints (`/v1/collections`).
Each collection holds the character's prompt (the text description used for generation), reference images (up to 6 examples of what the character looks like), and a style card (an auto-extracted summary of the character's visual traits).
Collections also store settings like animation sizes, CDN configuration, and the caution list used to maintain consistency across generations.
## Items
An item is a single pose or action for the mascot - like "Wave", "Idle", or "Thumbs Up". Each item has a name, a prompt describing the action, and a type (`image`, `animation`, or `logo`).
When you generate an image for an item, the API combines the collection's character prompt with the item's action prompt to produce a consistent result.
## Assets
An asset is a single generated file. Each item can have multiple assets of different types:
| Type | Format | Description |
| --- | --- | --- |
| `image` | .png | Original generated image with background |
| `transparent_image` | .png | Background removed, transparent PNG |
| `video` | .mp4 | Animated version (H.264) |
| `webm` | .webm | Web-optimized format with alpha channel |
| `hevc` | .mov | Apple-compatible format with alpha channel |
| `stacked_video` | .mp4 | Stacked layout for custom alpha compositing |
## Generation Graph
Assets are connected through a generation graph. When you generate an animation, the API first creates an image, then removes the background, then animates it, then converts to web formats. Each step links back to its source via the `generation_links` table.
```text
image (.png)
└── transparent_image (.png) [role: source]
└── video (.mp4) [role: source, end_frame]
├── webm (.webm) [role: source]
└── hevc (.mov) [role: source]
```
The `role` field on each link indicates the relationship. `source` means "this asset was derived from that asset". `end_frame` is used for animations where a final pose image guides the motion.
## Reference Images & Style Cards
Each collection can have up to 6 reference images. These are examples of what the mascot looks like - they guide every generation to maintain visual consistency.
When you first generate an image, Masko automatically extracts a style card from the references. The style card is a structured summary of the character's visual traits (colors, proportions, line style, shading) that gets injected into every prompt. If you change the references, the style card is cleared and re-extracted on the next generation.
The caution list accumulates notes from post-generation validation. If a generated image drifts from the style (wrong color, missing detail), the issue is logged and injected into future prompts to prevent recurrence.
## Size Variants
Animations can be generated at multiple sizes simultaneously. Set the `animation_sizes` field on a collection to define which resolutions you need (e.g. 512x512, 256x256, 128x128). Resizing is free - you only pay credits for the base animation generation.
---
---url: /docs/credits---
# Credits & Pricing
Understanding costs and optimizing your credit usage.
## Credit Costs
| Operation | Credits | Notes |
| --- | --- | --- |
| Image generation | 1 | Per image |
| Animation | 5 / second | 4-second animation = 20 credits |
| Logo generation | 5 | Per logo |
| Image edit | 1 | Inpainting or style transfer |
| Reverse (undo) | 0 | Free |
## What's Free
These operations cost zero credits:
- `analyze-image` - AI analysis of an uploaded image
- `analyze-url` - Website analysis and mascot suggestions
- `suggest-actions` - AI-suggested poses for a collection
- Style card extraction (automatic on first generation)
- Background removal (included in generation pipeline)
- Format conversion (webm, hevc from video)
- Size variants (resizing animations to multiple resolutions)
## How Credits Work
Credits are deducted upfront when a generation job starts. If the job fails, credits are automatically refunded to your account.
Your account has two credit balances: subscription credits (replenished each billing cycle) and top-up credits (purchased separately, never expire). Subscription credits are used first.
## Checking Your Balance
```bash
curl https://api.masko.ai/v1/credits \
-H "Authorization: Bearer masko_YOUR_API_KEY"
```
```javascript
const res = await fetch('https://api.masko.ai/v1/credits', {
headers: { 'Authorization': 'Bearer masko_YOUR_API_KEY' }
});
const data = await res.json();
console.log(data);
```
```json
{
"subscription_credits": 450,
"topup_credits": 100,
"total": 550
}
```
## Common Workflow Costs
| Workflow | Credits |
| --- | --- |
| 1 image (with bg removal + formats) | 1 |
| 1 animation (4s, includes image + bg removal) | 21 |
| 8 poses (images only) | 8 |
| Full canvas (4 states, 16 animations at 4s) | ~400 |
## Insufficient Credits
If you don't have enough credits, the API returns a `402 Payment Required` response:
```json
{
"error": "Insufficient credits",
"required": 21,
"available": 5
}
```
Logo generation requires a Pro plan or higher. If you're on the Free or Starter plan, the API returns a `403 Forbidden` response instead.
---
---url: /docs/create/from-text---
# Create from Text
Describe your mascot and pick a style - the API generates the reference image.
## Two Approaches
You can either preview multiple variations first (recommended) or create a collection directly in a single call. The preview approach costs 1 credit and gives you 4 options to choose from. Direct creation auto-generates one reference and builds the collection immediately.
## Step 1: Browse Styles
GET /v1/styles
Fetch the list of available art styles. Each style has a preset ID you can pass to the generation endpoint.
```bash
curl https://api.masko.ai/v1/styles \
-H "Authorization: Bearer masko_YOUR_API_KEY"
```
```javascript
const res = await fetch('https://api.masko.ai/v1/styles', {
headers: { 'Authorization': 'Bearer masko_YOUR_API_KEY' }
});
const { styles } = await res.json();
```
```json
{
"styles": [
{ "id": "3d-render", "name": "3D Render", "preview_url": "..." },
{ "id": "pixel-art", "name": "Pixel Art", "preview_url": "..." },
{ "id": "flat-vector", "name": "Flat Vector", "preview_url": "..." }
]
}
```
## Step 2: Generate Previews
POST /v1/generate/preview
Generate multiple preview images from your text description. This lets you pick the best variation before committing to a collection.
```bash
curl -X POST https://api.masko.ai/v1/generate/preview \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A friendly orange fox wearing a space helmet",
"preset_id": "3d-render",
"count": 4
}'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/generate/preview', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'A friendly orange fox wearing a space helmet',
preset_id: '3d-render',
count: 4
})
});
const { images } = await res.json();
```
```json
{
"images": [
{ "url": "https://api.masko.ai/v1/previews/preview_0.png" },
{ "url": "https://api.masko.ai/v1/previews/preview_1.png" },
{ "url": "https://api.masko.ai/v1/previews/preview_2.png" },
{ "url": "https://api.masko.ai/v1/previews/preview_3.png" }
]
}
```
## Step 3: Create Collection
POST /v1/collections
Take the preview URL you like best and use it as a reference image to create your collection.
```bash
curl -X POST https://api.masko.ai/v1/collections \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Astro Fox",
"project_id": "PROJECT_ID",
"prompt": "A friendly orange fox wearing a space helmet",
"reference_image_urls": [
"https://api.masko.ai/v1/previews/preview_2.png"
]
}'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/collections', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Astro Fox',
project_id: 'PROJECT_ID',
prompt: 'A friendly orange fox wearing a space helmet',
reference_image_urls: [images[2].url]
})
});
const { collection } = await res.json();
console.log(collection.id); // Use this for generation
```
```json
{
"collection": {
"id": "col_abc123",
"name": "Astro Fox",
"prompt": "A friendly orange fox wearing a space helmet",
"cdn_enabled": true,
"created_at": "2026-03-28T10:00:00Z"
}
}
```
CDN publishing is enabled by default on new collections. You can also set `animation_sizes` at creation time to define which resolutions to generate (e.g. `["512x512", "256x256", "128x128"]`).
## Shortcut: Direct Creation
If you don't need to preview, you can create a collection in one call. The API auto-generates a reference image (1 credit) from your prompt. Optionally pass a `style` to apply a visual preset.
```bash
curl -X POST https://api.masko.ai/v1/collections \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Astro Fox",
"project_id": "PROJECT_ID",
"prompt": "A friendly orange fox wearing a space helmet",
"style": "3d"
}'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/collections', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Astro Fox',
project_id: 'PROJECT_ID',
prompt: 'A friendly orange fox wearing a space helmet',
style: '3d'
})
});
```
## Next Steps
- [Generate Images](/docs/generation) - Create poses and actions for your mascot.
- [Generate Animations](/docs/generation) - Bring your mascot to life with animated sequences.
---
---url: /docs/create/from-image---
# Create from Image
Upload your existing mascot design and let the API auto-detect the character.
## Upload Your Image
POST /v1/upload
You can upload an image either as a multipart form upload or by providing a URL to an existing image.
### Multipart Upload
```bash
curl -X POST https://api.masko.ai/v1/upload \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-F "file=@mascot.png"
```
```javascript
const formData = new FormData();
formData.append('file', fileBlob, 'mascot.png');
const res = await fetch('https://api.masko.ai/v1/upload', {
method: 'POST',
headers: { 'Authorization': 'Bearer masko_YOUR_API_KEY' },
body: formData
});
const { asset_id } = await res.json();
```
### URL Upload
```bash
curl -X POST https://api.masko.ai/v1/upload \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com/my-mascot.png" }'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/upload', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com/my-mascot.png'
})
});
const { asset_id } = await res.json();
```
```json
{
"asset_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```
## Create Collection
POST /v1/collections
Pass the `asset_id` from the upload step as a reference. You don't need to provide a `prompt` - the image itself is the reference, and the API extracts the character description automatically. If you omit `name`, it's also auto-detected from the image.
```bash
curl -X POST https://api.masko.ai/v1/collections \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"project_id": "PROJECT_ID",
"reference_asset_ids": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]
}'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/collections', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
project_id: 'PROJECT_ID',
reference_asset_ids: [asset_id]
})
});
const { collection } = await res.json();
// collection.name is auto-detected from the image
// collection.prompt is auto-generated from the visual analysis
```
You can also pass `reference_image_urls` with public URLs instead of uploading first. Both work - use `reference_asset_ids` for uploaded files, `reference_image_urls` for external URLs.
## How Auto-Analysis Works
When you create a collection from an image, Masko uses AI vision to analyze the reference and extract a character name and detailed prompt. This analysis is free and happens automatically. The extracted prompt describes the character's visual traits so future generations stay consistent.
## Adding More References
POST /v1/collections/:id/references
You can add up to 6 reference images to a collection. More references means better consistency across generated poses.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/references \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"asset_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}'
```
```javascript
await fetch(`https://api.masko.ai/v1/collections/${collectionId}/references`, {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
asset_id: assetId // from POST /upload
})
});
```
You can also pass a `url` instead of `asset_id` if you have a public image URL.
When references change, the style card is cleared and will be re-extracted on the next generation to reflect the updated visual direction.
## Best Practices
- Use 3-4 reference images showing different angles for best consistency
- Keep a consistent art style across all references - don't mix 3D and flat vector
- Use high-resolution images (1024x1024 or larger recommended)
- White or transparent backgrounds work best - the AI focuses on the character, not the scene
---
---url: /docs/create/from-website---
# Create from Website
Analyze a website to get AI-generated mascot suggestions based on the brand.
## Analyze a URL
POST /v1/analyze-url
Send a website URL and the API will screenshot the page, extract brand colors, analyze the visual identity, and suggest mascot concepts that match the brand. This endpoint is free.
```bash
curl -X POST https://api.masko.ai/v1/analyze-url \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com" }'
```
```javascript
const res = await fetch('https://api.masko.ai/v1/analyze-url', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ url: 'https://example.com' })
});
const { suggestions } = await res.json();
```
```json
{
"brand": {
"name": "Example Corp",
"colors": ["#2563eb", "#1e40af", "#f8fafc"],
"industry": "Developer Tools"
},
"suggestions": [
{
"name": "Codey",
"prompt": "A friendly blue robot with rounded features...",
"style": "3d-render"
},
{
"name": "Buildy",
"prompt": "A cheerful construction worker hamster...",
"style": "flat-vector"
}
]
}
```
## Use Suggestions
Take a suggestion from the response and pass its prompt and style to create a collection. You can use the direct creation shortcut to do it in one call.
```bash
curl -X POST https://api.masko.ai/v1/collections \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Codey",
"project_id": "PROJECT_ID",
"prompt": "A friendly blue robot with rounded features...",
"style": "3d"
}'
```
```javascript
const suggestion = suggestions[0];
const res = await fetch('https://api.masko.ai/v1/collections', {
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: suggestion.name,
project_id: 'PROJECT_ID',
prompt: suggestion.prompt,
style: suggestion.style
})
});
```
## When to Use This
Choose the right creation method for your use case:
- **From website** - You have a brand but no mascot idea yet. The AI analyzes the site and suggests characters that match the visual identity.
- **From text** - You already know what you want. Describe the character, pick a style, and generate previews.
- **From image** - You have existing artwork. Upload it and the API auto-detects the character for consistent new poses.
---
---url: /docs/generate/images---
# Images & Poses
Generate static mascot images from text prompts. Each image costs 1 credit and produces both a full image and a transparent (background-removed) variant.
POST /v1/collections/:id/generate
## Generate an Image
Send a `type: "image"` request with a `name` for the item and an `image_prompt` describing the pose. A new item is created in your collection with pending image and transparent_image assets.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "image",
"name": "Waving hello",
"image_prompt": "waving hello with a friendly smile, one arm raised"
}'
```
```json
{
"data": {
"job_id": "job_abc123",
"status": "pending",
"type": "image",
"item_id": "item_def456",
"item_name": "Waving hello",
"estimated_cost": 1,
"asset_ids": {
"image": "ast_img_001",
"transparent_image": "ast_img_002"
},
"urls": {
"image": "https://assets.masko.ai/u/felix-the-fox/waving-hello-a1b2c3.png",
"transparent_image": "https://assets.masko.ai/u/felix-the-fox/waving-hello-d4e5f6.png"
}
},
"poll": "/v1/jobs/job_abc123"
}
```
## Edit an Image
Modify an existing image with natural language instructions. Pass `type: "edit"` along with `source_image_asset_id` and `edit_instructions`. The edit creates new assets on the same item. Costs **1 credit**.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "edit",
"item_id": "item_def456",
"source_image_asset_id": "ast_img_001",
"edit_instructions": "Add a party hat and confetti falling around"
}'
```
```json
{
"data": {
"job_id": "job_edit789",
"status": "pending",
"type": "edit",
"item_id": "item_def456",
"item_name": "Waving hello",
"estimated_cost": 1,
"asset_ids": {
"image": "ast_img_010",
"transparent_image": "ast_img_011"
},
"urls": {
"image": "https://assets.masko.ai/u/felix-the-fox/waving-hello-g7h8i9.png",
"transparent_image": "https://assets.masko.ai/u/felix-the-fox/waving-hello-j0k1l2.png"
}
},
"poll": "/v1/jobs/job_edit789"
}
```
## Regenerate
To regenerate an existing item, pass the same `item_id` with a new `image_prompt`. The endpoint creates fresh assets under the same item each time. Previous assets remain accessible - nothing is overwritten.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "image",
"item_id": "item_def456",
"image_prompt": "waving hello with both arms raised high"
}'
```
## Style Consistency
Masko keeps your mascot looking consistent across all generated images using two mechanisms:
- **Reference images** - Up to 6 images pinned as references in your collection. Every generation includes these as visual context so the AI matches the character's appearance.
- **Style card** - Automatically extracted from your references on the first generation. The style card captures defining traits like color palette, proportions, and design style, then injects them into every prompt.
You do not need to configure either of these manually. Add reference images via the [references endpoint](/docs/reference), and the style card is generated lazily when you first run a generation.
If your character looks different across generations, add 2-3 reference images showing the character from different angles. The style card will recalculate automatically when references change.
## Image vs Animation
Use **images** when you need a static pose - profile pictures, thumbnails, marketing assets, or any context where motion is not needed. Images cost 1 credit and generate in a few seconds.
Use **animations** when you need movement - idle loops, transitions between states, reactions, or interactive behaviors. Animations start at 16 credits (3 seconds) and take longer to generate. See the [Animations guide](/docs/generate/animations) for details.
---
---url: /docs/generate/animations---
# Animations
%% animation https://assets.masko.ai/7fced6/spark-4735/painting-7a826736-360.webm https://assets.masko.ai/7fced6/spark-4735/painting-76a264c3-360.mov %%
Generate animated mascot videos from scratch or from existing images. All animation types use the same generate endpoint with `type: "animation"`.
POST /v1/collections/:id/generate
## Image + Animation (New)
Generate a new image and animate it in one request. Provide both an `image_prompt` (for the pose) and an `animation_prompt` (for the motion). This costs 1 credit for the image plus 5 credits per second of video - a 4-second animation costs **21 credits** total.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Idle breathing",
"image_prompt": "standing relaxed with arms at sides",
"animation_prompt": "gentle breathing motion, subtle body sway",
"duration": 4,
"loop": true
}'
```
```json
{
"data": {
"job_id": "job_anim_001",
"status": "pending",
"type": "animation",
"item_id": "item_anim_100",
"item_name": "Idle breathing",
"estimated_cost": 21,
"asset_ids": {
"image": "ast_img_050",
"transparent_image": "ast_img_051",
"video": "ast_vid_052",
"webm": "ast_vid_053",
"hevc": "ast_vid_054"
},
"urls": {
"image": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-a1b2.png",
"transparent_image": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-c3d4.png",
"video": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-e5f6.mp4",
"webm": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-g7h8.webm",
"hevc": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-i9j0.mov"
}
},
"poll": "/v1/jobs/job_anim_001"
}
```
## Animate Existing Image
Animate an image you already have by passing `source_image_asset_id`. This skips image generation, so you only pay for the video - **20 credits** for 4 seconds.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Waving animated",
"source_image_asset_id": "ast_img_001",
"animation_prompt": "waving hello with smooth arm motion",
"duration": 4,
"loop": true
}'
```
```json
{
"data": {
"job_id": "job_anim_002",
"status": "pending",
"type": "animation",
"item_id": "item_anim_101",
"item_name": "Waving animated",
"estimated_cost": 20,
"asset_ids": {
"video": "ast_vid_060",
"webm": "ast_vid_061",
"hevc": "ast_vid_062"
},
"urls": {
"video": "https://assets.masko.ai/u/felix-the-fox/waving-animated-a1b2.mp4",
"webm": "https://assets.masko.ai/u/felix-the-fox/waving-animated-c3d4.webm",
"hevc": "https://assets.masko.ai/u/felix-the-fox/waving-animated-e5f6.mov"
}
},
"poll": "/v1/jobs/job_anim_002"
}
```
## Transitions
Create a transition between two poses by providing both `source_image_asset_id` and `end_image_asset_id`. Transitions automatically set `loop: false` since they play once between two states. Costs **20 credits** for 4 seconds.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Idle to Wave",
"source_image_asset_id": "ast_img_idle",
"end_image_asset_id": "ast_img_wave",
"animation_prompt": "smoothly transitioning from idle stance to waving",
"duration": 4
}'
```
## Auto-Reverse
When creating a transition, set `auto_reverse: true` to automatically generate the return transition (B to A) at **0 extra credits**. The response includes a `reverse_job` with its own job ID and asset IDs.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Idle to Wave",
"source_image_asset_id": "ast_img_idle",
"end_image_asset_id": "ast_img_wave",
"animation_prompt": "transitioning from idle to waving",
"auto_reverse": true,
"reverse_name": "Wave to Idle",
"duration": 4
}'
```
```json
{
"data": {
"job_id": "job_fwd_001",
"status": "pending",
"type": "animation",
"item_id": "item_fwd_100",
"item_name": "Idle to Wave",
"estimated_cost": 20,
"asset_ids": {
"video": "ast_vid_070",
"webm": "ast_vid_071",
"hevc": "ast_vid_072"
},
"urls": { ... },
"reverse_job": {
"job_id": "job_rev_002",
"item_id": "item_rev_101",
"status": "pending",
"cost": 0,
"asset_ids": {
"video": "ast_vid_080",
"webm": "ast_vid_081",
"hevc": "ast_vid_082"
}
}
},
"poll": "/v1/jobs/job_fwd_001"
}
```
Auto-reverse is essential for canvas transitions. When building a state machine, every A-to-B transition needs a matching B-to-A. Use auto_reverse to get both for the price of one.
## Duration & Looping
The `duration` field accepts values from **3 to 10 seconds**. Default is 4 seconds. The cost formula is `5 x duration` credits for the video portion.
The `loop` field defaults to `true` for standard animations and is automatically set to `false` for transitions (when `end_image_asset_id` is provided). Looping animations seamlessly repeat; non-looping animations play once and hold the last frame.
## Output Formats
Every animation produces multiple format variants optimized for different platforms:
| Type | Format | Use Case |
| --- | --- | --- |
| `video` | MP4 (H.264) | Universal fallback, opaque background |
| `webm` | WebM (VP9) | Transparent video for Chrome, Firefox, Edge |
| `hevc` | MOV (HEVC + Alpha) | Transparent video for Safari, iOS, macOS |
| `stacked_video` | MP4 (stacked) | Transparent video for Android (color + alpha stacked vertically) |
## Size Variants
By default, animations are generated at full resolution. You can configure a collection to automatically produce smaller size variants for each animation - useful for responsive layouts, thumbnails, or mobile-optimized assets.
PATCH /v1/collections/:id/settings
```bash
curl -X PATCH https://api.masko.ai/v1/collections/COL_ID/settings \
-H "Authorization: Bearer masko_..." \
-H "Content-Type: application/json" \
-d '{
"publish_params": {
"animation_sizes": {
"enabled": true,
"sizes": [480, 360, 240]
}
}
}'
```
Available sizes are `720`, `480`, `360`, and `240` pixels. When enabled, every new animation automatically generates resized variants alongside the original. Existing animations in the collection are also resized retroactively.
### Instant CDN URLs for Size Variants
When generating an animation, pass the `sizes` array to get pre-allocated CDN URLs for specific size variants immediately in the response:
```bash
curl -X POST https://api.masko.ai/v1/collections/COL_ID/generate \
-H "Authorization: Bearer masko_..." \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "wave",
"image_prompt": "standing with a smile",
"animation_prompt": "waving hello",
"duration": 3,
"sizes": [480]
}'
```
The response includes both original and variant URLs:
```json
{
"urls": {
"webm": "https://assets.masko.ai/.../wave.webm",
"hevc": "https://assets.masko.ai/.../wave.mov",
"webm_480": "https://assets.masko.ai/.../wave-480.webm",
"hevc_480": "https://assets.masko.ai/.../wave-480.mov",
"stacked_video_480": "https://assets.masko.ai/.../wave-480.mp4"
}
}
```
The `sizes` parameter is a filter - it only returns URLs for sizes that are enabled in the collection settings. If you request `sizes: [720]` but the collection only has `[480, 360]` configured, no 720 URLs are returned.
All variant URLs serve placeholders immediately and are replaced with the real resized files when the size variant workflow completes. Poll the job to check `size_variants.status`.
Since `sizes` returns CDN URLs directly in the generate response, you can embed them in your app immediately without waiting for the job to finish or making a second API call. This is the fastest way to wire up responsive animations.
## Cost Reference
Summary of animation costs at the default 4-second duration:
| Operation | Formula | 4s Cost |
| --- | --- | --- |
| New image + animation | 1 + (5 x duration) | 21 credits |
| Animate existing image | 5 x duration | 20 credits |
| Transition (A to B) | 5 x duration | 20 credits |
| Auto-reverse (B to A) | Free | 0 credits |
---
---url: /docs/generate/batch---
# Batch Generation & AI Suggestions
Generate multiple items in a single API call, and use AI vision to get smart action suggestions for your mascot.
## Batch Generation
Send up to **10 generation requests** in a single call. Each item in the `requests` array follows the same format as the single generate endpoint. All requests run in parallel.
POST /v1/collections/:id/generate-batch
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate-batch \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{
"type": "image",
"name": "Waving",
"image_prompt": "waving hello with a friendly smile"
},
{
"type": "image",
"name": "Thinking",
"image_prompt": "hand on chin, looking up thoughtfully"
},
{
"type": "animation",
"name": "Celebrating",
"image_prompt": "jumping with arms raised in celebration",
"animation_prompt": "jumping up and down excitedly, confetti motion",
"duration": 4,
"loop": true
}
]
}'
```
```json
{
"data": {
"jobs": [
{
"job_id": "job_batch_001",
"item_id": "item_b1",
"item_name": "Waving",
"status": "pending",
"estimated_cost": 1,
"asset_ids": { "image": "ast_001", "transparent_image": "ast_002" },
"urls": { "image": "https://assets.masko.ai/u/.../waving-a1b2.png", ... }
},
{
"job_id": "job_batch_002",
"item_id": "item_b2",
"item_name": "Thinking",
"status": "pending",
"estimated_cost": 1,
"asset_ids": { "image": "ast_003", "transparent_image": "ast_004" },
"urls": { ... }
},
{
"job_id": "job_batch_003",
"item_id": "item_b3",
"item_name": "Celebrating",
"status": "pending",
"estimated_cost": 21,
"asset_ids": { "image": "ast_005", "video": "ast_006", "webm": "ast_007", "hevc": "ast_008" },
"urls": { ... }
}
],
"total_cost": 23
}
}
```
## When to Batch vs Sequential
Use **batch** when you know all the items upfront - for example, generating a full set of poses for a new mascot. All items are created and queued in parallel, which is faster than sending individual requests.
Use **sequential requests** when each generation depends on the previous result - for example, generating an image first, then animating it with `source_image_asset_id`. You need the first job to complete before starting the second.
## AI Action Suggestions
Ask the AI to suggest action poses for your mascot. The endpoint analyzes your mascot's reference images (or the first completed image in the collection) and returns 6-8 action names that suit the character. This is **free** - no credits are deducted.
POST /v1/collections/:id/suggest-actions
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/suggest-actions \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
```
```json
{
"data": {
"suggestions": [
"Wave Hello",
"Thumbs Up",
"Thinking",
"Celebrate",
"Point Right",
"Sleeping",
"Running",
"Confused"
]
}
}
```
Suggestions automatically exclude items that already exist in the collection, so you can call it repeatedly as you build out your pose library.
Use the suggestion names directly as `name` values in a batch generation request. The AI picks names that also work well as image prompts.
---
---url: /docs/generate/cdn---
# CDN URLs & Size Variants
Every generation returns CDN URLs immediately, before the assets finish generating. You can embed these URLs in your app right away - they work from the moment you receive them.
## How Instant CDN URLs Work
When you call the generate endpoint, Masko uploads a branded placeholder to the CDN path and returns the URL in the response. Your app can start using this URL immediately. Once generation completes, the real asset file replaces the placeholder at the same URL - seamlessly, with no URL change needed on your side.
This means you can build your UI, set up image tags, and configure video players before any generation finishes. The placeholder is a lightweight branded image that signals "generating" to users.
CDN URLs serve a branded Masko placeholder until generation completes. No broken images, no loading spinners - just a smooth transition from placeholder to final asset.
## URL Format
CDN URLs follow this structure:
```text
https://assets.masko.ai/{user_prefix}/{collection_slug}/{item_slug}-{hash}.{ext}
Example:
https://assets.masko.ai/u/felix-the-fox/waving-hello-a1b2c3d4.png
```
- **user_prefix** - Your account prefix (e.g. `u`), set automatically.
- **collection_slug** - Derived from the collection name. Can be changed via the cdn-slug endpoint.
- **item_slug** - Derived from the item name when created.
- **hash** - Short unique hash to prevent collisions.
- **ext** - File extension based on asset type (png, mp4, webm, mov).
## Size Variants
Configure `animation_sizes` in the collection settings to generate pre-rendered size variants. Size variants are **free** - no extra credits.
Size variant URLs append the resolution suffix before the extension:
```text
# Original (full resolution)
https://assets.masko.ai/u/felix-the-fox/waving-a1b2.webm
# 480px variant
https://assets.masko.ai/u/felix-the-fox/waving-c3d4-480.webm
# 360px variant
https://assets.masko.ai/u/felix-the-fox/waving-e5f6-360.webm
```
### Get variant URLs instantly
Pass `sizes` in the generate request to get pre-allocated CDN URLs for specific variants:
```json
{
"type": "animation",
"name": "wave",
"animation_prompt": "waving hello",
"sizes": [480, 360]
}
```
The response `urls` object includes keys like `webm_480`, `hevc_480` alongside the originals. These URLs serve placeholders immediately and swap to real files once the size variant workflow finishes.
The `sizes` parameter is a filter on what you get back - it only returns URLs for sizes that are enabled in the collection's `animation_sizes` config. Poll the job's `size_variants.status` field to know when all variants are ready.
## Check CDN Status
Get the CDN publishing status for all assets in a collection. Shows which assets have been published, their file sizes, and current status.
GET /v1/collections/:id/cdn-status
```bash
curl https://api.masko.ai/v1/collections/COLLECTION_ID/cdn-status \
-H "Authorization: Bearer masko_YOUR_API_KEY"
```
```json
{
"data": {
"assets": [
{
"asset_id": "ast_img_001",
"item_name": "Waving hello",
"type": "image",
"cdn_url": "https://assets.masko.ai/u/felix-the-fox/waving-hello-a1b2.png",
"status": "completed",
"file_size": 245832
},
{
"asset_id": "ast_vid_010",
"item_name": "Idle breathing",
"type": "webm",
"cdn_url": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-c3d4.webm",
"status": "completed",
"file_size": 1548200
}
]
}
}
```
## Get All URLs
Retrieve all URLs for every item in a collection, organized by item. Returns CDN URLs when available, falling back to signed storage URLs.
GET /v1/collections/:id/urls
```bash
curl https://api.masko.ai/v1/collections/COLLECTION_ID/urls \
-H "Authorization: Bearer masko_YOUR_API_KEY"
```
```json
{
"data": {
"collection": "Felix the Fox",
"items": [
{
"name": "Waving hello",
"image": "https://assets.masko.ai/u/felix-the-fox/waving-hello-a1b2.png",
"transparent_image": "https://assets.masko.ai/u/felix-the-fox/waving-hello-c3d4.png"
},
{
"name": "Idle breathing",
"image": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-e5f6.png",
"transparent_image": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-g7h8.png",
"animations": [
{
"video": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-i9j0.mp4",
"transparent_video_webm": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-k1l2.webm",
"transparent_video_mov": "https://assets.masko.ai/u/felix-the-fox/idle-breathing-m3n4.mov"
}
]
}
]
}
}
```
## Change Slug
Update the collection's CDN slug. This changes the URL path for all future assets. Existing CDN URLs are not affected - only new publishes use the new slug.
PATCH /v1/collections/:id/cdn-slug
```bash
curl -X PATCH https://api.masko.ai/v1/collections/COLLECTION_ID/cdn-slug \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"slug": "felix"
}'
```
```json
{
"data": {
"slug": "felix"
}
}
```
Slugs must be 2-50 characters, lowercase alphanumeric with dashes. Each slug must be unique across all collections.
## Disabling CDN
If you do not need CDN URLs, set `cdn_enabled: false` in the collection settings when creating or updating the collection. This skips placeholder uploads and CDN URL allocation. Assets are still generated and accessible via signed storage URLs through the jobs endpoint.
---
---url: /docs/generation---
# Generation
%% animation https://assets.masko.ai/7fced6/spark-4735/painting-dddca74c-360.webm https://assets.masko.ai/7fced6/spark-4735/painting-bba26b7f-360.mov %%
A single unified endpoint handles all generation types: images, animations, logos, and edits. Each request creates a job you can poll for results.
POST /v1/collections/:id/generate
## Image Generation
Generate a mascot image from a text prompt. Costs **1 credit**. Returns both a full image and a transparent (background-removed) variant.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "image",
"name": "Waving hello",
"image_prompt": "waving hello with a friendly smile"
}'
```
```javascript
const res = await fetch(
'https://api.masko.ai/v1/collections/COLLECTION_ID/generate',
{
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'image',
name: 'Waving hello',
image_prompt: 'waving hello with a friendly smile',
}),
}
);
const { job_id, asset_ids, urls } = await res.json();
```
Response includes `asset_ids.image` and `asset_ids.transparent_image` for the two variants.
## Animation Generation
Generate an animated mascot from scratch. Costs **21 credits** for a 4-second animation (1 credit for the image + 5 credits/sec for the video). Returns image, video, webm, and hevc assets.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Dancing",
"image_prompt": "standing in a dance pose, arms raised",
"animation_prompt": "dancing energetically with bouncy movements",
"duration": 4,
"loop": true
}'
```
```javascript
const res = await fetch(
'https://api.masko.ai/v1/collections/COLLECTION_ID/generate',
{
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'animation',
name: 'Dancing',
image_prompt: 'standing in a dance pose, arms raised',
animation_prompt: 'dancing energetically with bouncy movements',
duration: 4,
loop: true,
}),
}
);
const { job_id, asset_ids, urls } = await res.json();
// asset_ids: { image, transparent_image, video, webm, hevc }
```
### Size Variants
Pass a `sizes` array to get pre-allocated CDN URLs for smaller variants directly in the response. Available sizes: `720`, `480`, `360`, `240`. Requires [size variants enabled](/docs/generate/animations#size-variants) on the collection.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Dancing",
"image_prompt": "standing in a dance pose",
"animation_prompt": "dancing energetically",
"duration": 4,
"sizes": [360]
}'
```
The response includes both original and variant URLs (`webm_360`, `hevc_360`, `stacked_video_360`). These URLs work immediately as placeholders and switch to the real resized files once processing completes.
## Animate Existing Image
Animate an image you already have. Pass `source_image_asset_id` to skip image generation. Costs **20 credits** for 4 seconds (video only, no image cost).
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Waving animated",
"source_image_asset_id": "IMAGE_ASSET_ID",
"animation_prompt": "waving hello smoothly",
"duration": 4
}'
```
## Transitions
Create a transition between two poses by providing both a source and end image. Set `auto_reverse` to automatically generate the return transition at no extra cost.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "animation",
"name": "Idle to Wave",
"source_image_asset_id": "IDLE_IMAGE_ID",
"end_image_asset_id": "WAVE_IMAGE_ID",
"animation_prompt": "transitioning from idle to waving",
"auto_reverse": true,
"reverse_name": "Wave to Idle"
}'
```
When `auto_reverse` is true, the response includes a `reverse_job` object with its own job ID and asset IDs. The reverse costs 0 credits.
## Edit Image
Modify an existing image with natural language instructions. Costs **1 credit**.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "edit",
"item_id": "EXISTING_ITEM_ID",
"source_image_asset_id": "IMAGE_ASSET_ID",
"edit_instructions": "Add a santa hat and snow falling in the background"
}'
```
## Logo Pack
Generate a full logo pack with multiple style variants. Costs **5 credits**.
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "logo",
"name": "App Logo",
"logo_description": "Iconic representation of the character face",
"logo_style_name": "Flat",
"logo_style_instruction": "Flat design with solid colors, no gradients or shadows"
}'
```
## Batch Generation
Generate multiple items in a single request. Each item in the batch follows the same format as the single generate endpoint.
POST /v1/collections/:id/generate-batch
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/generate-batch \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "type": "image", "name": "Waving", "image_prompt": "waving hello" },
{ "type": "image", "name": "Thinking", "image_prompt": "thinking with hand on chin" },
{ "type": "animation", "name": "Dancing", "image_prompt": "dancing pose", "animation_prompt": "dancing", "duration": 4 }
]
}'
```
## Preview
Test a generation prompt without creating items or spending credits. Returns a temporary preview image URL.
POST /v1/generate/preview
```bash
curl -X POST https://api.masko.ai/v1/generate/preview \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"collection_id": "COLLECTION_ID",
"prompt": "a friendly fox mascot waving hello"
}'
```
## Polling Jobs
Every generation returns a `job_id`. Poll the job endpoint to check progress. Use `?wait=true` for long polling - the server holds the connection until the job completes or times out.
GET /v1/jobs/:id
```bash
# Standard polling
curl https://api.masko.ai/v1/jobs/JOB_ID \
-H "Authorization: Bearer masko_YOUR_API_KEY"
# Long polling (waits for completion)
curl https://api.masko.ai/v1/jobs/JOB_ID?wait=true \
-H "Authorization: Bearer masko_YOUR_API_KEY"
```
```javascript
// Long polling - simplest approach
const res = await fetch(
`https://api.masko.ai/v1/jobs/${jobId}?wait=true`,
{
headers: { 'Authorization': 'Bearer masko_YOUR_API_KEY' },
}
);
const job = await res.json();
if (job.status === 'completed') {
console.log('Assets:', job.assets);
}
```
CDN URLs are returned immediately in the generate response, before generation finishes. You can embed these URLs in your app right away - they serve a placeholder until the real asset is ready, then automatically switch over. For animations, pass `sizes: [360]` to also get instant CDN URLs for smaller variants - no extra API call needed.
---
---url: /docs/canvas---
# Canvas & Templates
A canvas is an interactive state machine for your mascot. Define poses (nodes), transitions (edges), conditions, and input triggers to create mascots that react to user actions in real time.
## Concepts
- [Nodes (Poses)] - Each node represents a mascot pose or state - idle, waving, thinking, etc. Nodes reference an animation asset.
- [Edges (Transitions)] - Edges connect nodes and define how the mascot moves between poses. Each edge is an animation from one pose to another.
- [Loops] - Looping animations play continuously within a pose. Non-looping animations play once then hold the last frame.
- [Conditions & Inputs] - Edges can have conditions like 'on hover', 'on click', or custom triggers. Inputs let your app control the mascot programmatically.
## Create a Canvas
Create a canvas within a collection. A canvas starts empty - you add nodes and edges by applying a template or building manually.
POST /v1/collections/:id/canvases
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/canvases \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Main Canvas"
}'
```
```javascript
const res = await fetch(
'https://api.masko.ai/v1/collections/COLLECTION_ID/canvases',
{
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'Main Canvas' }),
}
);
const canvas = await res.json();
// canvas.id is used in subsequent requests
```
## Apply a Template
Templates define a pre-built set of nodes and edges. Applying a template populates the canvas with poses and transitions, then generates all the required images and animations.
POST /v1/collections/:id/canvases/:canvasId/from-template
```bash
# Apply the Claude Code 4-state template
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/canvases/CANVAS_ID/from-template \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "claude-code-4state"
}'
```
```javascript
const res = await fetch(
`https://api.masko.ai/v1/collections/COLLECTION_ID/canvases/CANVAS_ID/from-template`,
{
method: 'POST',
headers: {
'Authorization': 'Bearer masko_YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
template_id: 'claude-code-4state',
}),
}
);
const result = await res.json();
// result.nodes, result.edges, result.jobs
```
## Generate All Animations
Once your canvas has nodes with images, generate all the transition animations between connected poses in a single call. Transitions use `auto_reverse` by default, so reverse animations are generated for free.
POST /v1/collections/:id/canvases/:canvasId/generate-all
```bash
curl -X POST https://api.masko.ai/v1/collections/COLLECTION_ID/canvases/CANVAS_ID/generate-all \
-H "Authorization: Bearer masko_YOUR_API_KEY" \
-H "Content-Type: application/json"
```
Reverse transitions are free (0 credits). When generating a transition from A to B with `auto_reverse`, the B to A animation is created automatically at no additional cost.
## Check Progress
Get the generation status of all nodes and edges in a canvas. Returns completion percentages and individual asset statuses.
GET /v1/collections/:id/canvases/:canvasId/status
```bash
curl https://api.masko.ai/v1/collections/COLLECTION_ID/canvases/CANVAS_ID/status \
-H "Authorization: Bearer masko_YOUR_API_KEY"
# Response:
# {
# "canvas_id": "...",
# "total_jobs": 12,
# "completed": 8,
# "pending": 3,
# "failed": 1,
# "progress": 0.67
# }
```
## Export
Export the canvas as a `MaskoAnimationConfig` JSON object ready to use with the Masko embed player. All asset URLs point to the CDN.
GET /v1/collections/:id/canvases/:canvasId/export
```bash
curl https://api.masko.ai/v1/collections/COLLECTION_ID/canvases/CANVAS_ID/export \
-H "Authorization: Bearer masko_YOUR_API_KEY"
```
```javascript
const res = await fetch(
`https://api.masko.ai/v1/collections/COLLECTION_ID/canvases/CANVAS_ID/export`,
{
headers: { 'Authorization': 'Bearer masko_YOUR_API_KEY' },
}
);
const config = await res.json();
// Pass config to your Masko embed player
//