{"openapi":"3.1.0","info":{"title":"MAP Audio Music API","version":"2026-11-01","summary":"PAM's sound engine as an API: loops, stems, variations, DJ sets, drum hits and MIDI patterns rendered from factory presets, on CPU, with no AI model.","description":"The MAP Audio Music API runs PAM's sound engine on MAP Audio's servers. Send JSON and get audio and MIDI files back: loops, stems, variations and DJ sets rendered from PAM's factory presets, plus drum hits and MIDI patterns. No AI model makes the audio. A preset render reports the seed it used, and sending that seed again renders the same audio; each result also carries a signed provenance record.\n\nDocs, recipes and the error catalogue: https://map.audio/developers/music-api. Access is invite-only while the API is in preview: request it at https://map.audio/music, where invited accounts also accept the terms, create API keys and choose a plan.\n\nEvery operation that runs the engine is a job. A request answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s by default for quick commands, 0 for renders, at most 60), else 202 with the job to poll, stream or hear about by webhook. Send an `Idempotency-Key` with a POST that starts a job to make a retry safe; the other POSTs refuse that header with 400 idempotency_key_unsupported.\n\nFree plan: 30 render-minutes a month, 2 jobs at once, renders up to 300 s, outputs kept 7 days. A render-minute is a minute of rendered audio, at least 0.1 per output; analysis, edits, patterns and drum hits are free. Paid plans and bought render-minutes add more (GET /v1/credits).\n\nRate limit: each API key may send 120 requests a minute, on every plan, and map.audio sign-ins share one such limit per account. Responses to an accepted credential carry `RateLimit-Policy: 120;w=60`; past the limit a request answers 429 rate_limited with `Retry-After`.\n\nTest and live keys: an `sk_test_` key and an `sk_live_` key reach the same account. Both spend the same render-minutes and see the same jobs, files and webhooks; test mode is not a sandbox yet. The prefix keeps their Idempotency-Key namespaces apart, sets `livemode` on jobs, and gives a test render's provenance licence id a `_test` suffix. The examples here use a test key.\n\nVersioning: this is version 2026-11-01, named in the `Map-Version` header of every JSON response. A request may send `Map-Version: 2026-11-01` to pin it; any other value answers 400 version_unsupported. While the API is in preview, breaking changes can land under 2026-11-01 until general availability; each one is listed in the docs changelog.\n\nMCP: operations whose `x-mcp` names a tool are also tools on the hosted MCP server at https://api.map.audio/mcp (Streamable HTTP, the same credentials); `x-mcp` says why the others are not.","contact":{"name":"MAP Audio","url":"https://map.audio/developers/music-api","email":"support@map.audio"},"x-generated-by":"daemon/scripts/generate-cli.mjs from music-api/openapi.base.json and cli/contract/v1.contract.json","x-authority-sha256":"8b7d3fbfeed4628e404dce43564e24b0f619387276e3aa85146790426d048466"},"servers":[{"url":"https://api.map.audio"}],"security":[{"bearer":[]}],"tags":[{"name":"Account","description":"The account behind a credential: plan, render-minutes, usage, terms, access requests, API keys and billing. Keys and billing need a map.audio sign-in on MAP Audio's own pages (https://map.audio/music)."},{"name":"Catalogue","description":"The factory presets the engine renders, the drum-synth engines, the DJ transitions, and this document."},{"name":"Plans","description":"Turn a short prompt, or a spec you write, into an editable render plan. Free; no AI model."},{"name":"Renders","description":"Render presets and plans to audio, and fit cutdowns or check DJ sets before rendering."},{"name":"Commands","description":"PAM's engine commands as endpoints: audio analysis and editing, preset renders, effects, mastering, headless state, DJ sets, patterns and drum synthesis. Body fields use the same names as the commands' MCP arguments."},{"name":"Jobs","description":"Every engine call is a job: read it, wait for it, stream its events or cancel it."},{"name":"Files","description":"Render outputs and uploads, with signed download links. Uploads stay off until the decoder and project-reader fuzzers have run."},{"name":"Webhooks","description":"Signed Standard Webhooks deliveries of job events to your HTTPS endpoints."},{"name":"Provenance","description":"Signed records of what made each render, and the public keys that verify them."}],"paths":{"/v1/account":{"get":{"operationId":"getAccount","tags":["Account"],"summary":"Get the calling account","description":"Who this credential belongs to: the Music API account's status, the terms version it accepted, its tier's limits and this month's render-minutes. Call it first. `currentTerms` is the version POST /v1/account/terms takes (every request that starts work needs it), and `credits.remaining` is what jobs can still draw. Free.","responses":{"200":{"description":"The account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"},"examples":{"account":{"summary":"An active free-tier account","value":{"object":"account","id":"acct_01M6BPR7CRAWF0WZQZNP3ZD818","email":"dev@example.com","status":"active","termsVersion":"2026-11-01-prototype","currentTerms":"2026-11-01-prototype","livemode":false,"limits":{"renderMinutesPerMonth":30,"maxRenderSeconds":300,"maxSampleRate":48000,"concurrentJobs":2,"requestsPerMinute":120,"maxDrumSeconds":30,"outputRetentionDays":7},"credits":{"object":"credits","period":"2026-11","unit":"render_minute","tier":{"id":"free","name":"Free","currentPeriodEnd":null,"cancelAtPeriodEnd":false},"granted":30,"used":4.214,"reserved":0.267,"remaining":25.519,"grants":[{"source":"free","amount":30,"remaining":25.519,"expiresAt":"2026-12-01T00:00:00.000Z"}]}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"403":{"description":"No Music API access yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_invited":{"summary":"No Music API access yet","value":{"error":{"type":"entitlement","code":"not_invited","message":"This map.audio account (customer 8f14e45f-ceea-467a-9575-62f3b1a6c2d0) has no Music API access yet. Request access at https://map.audio/music, or POST /v1/access-requests with this token.","param":null,"details":{"customerId":"8f14e45f-ceea-467a-9575-62f3b1a6c2d0","emailConfirmed":true,"accessRequest":null,"requestAccessUrl":"https://map.audio/music"},"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_invited","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":"get_account"}}},"/v1/account/terms":{"post":{"operationId":"acceptTerms","tags":["Account"],"summary":"Accept the prototype terms","description":"Accept the terms that every request starting work needs: renders, commands, plans, arrangements, uploads and checkout. Send the version from `currentTerms` in GET /v1/account; an invited account becomes active. The terms are on https://map.audio/music, where you can also accept them signed in. Free.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accept"],"additionalProperties":false,"properties":{"accept":{"type":"string","description":"The version in `currentTerms`."}}},"examples":{"accept":{"summary":"Accept the current terms","value":{"accept":"2026-11-01-prototype"}}}}}},"responses":{"200":{"description":"The account, now active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"},"examples":{"account":{"summary":"Terms accepted","value":{"object":"account","id":"acct_01M6BPR7CRAWF0WZQZNP3ZD818","email":"dev@example.com","status":"active","termsVersion":"2026-11-01-prototype","currentTerms":"2026-11-01-prototype","livemode":false,"limits":{"renderMinutesPerMonth":30,"maxRenderSeconds":300,"maxSampleRate":48000,"concurrentJobs":2,"requestsPerMinute":120,"maxDrumSeconds":30,"outputRetentionDays":7},"credits":{"object":"credits","period":"2026-11","unit":"render_minute","tier":{"id":"free","name":"Free","currentPeriodEnd":null,"cancelAtPeriodEnd":false},"granted":30,"used":4.214,"reserved":0.267,"remaining":25.519,"grants":[{"source":"free","amount":30,"remaining":25.519,"expiresAt":"2026-12-01T00:00:00.000Z"}]}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Wrong terms version","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"terms_version_mismatch":{"summary":"Wrong terms version","value":{"error":{"type":"invalid_request","code":"terms_version_mismatch","message":"accept must be \"2026-11-01-prototype\", the current terms version; got \"2026-10-01\".","param":"accept","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#terms_version_mismatch","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["terms_version_mismatch","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":"accept_terms"}}},"/v1/access-requests":{"post":{"operationId":"createAccessRequest","tags":["Account"],"summary":"Request Music API access","description":"Ask MAP Audio for Music API access as the signed-in map.audio account behind the access token. Use it when a call answers 403 not_invited: send the same token, with a line about what you will build and a website if you like. One request per account; sending again updates the fields you send (null clears one), keeps the ones you leave out, and answers 200. MAP Audio emails the account when access is ready, and https://map.audio/music does the same signed in. An API key cannot call this route, and it never answers not_invited. Free.","security":[{"signIn":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequestCreate"},"examples":{"project":{"summary":"A short note about the project","value":{"useCase":"A game that scores every level with new loops from PAM presets.","website":"https://example.com"}}}}}},"responses":{"200":{"description":"The request, updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"},"examples":{"updated":{"summary":"Updated","value":{"object":"access_request","id":"areq_01M6BPS09M7WAVD3A2N3JPJE0X","status":"pending","email":"dev@example.com","useCase":"A game that scores every level with new loops from PAM presets.","website":"https://example.com","createdAt":"2026-11-01T13:40:12.007Z","updatedAt":"2026-11-01T14:05:51.630Z"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"201":{"description":"The request, created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"},"examples":{"created":{"summary":"Created","value":{"object":"access_request","id":"areq_01M6BPS09M7WAVD3A2N3JPJE0X","status":"pending","email":"dev@example.com","useCase":"A game that scores every level with new loops from PAM presets.","website":"https://example.com","createdAt":"2026-11-01T13:40:12.007Z","updatedAt":"2026-11-01T13:40:12.007Z"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"403":{"description":"Access requests need a sign-in","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"access_request_needs_sign_in":{"summary":"Access requests need a sign-in","value":{"error":{"type":"entitlement","code":"access_request_needs_sign_in","message":"An API key cannot request access: every key belongs to an account that has it already. Sign in at https://map.audio/music with the map.audio account that needs access, and request it there.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#access_request_needs_sign_in","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"409":{"description":"Already has access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"already_has_access":{"summary":"Already has access","value":{"error":{"type":"conflict","code":"already_has_access","message":"This map.audio account already has Music API access, so there is nothing to request. Call the API with this token, or create API keys at https://map.audio/music.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#already_has_access","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["access_request_needs_sign_in","already_has_access","customer_erased","rate_limited","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":false,"reason":"An MCP session already has Music API access; an account without it requests access signed in at https://map.audio/music."}}},"/v1/usage":{"get":{"operationId":"getUsage","tags":["Account"],"summary":"Get usage by key and meter","description":"Meter totals for the account per API key and meter: render-minutes, rendered audio seconds, compute time, and the free commands' own meters. `from` and `to` are UTC days, at most a year apart and at most 90 days back, as usage is kept that long. Requests made with a map.audio sign-in have `keyId: null`. Free; GET /v1/credits shows what is left to spend.","parameters":[{"name":"from","in":"query","description":"First UTC day, YYYY-MM-DD, at most 90 days back. Default: the first of this month.","example":"2026-11-01","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Last UTC day, included. Default: today.","example":"2026-11-30","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"},"examples":{"month":{"summary":"This month so far","value":{"object":"usage","from":"2026-11-01","to":"2026-11-01","data":[{"keyId":"key_01M6BPR91W1E1YGMF0P6TAZZNG","meter":"audioSeconds","quantity":252.8},{"keyId":"key_01M6BPR91W1E1YGMF0P6TAZZNG","meter":"computeMs","quantity":61408},{"keyId":"key_01M6BPR91W1E1YGMF0P6TAZZNG","meter":"renderMinutes","quantity":4.214}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"from must be a date as YYYY-MM-DD; got \"yesterday\".","param":"from","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":false,"reason":"Per-key meter totals are for dashboards and audits; get_credits shows the render-minutes an agent can still spend."}}},"/v1/credits":{"get":{"operationId":"getCredits","tags":["Account"],"summary":"Get the render-minute balance","description":"What jobs can still spend this month: the tier's allowance, render-minutes used, render-minutes running jobs hold, credits bought, and `remaining`, which the next job draws on. A job reserves its estimate when it is admitted and settles at its outputs' real length. Free. Buy render-minutes or a paid tier at https://map.audio/music.","responses":{"200":{"description":"Credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credits"},"examples":{"free":{"summary":"A free-tier account part way through the month","value":{"object":"credits","period":"2026-11","unit":"render_minute","tier":{"id":"free","name":"Free","currentPeriodEnd":null,"cancelAtPeriodEnd":false},"granted":30,"used":4.214,"reserved":0.267,"remaining":25.519,"grants":[{"source":"free","amount":30,"remaining":25.519,"expiresAt":"2026-12-01T00:00:00.000Z"}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"authentication_failed":{"summary":"Authentication failed","value":{"error":{"type":"authentication","code":"authentication_failed","message":"That API key is not valid or was revoked.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#authentication_failed","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":"get_credits"}}},"/v1/api-keys":{"get":{"operationId":"listApiKeys","tags":["Account"],"summary":"List API keys","description":"The account's API keys, newest first, without their secrets; `prefix` shows each one's first characters so you can tell them apart. Free.","responses":{"200":{"description":"Keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyList"},"examples":{"keys":{"summary":"One key","value":{"object":"list","data":[{"object":"api_key","id":"key_01M6BPR91W1E1YGMF0P6TAZZNG","name":"Build server","mode":"test","prefix":"sk_test_7Hq2","createdAt":"2026-10-28T09:12:44.031Z","lastUsedAt":"2026-11-01T14:03:31.000Z","revokedAt":null}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"\"cursor\" is not a parameter of GET /v1/api-keys; it takes none.","param":"cursor","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":false,"reason":"API keys are created, listed and revoked signed in at https://map.audio/music, so a connected app never holds or handles credentials."}},"post":{"operationId":"createApiKey","tags":["Account"],"summary":"Create an API key","description":"Create an API key; its secret is in this response only, so store it now. Needs a map.audio sign-in on MAP Audio's own pages (https://map.audio/music), not an API key or another app's token, so a leaked key cannot mint more. `mode` picks the `sk_test_` or `sk_live_` prefix: both modes spend the same render-minutes and see the same jobs and files. An account holds at most 10 active keys. Send `acceptTerms` to accept the terms in the same call. Free.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreate"},"examples":{"live":{"summary":"A live key for a server","value":{"name":"Production server","mode":"live"}},"first":{"summary":"A first test key, accepting the terms","value":{"name":"Laptop","mode":"test","acceptTerms":"2026-11-01-prototype"}}}}}},"responses":{"201":{"description":"The key, with its secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreated"},"examples":{"created":{"summary":"Created","value":{"object":"api_key","id":"key_01M6BPRAQ0QXZ93APJ3C3FRWXZ","name":"Production server","mode":"live","prefix":"sk_live_Qm4T","createdAt":"2026-11-01T14:10:05.311Z","lastUsedAt":null,"revokedAt":null,"secret":"sk_live_Qm4Tz8VbN2rYp6KcW1sXe9JhL3dGa7FuR5o"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"403":{"description":"Needs the account owner's sign-in; Key limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"oauth_required":{"summary":"Needs the account owner's sign-in","value":{"error":{"type":"entitlement","code":"oauth_required","message":"Only the account owner, signed in at https://map.audio/music, can create or revoke API keys. This request used an API key.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#oauth_required","requestId":"9a3f7c2e5b1d8f40-LHR"}}},"too_many_keys":{"summary":"Key limit reached","value":{"error":{"type":"entitlement","code":"too_many_keys","message":"An account may hold 10 active keys; revoke one (DELETE /v1/api-keys/{id}) first.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#too_many_keys","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["oauth_required","terms_version_mismatch","too_many_keys","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":false,"reason":"API keys are created, listed and revoked signed in at https://map.audio/music, so a connected app never holds or handles credentials."}}},"/v1/api-keys/{id}":{"delete":{"operationId":"revokeApiKey","tags":["Account"],"summary":"Revoke an API key","description":"Revoke a key at once: requests with it answer 401 from then on, and webhook endpoints whose secret it last set are disabled with it. Needs a map.audio sign-in on MAP Audio's own pages (https://map.audio/music), so a leaked key cannot revoke the others. Free.","parameters":[{"$ref":"#/components/parameters/ApiKeyId"}],"responses":{"200":{"description":"The key, revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKey"},"examples":{"revoked":{"summary":"Revoked","value":{"object":"api_key","id":"key_01M6BPRAQ0QXZ93APJ3C3FRWXZ","name":"Production server","mode":"live","prefix":"sk_live_Qm4T","createdAt":"2026-11-01T14:10:05.311Z","lastUsedAt":null,"revokedAt":"2026-11-01T14:12:40.902Z"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No API key with that id; GET /v1/api-keys lists this account's keys.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["oauth_required","not_found","invalid_request"],"x-mcp":{"tool":false,"reason":"API keys are created, listed and revoked signed in at https://map.audio/music, so a connected app never holds or handles credentials."}}},"/v1/presets":{"get":{"operationId":"listPresets","tags":["Catalogue"],"summary":"Search the factory presets","description":"Search the factory presets the engine renders, by words in their names, descriptions, categories and tags, by category and by tempo. Each preset's `ref` (pam:factory/<slug>) is what renders, plans, arrangements and DJ sets take, and `variations` lists its slots. Free. Next: POST /v1/renders with `source.preset` set to a `ref`.","parameters":[{"name":"q","in":"query","description":"Words that must each start a word of a preset's name, description, category, subcategory, author or tags.","example":"disco","schema":{"type":"string","maxLength":200}},{"name":"category","in":"query","description":"A category, matched without regard to case.","example":"Drums","schema":{"type":"string"}},{"name":"tempoMin","in":"query","description":"Lowest tempo, in BPM.","example":118,"schema":{"type":"number"}},{"name":"tempoMax","in":"query","description":"Highest tempo, in BPM.","example":128,"schema":{"type":"number"}},{"name":"limit","in":"query","description":"Presets per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"The `nextCursor` of the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Matching presets.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetList"},"examples":{"disco":{"summary":"Searching for \"disco\"","value":{"object":"list","data":[{"object":"preset","slug":"313-disco","ref":"pam:factory/313-disco","product":"pam","name":"313 Disco","author":"TopograFX","description":"Motor City disco with aquatic funk","bpm":120,"timeSignature":[4,4],"category":"Drums","subcategory":"Disco","tags":[],"variations":[1],"sha256":"3afbf5dea1003b2d17385955017785a57d74c65f77f97b58cf5d7cec9794ca1c","hasSong":false}],"total":1,"nextCursor":null}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"limit must be a whole number from 1 to 100; got \"500\".","param":"limit","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":"search_presets"}}},"/v1/presets/{id}":{"get":{"operationId":"getPreset","tags":["Catalogue"],"summary":"Get one preset","description":"One factory preset by its slug (313-disco) or URL-encoded reference: name, tempo, time signature, category, tags and the variation slots it has. Free.","parameters":[{"$ref":"#/components/parameters/PresetId"}],"responses":{"200":{"description":"The preset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Preset"},"examples":{"disco":{"summary":"313 Disco","value":{"object":"preset","slug":"313-disco","ref":"pam:factory/313-disco","product":"pam","name":"313 Disco","author":"TopograFX","description":"Motor City disco with aquatic funk","bpm":120,"timeSignature":[4,4],"category":"Drums","subcategory":"Disco","tags":[],"variations":[1],"sha256":"3afbf5dea1003b2d17385955017785a57d74c65f77f97b58cf5d7cec9794ca1c","hasSong":false}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"No such preset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"preset_not_found":{"summary":"No such preset","value":{"error":{"type":"not_found","code":"preset_not_found","message":"No factory preset 313-discoo; list them with GET /v1/presets.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#preset_not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","preset_not_found","preset_not_served"],"x-mcp":{"tool":"get_preset"}}},"/v1/drum-engines":{"get":{"operationId":"listDrumEngines","tags":["Catalogue"],"summary":"List the drum-synth engines","description":"The drum-synth engines POST /v1/synth/drum plays, each with its controls: label, unit and range. Set controls by label in that route's `param` (Tune=55,Decay=1.5); percent controls take 0 to 100. Free.","responses":{"200":{"description":"Engines.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/DrumEngine"}}}},"examples":{"engines":{"summary":"The first two engines","value":{"object":"list","data":[{"id":"1","slug":"kick","name":"Kick","controls":[{"label":"Tune","unit":"Hz","min":30,"max":160},{"label":"P.Depth","unit":"ratio","min":1,"max":5},{"label":"P.Decay","unit":"s","min":0.005,"max":0.2},{"label":"Decay","unit":"s","min":0.03,"max":3},{"label":"Click","unit":"percent","min":0,"max":100},{"label":"Drive","unit":"percent","min":0,"max":100},{"label":"Tone","unit":"Hz","min":150,"max":16000},{"label":"Wave","unit":"percent","min":0,"max":100}]},{"id":"2","slug":"snare","name":"Snare","controls":[{"label":"Tune","unit":"Hz","min":120,"max":400},{"label":"Noise","unit":"percent","min":0,"max":100},{"label":"Decay","unit":"s","min":0.03,"max":0.5},{"label":"N.Decay","unit":"s","min":0.03,"max":0.6},{"label":"N.Tone","unit":"Hz","min":800,"max":8000},{"label":"P.Depth","unit":"ratio","min":1,"max":3},{"label":"P.Decay","unit":"s","min":0.005,"max":0.3},{"label":"Drive","unit":"percent","min":0,"max":100}]}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"rate_limited":{"summary":"Rate limited","value":{"error":{"type":"rate_limit","code":"rate_limited","message":"This API key sent more than 120 requests in a minute, the limit for each key; retry after 10 s.","param":null,"retryable":true,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#rate_limited","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":"list_drum_engines"}}},"/v1/transition-presets":{"get":{"operationId":"listTransitionPresets","tags":["Catalogue"],"summary":"List the DJ transitions","description":"What a DJ set's transitions can use: the transition presets a render knows, the modes and curves a transition takes, the longest window in bars, and the DJ set schema's definitions. Read it before writing a set for POST /v1/arrangements or POST /v1/dj/set. Free.","responses":{"200":{"description":"Transitions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransitionPresets"},"examples":{"transitions":{"summary":"Factory transitions (definitions cut to DjTransition's plain fields)","value":{"object":"transition_presets","presets":["drop","rise","break","blend","sweep","fill"],"modes":["auto","param","mix","seq","all","swap","chop"],"curves":["linear","ease","exp","log"],"maxBars":32,"schema":"https://map.audio/schemas/pam/dj-set.schema.json","definitions":{"DjTransition":{"type":"object","additionalProperties":false,"description":"Resolved in order: the preset's spec, spec merged over it one level deep per section, then bars, mode and curve as the DJ view's Length, Mode and Curve rows apply them.","properties":{"preset":{"type":"string","minLength":1,"maxLength":64,"description":"A transition preset id: drop, rise, break, blend, sweep, fill, or one the user saved."},"bars":{"type":"number","minimum":0,"maximum":32},"mode":{"enum":["auto","param","mix","seq","all","swap","chop"]},"curve":{"enum":["linear","ease","exp","log"]}}}}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"authentication_failed":{"summary":"Authentication failed","value":{"error":{"type":"authentication","code":"authentication_failed","message":"Send an API key or a map.audio access token as `Authorization: Bearer …`.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#authentication_failed","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":"list_transition_presets"}}},"/v1/plans":{"post":{"operationId":"createPlan","tags":["Plans"],"summary":"Plan a render from a prompt","description":"Turn a short prompt into an editable render plan, or store one you wrote. The `rules` planner matches the prompt's words and tempo against the catalogue, with no AI model, and returns its ranked candidates and a spec; `caller` stores your own spec once every reference checks out. Plans are free and never change: edit a spec and send it back as a `caller` plan. Next: POST /v1/renders with `plan` set to the plan's id.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanCreate"},"examples":{"rules":{"summary":"Plan from a prompt","value":{"prompt":"dark techno around 125 bpm","constraints":{"candidates":3},"seed":7}},"caller":{"summary":"Store your own spec: a morph toward another preset at 128 BPM","value":{"planner":"caller","spec":{"base":{"preset":"pam:factory/acid-sprinkle","variation":1},"tempo":128,"morph":{"to":{"preset":"pam:factory/teknochonic"},"at":0.35},"arrangement":{"kind":"loop","bars":8}}}}}}}},"responses":{"201":{"description":"The plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plan"},"examples":{"caller":{"summary":"A stored caller plan","value":{"object":"plan","id":"plan_01M6BPRCC4FTKB29RFYD2JDKJQ","seed":0,"prompt":null,"planner":{"kind":"caller","version":"caller-1","model":null},"candidates":[],"spec":{"product":"pam","base":{"preset":"pam:factory/acid-sprinkle","variation":1},"tempo":128,"morph":{"to":{"preset":"pam:factory/teknochonic"},"at":0.35},"arrangement":{"kind":"loop","bars":8}},"createdAt":"2026-11-01T14:02:10.250Z","provenance":{"aiModels":[],"presets":["pam:factory/acid-sprinkle","pam:factory/teknochonic"]}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"Give a prompt, or constraints with a tempo or category, to plan from.","param":"prompt","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["terms_required","preset_not_found","preset_not_served","variation_not_found","invalid_envelope","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":"create_plan"}}},"/v1/plans/{id}":{"get":{"operationId":"getPlan","tags":["Plans"],"summary":"Get a plan","description":"A stored plan: its spec, the candidates the rules planner ranked, and the presets it names. Plans never change; render one with POST /v1/renders and `plan`. Free.","parameters":[{"$ref":"#/components/parameters/PlanId"}],"responses":{"200":{"description":"The plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Plan"},"examples":{"caller":{"summary":"A caller plan","value":{"object":"plan","id":"plan_01M6BPRCC4FTKB29RFYD2JDKJQ","seed":0,"prompt":null,"planner":{"kind":"caller","version":"caller-1","model":null},"candidates":[],"spec":{"product":"pam","base":{"preset":"pam:factory/acid-sprinkle","variation":1},"tempo":128,"morph":{"to":{"preset":"pam:factory/teknochonic"},"at":0.35},"arrangement":{"kind":"loop","bars":8}},"createdAt":"2026-11-01T14:02:10.250Z","provenance":{"aiModels":[],"presets":["pam:factory/acid-sprinkle","pam:factory/teknochonic"]}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No plan with that id; plans come from POST /v1/plans, which returns the id.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","invalid_request"],"x-mcp":{"tool":"get_plan"}}},"/v1/renders":{"post":{"operationId":"createRender","tags":["Renders"],"summary":"Render presets or a plan to audio","description":"Render a factory preset or a stored plan as one job, with one output or many: a length in bars or seconds, a variation, stems, a sample rate, WAV, FLAC or MP3, and a seed (the job reports the seed it used; sending it again renders the same audio). `variations` renders several slots, seeds, morph positions or a blend; `items` names outputs of their own lengths or cutdowns; `quality: standard` renders candidate seeds, measures each and keeps the best. Costs render-minutes: each output's length in minutes, at least 0.1 an output, shown in `estimate` before it runs. Answers 202 with the queued job unless `Prefer: wait` covers it; its outputs are in `result.outputs` once it succeeds.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderCreate"},"examples":{"loop":{"summary":"Eight bars of 313 Disco as WAV, with a fixed seed","value":{"source":{"preset":"pam:factory/313-disco"},"bars":8,"seed":42}},"variations":{"summary":"Four of Cal's variation slots in one job, as FLAC","value":{"source":{"preset":"pam:factory/cal"},"bars":8,"variations":{"kind":"slots","slots":[1,2,3,4]},"format":{"container":"flac"}}},"seeds":{"summary":"Four takes of Totes Rando, each from its own seed","value":{"source":{"preset":"pam:factory/totes-rando"},"bars":4,"variations":{"kind":"seeds","count":4},"seed":7}},"stems":{"summary":"Sixteen bars of a variation with one stem per cell","value":{"source":{"preset":"pam:factory/breakbeatrcool","variation":2},"bars":16,"stems":true,"seed":42}},"morph":{"summary":"Three points on a morph from Acid Sprinkle toward Teknochonic","value":{"source":{"preset":"pam:factory/acid-sprinkle"},"bars":8,"variations":{"kind":"morph","to":{"preset":"pam:factory/teknochonic"},"at":[0.25,0.5,0.75]}}},"cutdowns":{"summary":"30- and 15-second cutdowns for an ad, as 256 kbit/s MP3","value":{"source":{"preset":"pam:factory/thaw"},"items":[{"name":"spot-30","cutdown":{"seconds":30}},{"name":"spot-15","cutdown":{"seconds":15}}],"format":{"container":"mp3","bitrate":256}}},"quality":{"summary":"Render four seeds and keep the one nearest -14 LUFS","value":{"source":{"preset":"pam:factory/junglistic"},"bars":8,"quality":"standard","search":{"candidates":4,"return":1,"targetLufs":-14}}},"preview":{"summary":"Two minutes, with a 4-bar preview published first","value":{"source":{"preset":"pam:factory/corduroy"},"seconds":120,"preview":{"bars":4},"seed":11}},"plan":{"summary":"Render a stored plan","value":{"plan":"plan_01M6BPRCC4FTKB29RFYD2JDKJQ","format":{"container":"mp3"}}}}}}},"responses":{"200":{"description":"The finished job, when it ends within `Prefer: wait`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"$ref":"#/components/examples/RenderSucceeded"}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The queued job; poll `urls.self`, stream `urls.events`, or wait for a webhook.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"queued":{"$ref":"#/components/examples/RenderQueued"}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Render too long","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"render_too_long":{"summary":"Render too long","value":{"error":{"type":"invalid_request","code":"render_too_long","message":"This render is about 310 s (seconds 300 plus tail 10 s); a render may be at most 300 s.","param":"seconds","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#render_too_long","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"402":{"description":"Not enough render-minutes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"insufficient_credits":{"summary":"Not enough render-minutes","value":{"error":{"type":"entitlement","code":"insufficient_credits","message":"This job needs 0.267 render-minutes and 0.012 remain this month; make it shorter, or buy render-minutes at https://map.audio/music.","param":null,"details":{"needed":0.267,"remaining":0.012},"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#insufficient_credits","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"403":{"description":"Terms not accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"terms_required":{"summary":"Terms not accepted","value":{"error":{"type":"entitlement","code":"terms_required","message":"This account has not accepted the prototype terms (2026-11-01-prototype), which work needs. Read and accept them at https://map.audio/music, or send POST /v1/account/terms with {\"accept\": \"2026-11-01-prototype\"} (over MCP, the accept_terms tool).","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#terms_required","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["terms_required","preset_not_found","preset_not_served","variation_not_found","quality_unavailable","render_too_long","not_found","concurrency_limit","insufficient_credits","idempotency_key_reused","idempotency_in_flight","queue_unavailable","invalid_request","unsupported_media_type","payload_too_large"],"x-mcp":{"tool":"create_render"}}},"/v1/arrangements":{"post":{"operationId":"createArrangement","tags":["Renders"],"summary":"Fit a cutdown or check a DJ set","description":"Plan a render without rendering. `cutdown` fits one preset (from `source` or a stored `plan`) to a length in seconds as a DJ set over its variations; `set` checks a DJ set you wrote: references, variations, lengths and transitions. The answer is the set in preset references, its tempo and length, and each item's start in bars and seconds. It costs nothing; render the set with POST /v1/dj/set, or a cutdown as an item of POST /v1/renders.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArrangementCreate"},"examples":{"cutdown":{"summary":"Fit Thaw to about 30 seconds","value":{"source":{"preset":"pam:factory/thaw"},"cutdown":{"seconds":30}}},"set":{"summary":"Check a three-preset set","value":{"set":{"queue":[{"presetPath":"pam:factory/acid-sprinkle","bars":16},{"presetPath":"pam:factory/teknochonic","variationIndex":1,"bars":16,"transition":{"preset":"blend","bars":8}},{"presetPath":"pam:factory/breakbeatrcool","variationIndex":2,"bars":16,"transition":{"preset":"drop"}}],"tempo":{"bpm":124}}}}}}}},"responses":{"200":{"description":"The arrangement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Arrangement"},"examples":{"cutdown":{"summary":"Thaw fitted to 30.9 seconds","value":{"object":"arrangement","set":{"queue":[{"presetPath":"pam:factory/thaw","variationIndex":0,"bars":4},{"presetPath":"pam:factory/thaw","variationIndex":3,"bars":9,"transition":{"preset":"blend","bars":2}},{"presetPath":"pam:factory/thaw","variationIndex":5,"bars":4,"transition":{"preset":"blend","bars":2}}],"tempo":{"bpm":132}},"seconds":30.909,"bpm":132,"bars":17,"boundaries":[{"index":0,"preset":"pam:factory/thaw","variation":1,"startBar":0,"startSeconds":0,"bars":4},{"index":1,"preset":"pam:factory/thaw","variation":4,"startBar":4,"startSeconds":7.273,"bars":9},{"index":2,"preset":"pam:factory/thaw","variation":6,"startBar":13,"startSeconds":23.636,"bars":4}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Unknown transition preset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"dj_unknown_transition_preset":{"summary":"Unknown transition preset","value":{"error":{"type":"invalid_request","code":"dj_unknown_transition_preset","message":"Unknown transition preset swoosh; GET /v1/transition-presets lists the ones a render can use.","param":"set.queue[1].transition.preset","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#dj_unknown_transition_preset","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["terms_required","preset_not_found","preset_not_served","variation_not_found","not_found","dj_invalid_set","dj_offline_unsupported","dj_preset_missing","dj_unknown_transition_preset","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":"create_arrangement"}}},"/v1/jobs":{"get":{"operationId":"listJobs","tags":["Jobs"],"summary":"List jobs","description":"The account's jobs, newest first, optionally filtered by `status` and `operation`, with fresh download links on the outputs. Jobs from test and live keys are listed together. Job records are kept 90 days. Free.","parameters":[{"name":"status","in":"query","description":"Only jobs in this status.","schema":{"$ref":"#/components/schemas/JobStatus"}},{"name":"operation","in":"query","description":"Only jobs of this operation: `renders.create`, `uploads.complete`, or a command's operationId such as `presetRender`.","example":"renders.create","schema":{"type":"string"}},{"name":"limit","in":"query","description":"Jobs per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"The `nextCursor` of the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobList"},"examples":{"jobs":{"summary":"The latest job","value":{"object":"list","data":[{"object":"job","id":"job_01M6BPRE186QHP9QPYGDX5NNFP","operation":"renders.create","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b","bytes":4608044,"format":"wav","sampleRate":48000,"durationSeconds":16,"url":"https://api.map.audio/v1/download/file_01M6BPRK0M34NBP2XKJ1RMX1TQ?expires=1793545422&signature=yaoMrgCHcK9T8MaVnCVtXZc4Ym0FWWM8P-0feZDMObk","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":42,"command":{"ok":true,"wavPath":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sampleRate":48000,"channels":2,"durationSeconds":16,"seed":42,"stems":[],"stemTap":"post_cell_pre_master","latencySamples":0,"missingSamples":[]},"spec":{"source":{"preset":"pam:factory/313-disco"},"plan":null,"bars":8,"seconds":null,"tail":0,"seed":42,"stems":false,"sampleRate":48000,"format":{"container":"wav"},"quality":"draft","tempo":120},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":42,"presets":[{"ref":"pam:factory/313-disco","sha256":"3afbf5dea1003b2d17385955017785a57d74c65f77f97b58cf5d7cec9794ca1c"}],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:jsfkW3eF1r4kChqccp6AKLTvjTK5Re8acrEusqigz7MDUu6uZhsJXVnuQEl6EsErDgVYNXOkos9d0mMyt2CVCg"}},"error":null,"usage":{"renderMinutes":0.267,"audioSeconds":16,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP","events":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/cancel"}}],"nextCursor":null}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"status must be one of queued, running, succeeded, failed, cancelled or expired; got \"done\".","param":"status","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":"list_jobs"}}},"/v1/jobs/{id}":{"get":{"operationId":"getJob","tags":["Jobs"],"summary":"Get a job","description":"A job as it stands: status, progress and estimate, and once it ends, its outputs with download links valid for an hour, the seed, the engine's own result, the provenance record and the render-minutes it was charged. Poll it after a 202, or read it when a webhook says the job ended. Free.","parameters":[{"$ref":"#/components/parameters/JobId"}],"responses":{"200":{"description":"The job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"$ref":"#/components/examples/RenderSucceeded"}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No job with that id; GET /v1/jobs lists this account's jobs.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","invalid_request"],"x-mcp":{"tool":"get_job"}}},"/v1/jobs/{id}/cancel":{"post":{"operationId":"cancelJob","tags":["Jobs"],"summary":"Cancel a job","description":"Stop a queued or running job. A queued job ends `cancelled` at once and a running one when its engine stops; nothing is charged unless the job already published a preview. A job that already ended keeps its outcome. Free.","parameters":[{"$ref":"#/components/parameters/JobId"}],"responses":{"200":{"description":"The job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"cancelled":{"summary":"Cancelled while queued","value":{"object":"job","id":"job_01M6BPRE186QHP9QPYGDX5NNFP","operation":"renders.create","status":"cancelled","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":"2026-11-01T14:03:32.204Z","estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP","events":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No job with that id; GET /v1/jobs lists this account's jobs.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","idempotency_key_unsupported","invalid_request"],"x-mcp":{"tool":"cancel_job"}}},"/v1/jobs/{id}/events":{"get":{"operationId":"streamJobEvents","tags":["Jobs"],"summary":"Stream a job's events","description":"Server-sent events for one job: job.queued, job.started, job.progress, job.preview and job.requeued, then job.succeeded, job.failed, job.cancelled or job.expired. Each event's `data` is JSON with `jobId` and `createdAt`; job.preview carries the preview's outputs, and job.failed the error. Reconnect with `Last-Event-ID` (or `after`) to miss nothing; a stream closes after 10 minutes or once the job has ended. A browser's EventSource cannot send Authorization, so read it with fetch. Free.","parameters":[{"$ref":"#/components/parameters/JobId"},{"name":"after","in":"query","description":"Resume after this event id, as the Last-Event-ID header does.","schema":{"type":"integer","minimum":0},"example":2},{"name":"Last-Event-ID","in":"header","description":"The last event id received; the stream resumes after it.","schema":{"type":"string","pattern":"^\\d{1,9}$"},"example":"2"}],"responses":{"200":{"description":"The event stream.","content":{"text/event-stream":{"schema":{"type":"string"},"examples":{"render":{"summary":"A render from queued to succeeded","value":"retry: 2000\n\nid: 1\nevent: job.queued\ndata: {\"jobId\":\"job_01M6BPRE186QHP9QPYGDX5NNFP\",\"createdAt\":\"2026-11-01T14:03:31.512Z\"}\n\nid: 2\nevent: job.started\ndata: {\"attempt\":1,\"jobId\":\"job_01M6BPRE186QHP9QPYGDX5NNFP\",\"createdAt\":\"2026-11-01T14:03:33.104Z\"}\n\nid: 3\nevent: job.succeeded\ndata: {\"jobId\":\"job_01M6BPRE186QHP9QPYGDX5NNFP\",\"createdAt\":\"2026-11-01T14:03:41.877Z\"}\n\n"}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No job with that id; GET /v1/jobs lists this account's jobs.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","invalid_request"],"x-mcp":{"tool":false,"reason":"A server-sent event stream; MCP tools answer once, so poll get_job instead."}}},"/v1/files":{"get":{"operationId":"listFiles","tags":["Files"],"summary":"List files","description":"Render outputs and uploads the account holds, newest first: kind, status, size, SHA-256 and the job that wrote each. Outputs are kept 7 days on the free tier and longer on paid tiers. Free.","parameters":[{"name":"limit","in":"query","description":"Files per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"The `nextCursor` of the previous page.","schema":{"type":"string"}}],"responses":{"200":{"description":"Files.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileList"},"examples":{"files":{"summary":"One output","value":{"object":"list","data":[{"object":"file","id":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","kind":"output","status":"ready","name":"master.wav","contentType":"audio/wav","bytes":4608044,"sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b","jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","role":"master","createdAt":"2026-11-01T14:03:41.877Z","expiresAt":"2026-11-08T14:03:41.877Z"}],"nextCursor":null}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"The cursor is not one this API issued; pass the nextCursor of the page before, unchanged.","param":"cursor","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":"list_files"}}},"/v1/files/{id}":{"get":{"operationId":"getFile","tags":["Files"],"summary":"Get a file","description":"One file's metadata: kind, status, name, content type, size, SHA-256, the job that wrote it and when retention deletes it. For its bytes, GET /v1/files/{id}/content. Free.","parameters":[{"$ref":"#/components/parameters/FileId"}],"responses":{"200":{"description":"The file.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/File"},"examples":{"output":{"summary":"A render's master","value":{"object":"file","id":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","kind":"output","status":"ready","name":"master.wav","contentType":"audio/wav","bytes":4608044,"sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b","jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","role":"master","createdAt":"2026-11-01T14:03:41.877Z","expiresAt":"2026-11-08T14:03:41.877Z"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No file with that id; GET /v1/files lists this account's files.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","invalid_request"],"x-mcp":{"tool":"get_file"}},"delete":{"operationId":"deleteFile","tags":["Files"],"summary":"Delete a file","description":"Delete a file's bytes now, before retention would; its record stays with status `deleted`, and an output leaves its job's outputs. A file whose job is still running cannot be deleted yet. Free.","parameters":[{"$ref":"#/components/parameters/FileId"}],"responses":{"200":{"description":"The file, deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/File"},"examples":{"deleted":{"summary":"Deleted","value":{"object":"file","id":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","kind":"output","status":"deleted","name":"master.wav","contentType":"audio/wav","bytes":4608044,"sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b","jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","role":"master","createdAt":"2026-11-01T14:03:41.877Z","expiresAt":"2026-11-08T14:03:41.877Z"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"409":{"description":"File not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"file_not_ready":{"summary":"File not ready","value":{"error":{"type":"conflict","code":"file_not_ready","message":"File file_01M6BPRK0M34NBP2XKJ1RMX1TQ is still being written by job_01M6BPRE186QHP9QPYGDX5NNFP; retry when that job succeeds.","param":"id","retryable":true,"jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","docUrl":"https://map.audio/developers/music-api/errors#file_not_ready","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","file_not_ready","invalid_request"],"x-mcp":{"tool":false,"reason":"Deleting a render cannot be undone, so it stays with your own code: DELETE /v1/files/{id} with an API key."}}},"/v1/files/{id}/content":{"get":{"operationId":"getFileContent","tags":["Files"],"summary":"Download a file","description":"Redirects (302) to a signed link for the file's bytes, valid for one hour; the link needs no Authorization header. Job outputs already carry such a link in `url`; use this route for a fresh one. Free.","parameters":[{"$ref":"#/components/parameters/FileId"}],"responses":{"302":{"description":"Redirect to the signed download link.","headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Location":{"description":"The signed link, valid for one hour.","schema":{"type":"string","format":"uri"},"example":"https://api.map.audio/v1/download/file_01M6BPRK0M34NBP2XKJ1RMX1TQ?expires=1793545422&signature=Xb3m0yQ8sV1pE7rL2kN9wT4cJ6hA5dF0gU8iO3zR1eM"}}},"410":{"description":"File no longer stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"file_expired":{"summary":"File no longer stored","value":{"error":{"type":"gone","code":"file_expired","message":"File file_01M6BPRK0M34NBP2XKJ1RMX1TQ expired at 2026-11-08T14:03:41.877Z; render it again.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#file_expired","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","file_not_ready","file_expired","invalid_request"],"x-mcp":{"tool":false,"reason":"Answers with a redirect to raw bytes, which a tool result cannot carry; get_job lists each output with a signed download url."}}},"/v1/uploads":{"post":{"operationId":"createUpload","tags":["Files"],"summary":"Start an upload","description":"Start a multipart upload of an audio file or a DAW project, declared by kind, name, size and SHA-256. Send the parts with PUT /v1/uploads/{id}/parts/{part}, then POST /v1/uploads/{id}/complete. Uploads are off until the decoder and project-reader fuzzers have run, so today this answers 403 uploads_disabled. Free.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadCreate"},"examples":{"audio":{"summary":"A 24-bit WAV","value":{"kind":"audio","name":"vocal-take.wav","bytes":23040044,"sha256":"3b8f1c6e2d9a4b7e0f5c1a8d6e3b9f2c4a7d0e1b5c8f3a6d9e2b4c7f0a1d3e5b"}}}}}},"responses":{"201":{"description":"The upload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"},"examples":{"audio":{"summary":"Two parts to send","value":{"object":"upload","id":"file_01M6BPRR00A11F2KEPGNR7V3Q9","file":"file_01M6BPRR00A11F2KEPGNR7V3Q9","kind":"audio","status":"uploading","partBytes":16777216,"parts":2,"expiresAt":"2026-11-02T14:20:00.000Z"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"403":{"description":"Uploads not open yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"uploads_disabled":{"summary":"Uploads not open yet","value":{"error":{"type":"entitlement","code":"uploads_disabled","message":"File uploads are not open yet; render from factory presets (GET /v1/presets) and pass render outputs as files meanwhile.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#uploads_disabled","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["uploads_disabled","terms_required","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":false,"reason":"Uploads send raw bytes in parts, which a JSON tool call cannot carry; uploads are also off until the decoder fuzzers have run."}}},"/v1/uploads/{id}/parts/{part}":{"put":{"operationId":"putUploadPart","tags":["Files"],"summary":"Send one upload part","description":"Send one part of an upload as raw bytes with its exact Content-Length: every part but the last is `partBytes` long (16 MiB), the last holds the rest. Sending a part again replaces it. Uploads are off for now, so this answers 403 uploads_disabled. Free.","parameters":[{"$ref":"#/components/parameters/UploadId"},{"name":"part","in":"path","required":true,"description":"The part number, from 1.","schema":{"type":"integer","minimum":1,"maximum":10000},"example":1}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"The part, stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadPart"},"examples":{"stored":{"summary":"Part 1 stored","value":{"object":"upload_part","upload":"file_01M6BPRR00A11F2KEPGNR7V3Q9","part":1,"bytes":16777216}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"403":{"description":"Uploads not open yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"uploads_disabled":{"summary":"Uploads not open yet","value":{"error":{"type":"entitlement","code":"uploads_disabled","message":"File uploads are not open yet; render from factory presets (GET /v1/presets) and pass render outputs as files meanwhile.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#uploads_disabled","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["uploads_disabled","terms_required","not_found","invalid_request","upload_closed","upload_expired"],"x-mcp":{"tool":false,"reason":"Uploads send raw bytes in parts, which a JSON tool call cannot carry; uploads are also off until the decoder fuzzers have run."}}},"/v1/uploads/{id}/complete":{"post":{"operationId":"completeUpload","tags":["Files"],"summary":"Finish an upload","description":"Close the upload and start its probe job: the render host checks the bytes against the declared SHA-256 and rewrites audio as a canonical WAV, after which the file is `ready` for commands. Answers with the probe job; completing again retries a probe that never started. Uploads are off for now, so this answers 403 uploads_disabled. Free.","parameters":[{"$ref":"#/components/parameters/UploadId"},{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"responses":{"200":{"description":"The probe job, finished.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Probe finished","value":{"object":"job","id":"job_01M6BPRE186QHP9QPYGDX5NNFP","operation":"uploads.complete","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[],"seed":null,"command":{"probe":{"ok":true,"durationSeconds":120,"sampleRate":48000,"channels":2}},"provenance":null},"error":null,"usage":{"renderMinutes":0,"audioSeconds":0,"computeMs":2210},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP","events":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The probe job, queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"queued":{"summary":"Probe queued","value":{"object":"job","id":"job_01M6BPRE186QHP9QPYGDX5NNFP","operation":"uploads.complete","status":"queued","livemode":false,"sequence":1,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP","events":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"403":{"description":"Uploads not open yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"uploads_disabled":{"summary":"Uploads not open yet","value":{"error":{"type":"entitlement","code":"uploads_disabled","message":"File uploads are not open yet; render from factory presets (GET /v1/presets) and pass render outputs as files meanwhile.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#uploads_disabled","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["uploads_disabled","terms_required","not_found","invalid_request","upload_closed","upload_expired","upload_incomplete","upload_processing","checksum_mismatch","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable"],"x-mcp":{"tool":false,"reason":"Uploads send raw bytes in parts, which a JSON tool call cannot carry; uploads are also off until the decoder fuzzers have run."}}},"/v1/webhook-endpoints":{"get":{"operationId":"listWebhookEndpoints","tags":["Webhooks"],"summary":"List webhook endpoints","description":"The account's webhook endpoints, newest first, without their secrets. Free.","responses":{"200":{"description":"Endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"},"examples":{"endpoints":{"summary":"One endpoint","value":{"object":"list","data":[{"object":"webhook_endpoint","id":"whep_01M6BPRWZCT8J4PSWZ8KG7EXWV","url":"https://hooks.example.com/map-audio","events":["job.succeeded","job.failed"],"description":"Render notifications","status":"enabled","createdAt":"2026-11-01T13:58:02.418Z"}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"\"limit\" is not a parameter of GET /v1/webhook-endpoints; it takes none.","param":"limit","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request"],"x-mcp":{"tool":false,"reason":"Webhook endpoints hold signing secrets for your own server; set them up with an API key (POST /v1/webhook-endpoints) or with the account holder's map.audio sign-in."}},"post":{"operationId":"createWebhookEndpoint","tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Subscribe a public HTTPS URL to job events: job.succeeded, job.failed and job.cancelled unless you list others, or `*` for every event. Each delivery is a signed Standard Webhooks POST (webhook-id, webhook-timestamp and webhook-signature headers: HMAC-SHA256 under the whsec_ secret, which is in this response only), retried with backoff for about 63 hours. An endpoint is disabled after three deliveries in a row run out of retries. Needs an API key or a map.audio sign-in on MAP Audio's own pages; an account has at most 10 endpoints. Free.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"},"examples":{"renders":{"summary":"Hear when renders end","value":{"url":"https://hooks.example.com/map-audio","events":["job.succeeded","job.failed"],"description":"Render notifications"}}}}}},"responses":{"201":{"description":"The endpoint, with its secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"},"examples":{"created":{"summary":"Created","value":{"object":"webhook_endpoint","id":"whep_01M6BPRWZCT8J4PSWZ8KG7EXWV","url":"https://hooks.example.com/map-audio","events":["job.succeeded","job.failed"],"description":"Render notifications","status":"enabled","createdAt":"2026-11-01T13:58:02.418Z","secret":"whsec_Zm9ydHkgdHdvIGJ5dGVzIG9mIGV4YW1wbGUgc2VjcmV0IGtleSE="}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"url must use https; got http.","param":"url","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"403":{"description":"Webhook endpoint limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"too_many_endpoints":{"summary":"Webhook endpoint limit reached","value":{"error":{"type":"entitlement","code":"too_many_endpoints","message":"An account may have 10 webhook endpoints; delete one with DELETE /v1/webhook-endpoints/{id} first (GET /v1/webhook-endpoints lists them).","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#too_many_endpoints","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["oauth_required","too_many_endpoints","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":false,"reason":"Webhook endpoints hold signing secrets for your own server; set them up with an API key (POST /v1/webhook-endpoints) or with the account holder's map.audio sign-in."}}},"/v1/webhook-endpoints/{id}":{"delete":{"operationId":"deleteWebhookEndpoint","tags":["Webhooks"],"summary":"Delete a webhook endpoint","description":"Delete an endpoint; deliveries to it stop. Free.","parameters":[{"$ref":"#/components/parameters/WebhookEndpointId"}],"responses":{"200":{"description":"The endpoint, deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"},"examples":{"deleted":{"summary":"Deleted","value":{"object":"webhook_endpoint","id":"whep_01M6BPRWZCT8J4PSWZ8KG7EXWV","url":"https://hooks.example.com/map-audio","events":["job.succeeded","job.failed"],"description":"Render notifications","status":"enabled","createdAt":"2026-11-01T13:58:02.418Z","deleted":true}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No webhook endpoint with that id; GET /v1/webhook-endpoints lists this account's endpoints.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","invalid_request"],"x-mcp":{"tool":false,"reason":"Webhook endpoints hold signing secrets for your own server; set them up with an API key (POST /v1/webhook-endpoints) or with the account holder's map.audio sign-in."}}},"/v1/webhook-endpoints/{id}/rotate-secret":{"post":{"operationId":"rotateWebhookSecret","tags":["Webhooks"],"summary":"Rotate a webhook secret","description":"Issue a new whsec_ secret, in this response only. For 24 hours each delivery carries signatures under both the old and the new secret, so your server can switch without dropping one; rotating a disabled endpoint also enables it again. Free.","parameters":[{"$ref":"#/components/parameters/WebhookEndpointId"}],"responses":{"200":{"description":"The endpoint, with its new secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"},"examples":{"rotated":{"summary":"Rotated","value":{"object":"webhook_endpoint","id":"whep_01M6BPRWZCT8J4PSWZ8KG7EXWV","url":"https://hooks.example.com/map-audio","events":["job.succeeded","job.failed"],"description":"Render notifications","status":"enabled","createdAt":"2026-11-01T13:58:02.418Z","secret":"whsec_bmV3IHNlY3JldCBmb3IgdGhlIG5leHQgMjQgaG91cnMgb2Ygc2lnbmluZw=="}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"409":{"description":"Secret rotation in progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"rotation_in_progress":{"summary":"Secret rotation in progress","value":{"error":{"type":"conflict","code":"rotation_in_progress","message":"The previous secret stays valid until 2026-11-02T14:20:00.000Z; rotate again after that, or delete the endpoint and create a new one.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#rotation_in_progress","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","oauth_required","rotation_in_progress","idempotency_key_unsupported","invalid_request"],"x-mcp":{"tool":false,"reason":"Webhook endpoints hold signing secrets for your own server; set them up with an API key (POST /v1/webhook-endpoints) or with the account holder's map.audio sign-in."}}},"/v1/webhook-endpoints/{id}/test":{"post":{"operationId":"testWebhookEndpoint","tags":["Webhooks"],"summary":"Send a test event","description":"Queue a signed `webhook.test` event to the endpoint, to check that your server receives deliveries and verifies their signatures. Free.","parameters":[{"$ref":"#/components/parameters/WebhookEndpointId"}],"responses":{"202":{"description":"The queued event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"},"examples":{"queued":{"summary":"Queued","value":{"id":"evt_01M6BPRYMG75T6HXQ8E61EARAX","type":"webhook.test","createdAt":"2026-11-01T14:15:09.664Z","apiVersion":"2026-11-01","data":{"object":{"endpoint":"whep_01M6BPRWZCT8J4PSWZ8KG7EXWV"}}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"409":{"description":"Webhook endpoint disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"endpoint_disabled":{"summary":"Webhook endpoint disabled","value":{"error":{"type":"conflict","code":"endpoint_disabled","message":"This endpoint is disabled, after repeated failed deliveries or because the key that set its secret was revoked; rotate its secret (POST /v1/webhook-endpoints/{id}/rotate-secret) to enable it again.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#endpoint_disabled","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","endpoint_disabled","idempotency_key_unsupported","invalid_request"],"x-mcp":{"tool":false,"reason":"Webhook endpoints hold signing secrets for your own server; set them up with an API key (POST /v1/webhook-endpoints) or with the account holder's map.audio sign-in."}}},"/v1/provenance/{id}":{"get":{"operationId":"getProvenance","tags":["Provenance"],"summary":"Get a provenance record","description":"A render's signed provenance record: the engine image, seed, presets, inputs and outputs with their SHA-256, the licence the render was made under, and that no AI model made the audio. Public, so anyone holding a record id can check it: verify `signature` (Ed25519 over the record's JSON with sorted keys and without `signature`) with the key in GET /.well-known/jwks.json whose `kid` matches. Free.","security":[],"parameters":[{"$ref":"#/components/parameters/ProvenanceId"}],"responses":{"200":{"description":"The record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Provenance"},"examples":{"render":{"summary":"A render of 313 Disco","value":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":42,"presets":[{"ref":"pam:factory/313-disco","sha256":"3afbf5dea1003b2d17385955017785a57d74c65f77f97b58cf5d7cec9794ca1c"}],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:jsfkW3eF1r4kChqccp6AKLTvjTK5Re8acrEusqigz7MDUu6uZhsJXVnuQEl6EsErDgVYNXOkos9d0mMyt2CVCg"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No provenance record with that id; a job's result.provenance.id names its record.","param":"id","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["not_found","rate_limited","invalid_request"],"x-mcp":{"tool":false,"reason":"Public and unauthenticated: read it with a plain GET. get_job already returns each render's provenance record."}}},"/.well-known/jwks.json":{"get":{"operationId":"getJwks","tags":["Provenance"],"summary":"Get the provenance signing keys","description":"The public keys (Ed25519, as JWKs) that sign provenance records; pick the one whose `kid` matches a record's. Public. Free.","security":[],"responses":{"200":{"description":"JWKS.","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object"}}}},"examples":{"keys":{"summary":"One signing key","value":{"keys":[{"kty":"OKP","crv":"Ed25519","x":"r7VbRk8sQ1mN4pT6yW2cE9hJ3uL5aF0dG7iK1oZ2qXs","kid":"6c2f0a9d4b7e1358","use":"sig","alg":"EdDSA"}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"internal_error":{"summary":"Internal error","value":{"error":{"type":"unavailable","code":"internal_error","message":"Something went wrong on our side; nothing was charged.","param":null,"retryable":true,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#internal_error","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":[],"x-mcp":{"tool":false,"reason":"Public keys for checking provenance; fetch them with a plain GET."}}},"/v1/openapi.json":{"get":{"operationId":"getOpenApi","tags":["Catalogue"],"summary":"Get this OpenAPI document","description":"This document, with `servers` set to the origin that served it. Public. Free.","security":[],"responses":{"200":{"description":"OpenAPI 3.1.","content":{"application/json":{"schema":{"type":"object"},"examples":{"document":{"summary":"The document (shortened)","value":{"openapi":"3.1.0","info":{"title":"MAP Audio Music API","version":"2026-11-01"},"servers":[{"url":"https://api.map.audio"}]}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"internal_error":{"summary":"Internal error","value":{"error":{"type":"unavailable","code":"internal_error","message":"Something went wrong on our side; nothing was charged.","param":null,"retryable":true,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#internal_error","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":[],"x-mcp":{"tool":false,"reason":"This document; MCP clients get the same schemas from tools/list."}}},"/v1/billing/checkout":{"post":{"operationId":"createBillingCheckout","tags":["Account"],"summary":"Buy a tier or render-minutes","description":"Open a Stripe Checkout page to subscribe to a paid tier or to buy render-minutes; the tier or credits apply once Stripe confirms the payment. Send `tier` or `renderMinutes`, not both. Needs a map.audio sign-in on MAP Audio's own pages, as https://map.audio/music uses; an API key or another app cannot buy. Answers with a URL for a person to open in a browser.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingCheckout"},"examples":{"tier":{"summary":"Subscribe to Pro","value":{"tier":"pro","consent":{"analytics":"granted","advertising":"denied"}}},"credits":{"summary":"Buy 500 render-minutes","value":{"renderMinutes":500}}}}}},"responses":{"200":{"description":"A Stripe Checkout page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingLink"},"examples":{"checkout":{"summary":"Checkout","value":{"object":"billing_link","url":"https://checkout.stripe.com/c/pay/cs_live_a1B2c3D4e5F6g7H8i9J0kLmNoPqRsTuVwXyZ"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"409":{"description":"Already subscribed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"subscription_exists":{"summary":"Already subscribed","value":{"error":{"type":"conflict","code":"subscription_exists","message":"This account already subscribes to a plan; change or cancel it from the billing portal (POST /v1/billing/portal).","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#subscription_exists","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["oauth_required","terms_required","subscription_exists","billing_rate_limited","billing_unavailable","invalid_request","unsupported_media_type","payload_too_large","idempotency_key_unsupported"],"x-mcp":{"tool":false,"reason":"Spends money on a Stripe page a person completes in a browser; only MAP Audio's own pages may open one."}}},"/v1/billing/portal":{"post":{"operationId":"createBillingPortal","tags":["Account"],"summary":"Open the billing portal","description":"Open the Stripe billing portal, where a subscriber changes plan or card, cancels and reads invoices. Needs a map.audio sign-in on MAP Audio's own pages. It does not wait on the terms, so a subscription can always be cancelled.","responses":{"200":{"description":"The billing portal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingLink"},"examples":{"portal":{"summary":"Portal","value":{"object":"billing_link","url":"https://billing.stripe.com/p/session/live_YWNjdF8xUHFSc1R1VndYeVo"}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"409":{"description":"No billing account yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"billing_not_available":{"summary":"No billing account yet","value":{"error":{"type":"conflict","code":"billing_not_available","message":"Nothing has been bought on this account yet, so it has no billing portal; buy with POST /v1/billing/checkout.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#billing_not_available","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["oauth_required","billing_not_available","billing_rate_limited","billing_unavailable","idempotency_key_unsupported"],"x-mcp":{"tool":false,"reason":"Spends money on a Stripe page a person completes in a browser; only MAP Audio's own pages may open one."}}},"/v1/audio/analyze":{"post":{"operationId":"audioAnalyze","tags":["Commands"],"summary":"Measure audio loudness and peaks (BS.1770).","description":"Measure audio this account holds, such as a render's master: loudness (BS.1770), true peak, spectrum, stereo image, tempo, key, sections and defects. Send file ids from a job's `result.outputs`; the measurements come back in `result.command`, under `files` when you send more than one. Run it on a render before you keep or deliver it, or to compare seeds. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","minItems":1,"maxItems":16,"items":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"description":"Ids (file_…) of WAV or FLAC audio this account holds, at most 16."},"peaks":{"type":"boolean","description":"Include the existing 48-bin RMS envelope."},"pitch":{"type":"boolean","description":"Estimate mono pitch and confidence."},"class":{"type":"boolean","description":"Classify the mono sample and report measured features."},"spectrum":{"type":"boolean","description":"Long-term third-octave spectrum of mid and side, and each band's energy share (sub, low, lowMid, mid, highMid, air), relative to the file's total energy from 20 Hz to 20 kHz."},"stereo":{"type":"boolean","description":"Side minus mid and L/R correlation per band, and the mono fold-down's loudness difference."},"hpss":{"type":"boolean","description":"Harmonic, percussive and residual energy shares from the Transient card's spectral split (HpssCore, FIRM)."},"sections":{"type":"boolean","description":"Section boundaries from Foote novelty over third-octave features, with each section's loudness and true peak."},"transients":{"type":"boolean","description":"Transient times from the sampler's transient detector."},"beats":{"type":"boolean","description":"Tempo in BPM, its confidence and the first downbeat, from the DJ view's beat tracker; a tempo in the file name (\"loop 92 BPM.wav\") fixes the octave."},"musicalKey":{"type":"boolean","description":"Musical key (\"A minor\") with its Camelot code and confidence, from the DJ view's key estimate."},"levels":{"type":"boolean","description":"Level statistics: RMS, PLR (true peak minus integrated), PSR (3 s true peak minus short-term loudness, median and lowest), the loudest momentary and short-term loudness, block crest and level swing."},"validity":{"type":"boolean","description":"File defects: non-finite samples with the first frame and channel, subnormals, DC offset, clipped samples, where sound starts and ends, and the level of the last 100 ms."},"timbre":{"type":"boolean","description":"Timbre: spectral centroid, spread, skewness, kurtosis and 95% rolloff in Hz, flatness and crest in dB (median and 90th percentile over the frames within 60 dB of the loudest) across 20 Hz-20 kHz and per broad band, MFCCs 1-13 (mean and standard deviation) and each pitch class's share of the power (chroma, C first)."},"compare":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"Compare with a reference file at the same rate, such as a render's input, lined up by `latency`: the null raw, after one best gain and after the best linear filter, the largest and RMS sample difference, the residual per broad band, gain and coherence per third octave, the envelope change per band, and MFCC and chroma distances. The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"latency":{"type":"integer","description":"Frames the file lags the `compare` reference by, such as a render's latencySamples.","minimum":-8388608,"maximum":8388608,"default":0},"thd":{"type":"number","description":"A steady tone's distortion at this frequency in Hz, over the whole file: harmonics in dBc, THD, THD+N, the even harmonics' share and the worst spur.","minimum":1,"maximum":192000},"imd":{"type":"string","description":"A steady twin tone's intermodulation, its two frequencies in Hz as 19000,20000: the difference tone and all products against the pair."},"window":{"type":"number","description":"Adds a per-window series of `spectrum`, `stereo` and `hpss` values, this many seconds a window, at most 256 windows.","minimum":0.5,"maximum":3600},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["files"],"additionalProperties":false},"examples":{"example":{"summary":"Check a render's loudness and look for defects","value":{"files":["file_01M6BPRK0M34NBP2XKJ1RMX1TQ"],"levels":true,"validity":true}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioAnalyze","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[],"seed":null,"command":{"ok":true,"path":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","format":"wav","sampleRate":48000,"channels":2,"durationSeconds":16,"integratedLufs":-9.6,"loudnessRange":3.8,"truePeakDb":-0.7,"samplePeakDb":-1.1,"levels":{"rmsDbfs":-11.4,"plrDb":8.9,"psrDb":7.6,"minPsrDb":5.2,"maxMomentaryLufs":-6.9,"maxShortTermLufs":-8.3,"crestDb":10.3,"swingDb":6.1},"validity":{"nonFinite":{"count":0,"firstFrame":null,"firstChannel":null,"firstSeconds":null},"subnormals":0,"dc":[0.0001,-0.0001],"dcDbfs":-80,"clipping":{"threshold":0.99997,"samples":0,"firstSeconds":null},"firstAudibleSeconds":0,"lastAudibleSeconds":15.98,"tailRmsDbfs":-31.2}},"provenance":null},"error":null,"usage":{"renderMinutes":0,"audioSeconds":0,"computeMs":184},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioAnalyze","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No file with that id; GET /v1/files lists this account's files.","param":"files[0]","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"audio_analyze"},"x-pam-command":{"argv":["audio","analyze"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["worker","native"],"meters":["analysisSeconds"],"resultFields":["ok","path","format","sampleRate","channels","durationSeconds","integratedLufs","loudnessRange","truePeakDb","samplePeakDb","spectrum","stereo","hpss","sections","sectionMethod","transients","tempo","key","levels","validity","timbre","compare","thd","imd","spectrogram","series","versions"],"excluded":{"offset":"Pages a batch of results to fit the local MCP's message size; the API returns every file's result in the job.","page-size":"Pages a batch of results to fit the local MCP's message size; the API returns every file's result in the job.","spectrogram":"Writes a PNG image to a local path; the API returns no images yet."}}}},"/v1/audio/normalize":{"post":{"operationId":"audioNormalize","tags":["Commands"],"summary":"Normalize loudness and verify a true-peak ceiling.","description":"Bring a file to a loudness target under a true-peak ceiling, for a platform's delivery spec (-14 LUFS and -1 dBTP unless you send others). Writes a new WAV and reports the loudness it reached; the source file stays as it was. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"lufs":{"type":"number","description":"Target integrated LUFS; achieved loudness is reported if the peak ceiling prevents the target.","minimum":-60,"maximum":0,"default":-14},"tp":{"type":"number","description":"Maximum measured true peak in dBTP.","minimum":-24,"maximum":0,"default":-1},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["file"],"additionalProperties":false},"examples":{"example":{"summary":"Normalize a render to -14 LUFS with a -1 dBTP ceiling","value":{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","lufs":-14,"tp":-1}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioNormalize","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":4608044,"format":"wav","sampleRate":48000,"durationSeconds":16,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":null,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"channels":2,"durationSeconds":16,"integratedLufs":-14,"truePeakDb":-1.4,"targetReached":true},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":null,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":16,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioNormalize","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"410":{"description":"File no longer stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"file_expired":{"summary":"File no longer stored","value":{"error":{"type":"gone","code":"file_expired","message":"File file_01M6BPRK0M34NBP2XKJ1RMX1TQ expired at 2026-11-08T14:03:41.877Z; render it again.","param":"file","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#file_expired","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"audio_normalize"},"x-pam-command":{"argv":["audio","normalize"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["native"],"meters":["editSeconds"],"resultFields":[],"excluded":{}}}},"/v1/audio/repitch":{"post":{"operationId":"audioRepitch","tags":["Commands"],"summary":"Render varispeed pitch shifting using the browser repitch core.","description":"Shift a file's pitch by varispeed, as a turntable does: tempo and length move with the pitch, so 12 semitones down plays at half speed. Writes a new WAV. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"semitones":{"type":"number","description":"Varispeed pitch shift; duration changes.","minimum":-24,"maximum":24,"default":0},"cents":{"type":"number","description":"Additional pitch shift in cents.","minimum":-100,"maximum":100,"default":0},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["file"],"additionalProperties":false},"examples":{"example":{"summary":"Drop a loop two semitones","value":{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","semitones":-2}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioRepitch","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":5172236,"format":"wav","sampleRate":48000,"durationSeconds":17.959,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":null,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"channels":2,"durationSeconds":17.959},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":null,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":17.959,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioRepitch","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"semitones must be at most 24; got 30.","param":"semitones","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"audio_repitch"},"x-pam-command":{"argv":["audio","repitch"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["native"],"meters":["editSeconds"],"resultFields":[],"excluded":{}}}},"/v1/audio/trim":{"post":{"operationId":"audioTrim","tags":["Commands"],"summary":"Trim a sample by time using the shared sample-edit core.","description":"Cut a file to a time range in seconds, such as a loop's first bars or a hit without its lead-in. Writes a new WAV. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"start":{"type":"number","description":"Trim start in seconds.","minimum":0,"maximum":86400,"default":0},"end":{"type":"number","description":"Trim end in seconds; absent uses file end.","minimum":0,"maximum":86400},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["file"],"additionalProperties":false},"examples":{"example":{"summary":"Keep the first 8 seconds","value":{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","start":0,"end":8}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioTrim","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":2304044,"format":"wav","sampleRate":48000,"durationSeconds":8,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":null,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"channels":2,"durationSeconds":8},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":null,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":8,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioTrim","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"end (2 s) must be after start (4 s).","param":"end","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"audio_trim"},"x-pam-command":{"argv":["audio","trim"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["native"],"meters":["editSeconds"],"resultFields":[],"excluded":{}}}},"/v1/audio/gain":{"post":{"operationId":"audioGain","tags":["Commands"],"summary":"Apply sample gain using the shared sample-edit core.","description":"Raise or lower a file's level by a number of decibels; samples past full scale clip. For a loudness target, POST /v1/audio/normalize measures and sets the level for you. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"db":{"type":"number","description":"Gain in decibels; samples exceeding full scale clip in the output WAV.","minimum":-96,"maximum":48},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["file","db"],"additionalProperties":false},"examples":{"example":{"summary":"Turn a render down 3 dB","value":{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","db":-3}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioGain","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":4608044,"format":"wav","sampleRate":48000,"durationSeconds":16,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":null,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"channels":2,"durationSeconds":16},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":null,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":16,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioGain","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"db is required.","param":"db","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"audio_gain"},"x-pam-command":{"argv":["audio","gain"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["native"],"meters":["editSeconds"],"resultFields":[],"excluded":{}}}},"/v1/audio/reverse":{"post":{"operationId":"audioReverse","tags":["Commands"],"summary":"Reverse a sample using the shared sample-edit core.","description":"Play a file backwards, for reverse cymbals, risers and transitions. Writes a new WAV. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["file"],"additionalProperties":false},"examples":{"example":{"summary":"Reverse a render","value":{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ"}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioReverse","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":4608044,"format":"wav","sampleRate":48000,"durationSeconds":16,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":null,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"channels":2,"durationSeconds":16},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":null,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":16,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioReverse","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"not_found":{"summary":"Not found","value":{"error":{"type":"not_found","code":"not_found","message":"No file with that id; GET /v1/files lists this account's files.","param":"file","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#not_found","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"audio_reverse"},"x-pam-command":{"argv":["audio","reverse"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["native"],"meters":["editSeconds"],"resultFields":[],"excluded":{}}}},"/v1/preset/render":{"post":{"operationId":"presetRender","tags":["Commands"],"summary":"Render a PAM preset to WAV without opening PAM.","description":"The engine's own render command: one factory preset to one WAV, with optional stems and an input file that the preset's External cells play. POST /v1/renders is the render API for everything else (FLAC and MP3, variation and seed batches, cutdowns, quality search, previews); use this route for an input file or the exact `pam preset render` options. It costs render-minutes for the audio it renders: its length in minutes, at least 0.1 a render. Answers 202 with the queued job: poll `GET /v1/jobs/{id}`, stream `GET /v1/jobs/{id}/events`, or send `Prefer: wait=N` (at most 60 s) to get the finished job in this response.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preset":{"type":"string","maxLength":200,"description":"A factory preset reference, pam:factory/<slug> or the bare slug; GET /v1/presets lists them."},"seconds":{"type":"number","description":"Render length in seconds; mutually exclusive with `bars`. Defaults to the input duration for fx and audio master.","minimum":0.001,"maximum":300},"bars":{"type":"integer","description":"Length in bars (1..64): pattern generation uses four beats and defaults to 1; preset rendering uses the preset time signature and defaults to 4.","minimum":1,"maximum":64},"sampleRate":{"type":"integer","description":"Output sample rate.","minimum":22050,"maximum":48000,"default":48000},"tail":{"type":"number","description":"Additional effect tail in seconds after transport stops.","minimum":0,"maximum":30,"default":0},"seed":{"type":"integer","description":"Reproducible seed; zero draws a random seed.","minimum":0,"maximum":4294967295,"default":0},"variation":{"type":"integer","description":"Preset variation, numbered from 1.","minimum":1,"maximum":16},"stems":{"type":"boolean","description":"Write each cell stem alongside the master in one render pass."},"input":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"Audio played into the engine's input, through the PAM cells whose source is External. Without `seconds` or `bars` the render lasts as long as the input, plus `tail`. The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["preset"],"additionalProperties":false},"examples":{"example":{"summary":"Render 8 bars of 313 Disco with a fixed seed","value":{"preset":"pam:factory/313-disco","bars":8,"seed":42}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"presetRender","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":4608044,"format":"wav","sampleRate":48000,"durationSeconds":16,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":42,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"durationSeconds":16,"seed":42,"stems":[],"latencySamples":0},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":42,"presets":[{"ref":"pam:factory/313-disco","sha256":"3afbf5dea1003b2d17385955017785a57d74c65f77f97b58cf5d7cec9794ca1c"}],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0.267,"audioSeconds":16,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The queued job; poll `urls.self` or stream `urls.events`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"queued":{"summary":"Queued","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"presetRender","status":"queued","livemode":false,"sequence":1,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":null,"estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"402":{"description":"Not enough render-minutes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"insufficient_credits":{"summary":"Not enough render-minutes","value":{"error":{"type":"entitlement","code":"insufficient_credits","message":"This job needs 0.267 render-minutes and 0.012 remain this month; make it shorter, or buy render-minutes at https://map.audio/music.","param":null,"details":{"needed":0.267,"remaining":0.012},"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#insufficient_credits","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","insufficient_credits","render_too_long","preset_not_found","preset_not_served","variation_not_found","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"preset_render"},"x-pam-command":{"argv":["preset","render"],"tier":"paid","paidWhen":[],"mode":"async","runtimes":["native"],"meters":["audioSeconds"],"resultFields":["ok","wavPath","sampleRate","durationSeconds","seed","stems","latencySamples"],"excluded":{"product":"The API renders PAM presets only; MFX presets wait on MFX's own licence check for server renders (#1719).","song":"Song arrangements are not served yet: every factory preset is listed with hasSong false, so render bars or seconds instead."}}}},"/v1/project/remix":{"post":{"operationId":"projectRemix","tags":["Commands"],"summary":"Remix an Ableton Live set, Bitwig project, DAWproject or FL Studio project into a PAM preset built from its own samples, MIDI and sections.","description":"Turn an uploaded DAW project (Ableton Live, Bitwig, DAWproject or FL Studio) into a PAM preset built from its own samples, MIDI and sections, returned as a .zip that holds the preset and its samples. Free: it counts in GET /v1/usage, never in render-minutes. Answers 202 with the queued job: poll `GET /v1/jobs/{id}`, stream `GET /v1/jobs/{id}/events`, or send `Prefer: wait=N` (at most 60 s) to get the finished job in this response. Needs uploads, which stay off until the decoder and project-reader fuzzers have run; until then it answers 403 uploads_disabled.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"project":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of an uploaded DAW project or zipped project folder."},"seed":{"type":"integer","description":"Seed for the remix variations; absent or zero derives one from the project, so the same project remixes the same way as a drop into PAM.","minimum":0,"maximum":4294967295,"default":0},"name":{"type":"string","description":"Preset name; absent uses the project file name followed by Remix."},"faithful":{"type":"boolean","description":"Keep only the project's own sections; skip PAM's remix variations and song tail."},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["project"],"additionalProperties":false},"examples":{"example":{"summary":"Remix an uploaded Live set with a fixed seed","value":{"project":"file_01M6BPRR00A11F2KEPGNR7V3Q9","seed":7}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"projectRemix","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[{"role":"preset","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":18734,"format":"zip","sampleRate":null,"durationSeconds":null,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":7,"command":{"ok":true,"presetPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","bundled":true,"presetName":"Night Drive Remix","bpm":124,"timeSignature":"4/4","seed":7,"variations":["Intro","Groove","Break","Drop"],"missingSampleCount":0,"warnings":[]},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":7,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRR00A11F2KEPGNR7V3Q9","sha256":"e20c37e5e2607bde5dfd78c1fe0b7fd000e0209a38b9e4eb963d14cfe7191b16"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":0,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The queued job; poll `urls.self` or stream `urls.events`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"queued":{"summary":"Queued","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"projectRemix","status":"queued","livemode":false,"sequence":1,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"403":{"description":"Uploads not open yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"uploads_disabled":{"summary":"Uploads not open yet","value":{"error":{"type":"entitlement","code":"uploads_disabled","message":"POST /v1/project/remix works on uploaded files, and uploads are not open yet. Nothing was charged.","param":null,"retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#uploads_disabled","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"project_remix"},"x-pam-command":{"argv":["project","remix"],"tier":"free","paidWhen":[],"mode":"async","runtimes":["native"],"meters":["remixes"],"resultFields":["ok","presetPath","bundled","presetName","source","bpm","cells","variations","song","missingSamples","warnings","seed","creator","timeSignature","droppedVoices","missingSampleCount","vendorLibrarySamples"],"excluded":{"samples":"Names a local folder to search for missing samples; the API reads only the uploaded project and the audio it embeds.","bundle":"The API always bundles: the result is one .zip holding the preset and copies of its samples."}}}},"/v1/fx":{"post":{"operationId":"fx","tags":["Commands"],"summary":"Render a PAM cell effect chain over an audio file.","description":"Run a file through PAM's cell effects: one cell's chain (delay, flanger, crusher, EQ and the rest of the cell rack), set as PAM parameters in `chain`. Without bars or seconds the render lasts as long as the file, plus `tail`. It costs render-minutes for the audio it renders: its length in minutes, at least 0.1 a render. Answers 202 with the queued job: poll `GET /v1/jobs/{id}`, stream `GET /v1/jobs/{id}/events`, or send `Prefer: wait=N` (at most 60 s) to get the finished job in this response.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"seconds":{"type":"number","description":"Render length in seconds; mutually exclusive with `bars`. Defaults to the input duration for fx and audio master.","minimum":0.001,"maximum":300},"bars":{"type":"integer","description":"Length in bars (1..64): pattern generation uses four beats and defaults to 1; preset rendering uses the preset time signature and defaults to 4.","minimum":1,"maximum":64},"sampleRate":{"type":"integer","description":"Output sample rate.","minimum":22050,"maximum":48000,"default":48000},"tail":{"type":"number","description":"Additional effect tail in seconds after transport stops.","minimum":0,"maximum":30,"default":0},"seed":{"type":"integer","description":"Reproducible seed; zero draws a random seed.","minimum":0,"maximum":4294967295,"default":0},"chain":{"type":"object","description":"A PAM state fragment as a JSON object: for fx, cell1_* settings, cell1_effectOrder and cells.1.effectConfig, or the same as {params, effectConfig, effectOrder} without the cell1_ prefix; master* settings for audio master."},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["file","chain"],"additionalProperties":false},"examples":{"example":{"summary":"Put a render through a feedback delay with a 2-second tail","value":{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","chain":{"params":{"delayMix":30,"delayFeedback":45},"effectConfig":{"delayEnabled":true},"effectOrder":["delay"]},"tail":2}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"fx","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":18,"renderMinutes":0.3},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":5184044,"format":"wav","sampleRate":48000,"durationSeconds":18,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":1795302311,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"durationSeconds":18,"seed":1795302311,"stems":[],"latencySamples":0},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":1795302311,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0.3,"audioSeconds":18,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The queued job; poll `urls.self` or stream `urls.events`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"queued":{"summary":"Queued","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"fx","status":"queued","livemode":false,"sequence":1,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":null,"estimate":{"audioSeconds":18,"renderMinutes":0.3},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"chain must be a JSON object; got a string.","param":"chain","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","insufficient_credits","render_too_long","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"fx"},"x-pam-command":{"argv":["fx"],"tier":"paid","paidWhen":[],"mode":"async","runtimes":["native"],"meters":["audioSeconds"],"resultFields":["ok","wavPath","sampleRate","durationSeconds","seed","stems","latencySamples"],"excluded":{}}}},"/v1/audio/master":{"post":{"operationId":"audioMaster","tags":["Commands"],"summary":"Render the PAM master effect chain over an audio file.","description":"Run a file through PAM's master chain (EQ, compression, tape, clipping, limiting and the other master stages), set as master* parameters in `chain`. For loudness alone, POST /v1/audio/normalize is free. It costs render-minutes for the audio it renders: its length in minutes, at least 0.1 a render. Answers 202 with the queued job: poll `GET /v1/jobs/{id}`, stream `GET /v1/jobs/{id}/events`, or send `Prefer: wait=N` (at most 60 s) to get the finished job in this response.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"file":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"seconds":{"type":"number","description":"Render length in seconds; mutually exclusive with `bars`. Defaults to the input duration for fx and audio master.","minimum":0.001,"maximum":300},"bars":{"type":"integer","description":"Length in bars (1..64): pattern generation uses four beats and defaults to 1; preset rendering uses the preset time signature and defaults to 4.","minimum":1,"maximum":64},"sampleRate":{"type":"integer","description":"Output sample rate.","minimum":22050,"maximum":48000,"default":48000},"tail":{"type":"number","description":"Additional effect tail in seconds after transport stops.","minimum":0,"maximum":30,"default":0},"seed":{"type":"integer","description":"Reproducible seed; zero draws a random seed.","minimum":0,"maximum":4294967295,"default":0},"chain":{"type":"object","description":"A PAM state fragment as a JSON object: for fx, cell1_* settings, cell1_effectOrder and cells.1.effectConfig, or the same as {params, effectConfig, effectOrder} without the cell1_ prefix; master* settings for audio master."},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["file","chain"],"additionalProperties":false},"examples":{"example":{"summary":"Master a render with a gentle tilt, glue compression and tape","value":{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","chain":{"masterEqEnabled":1,"masterEqTilt":-1.5,"masterCompressorEnabled":1,"masterCompThreshold":-18,"masterCompRatio":2,"masterTapeEnabled":1,"masterTapeDrive":0.35}}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioMaster","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":4608044,"format":"wav","sampleRate":48000,"durationSeconds":16,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":2290871365,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"durationSeconds":16,"seed":2290871365,"stems":[],"latencySamples":0},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":2290871365,"presets":[],"packs":[],"userFiles":[],"inputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0.267,"audioSeconds":16,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The queued job; poll `urls.self` or stream `urls.events`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"queued":{"summary":"Queued","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"audioMaster","status":"queued","livemode":false,"sequence":1,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":null,"estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"409":{"description":"File not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"file_not_ready":{"summary":"File not ready","value":{"error":{"type":"conflict","code":"file_not_ready","message":"File file_01M6BPRK0M34NBP2XKJ1RMX1TQ is still being written by job_01M6BPRE186QHP9QPYGDX5NNFP; retry when that job succeeds.","param":"file","retryable":true,"jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","docUrl":"https://map.audio/developers/music-api/errors#file_not_ready","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","insufficient_credits","render_too_long","not_found","file_not_ready","file_expired","uploads_disabled"],"x-mcp":{"tool":"audio_master"},"x-pam-command":{"argv":["audio","master"],"tier":"paid","paidWhen":[],"mode":"async","runtimes":["native"],"meters":["audioSeconds"],"resultFields":["ok","wavPath","sampleRate","durationSeconds","seed","stems","latencySamples"],"excluded":{}}}},"/v1/state":{"post":{"operationId":"state","tags":["Commands"],"summary":"Apply state envelopes to Init, a preset or a point between two presets in the headless PAM engine, read the resulting state and optionally render it.","description":"Run PAM's engine headless on a preset's state: apply envelopes (parameter changes), morph toward another preset or variation, or blend presets, then read the resulting state or render it. Without `render` it is free and answers at once; with `render: true` it renders like POST /v1/renders and also returns the session as a .preset file. Free without render; with render: true it costs render-minutes for the audio it renders. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll; with render: true it waits only as long as `Prefer: wait` asks.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preset":{"type":"string","maxLength":200,"description":"A factory preset reference, pam:factory/<slug> or the bare slug; GET /v1/presets lists them."},"envelopes":{"type":["object","array"],"description":"State envelopes ({delta, options?}, or {directNodeOps, options?} without a delta) applied in order, as a JSON array or object."},"keys":{"type":"string","description":"Top-level state keys to return, as a comma list or a JSON array; absent keys are listed in missingKeys."},"tempo":{"type":"number","description":"Transport tempo in beats per minute before the envelopes apply.","minimum":20,"maximum":999},"playing":{"type":"boolean","description":"Start the transport before the envelopes apply."},"variation":{"type":"integer","description":"Preset variation, numbered from 1.","minimum":1,"maximum":16},"morphTo":{"type":"string","maxLength":200,"description":"Preset to morph toward, from the preset argument or Init, at the position `at` gives. Below 1 the session stays the start's and only its parameters move; from 1 it is this preset's. A factory preset reference, pam:factory/<slug> or the bare slug; GET /v1/presets lists them."},"toVariation":{"type":"integer","description":"Variation, numbered from 1, the morph moves toward: of the `morphTo` preset, or of the preset argument without `morphTo`.","minimum":1,"maximum":16},"at":{"type":"number","description":"Morph position: 0 is the start, 1 the target. Values outside 0..1 extrapolate along the same line, clamped to each parameter's range."},"curve":{"type":"string","description":"Shape applied to `at` between 0 and 1, as a live Glide shapes its window.","enum":["linear","ease","exp","log"],"default":"ease"},"discrete":{"type":"string","description":"When parameters a Glide switches instead of moving (modes, selectors, timing) take the target's value: hold until 1, switch once `at` is above 0, or a threshold between 0 and 1.","default":"hold"},"pattern":{"type":"string","description":"Stage the cells' patterns at `at` as a Steps transition does: dissolve fades the start's steps out and the target's in through their probability, wipe sweeps a frontier through each pattern, cells hands patterns over cell by cell. Without it the patterns stay the start's below 1.","enum":["dissolve","wipe","cells"]},"patternCurve":{"type":"string","description":"Shape applied to `at` for `pattern`, as a live transition shapes its pattern stages.","enum":["linear","ease","exp","log"],"default":"linear"},"patternSeed":{"type":"integer","description":"Decide each step a `pattern` dissolve scaled: a start-only step stays with probability 1 - p and a target-only step arrives with p, drawn from this seed, so the cells hold a concrete pattern. The same seed gives the same steps.","minimum":0,"maximum":4294967295},"relations":{"type":"string","description":"A live Glide's relations: stepped moves a drum synth's pitch through its semitones instead of switching it at the anchor.","enum":["off","stepped"],"default":"off"},"stagger":{"type":"string","description":"A live Glide's cascade: parameters start moving group by group, by cell or by category, over the `staggerSpread` fraction of the window.","enum":["off","cell","category"],"default":"off"},"staggerSpread":{"type":"number","description":"Fraction of the window a `stagger` cascade spreads its groups' starts over; 0 staggers nothing, as in a live transition.","minimum":0,"maximum":0.9,"default":0},"staggerOrder":{"type":"string","description":"Order of a `stagger` cascade: forward starts the first cell or category first.","enum":["forward","reverse"],"default":"forward"},"liveCap":{"type":"boolean","description":"Move only the 1,024 largest moves, as a live Glide does when more parameters differ; the others switch as `discrete` says."},"blend":{"type":"array","minItems":2,"maxItems":16,"items":{"$ref":"#/components/schemas/BlendItem"},"description":"Presets to blend instead of a start and a target, each with a positive weight; weights are relative."},"render":{"type":"boolean","description":"Render the session the envelopes leave to WAV, as preset render renders a preset."},"seconds":{"type":"number","description":"Render length in seconds; mutually exclusive with `bars`. Defaults to the input duration for fx and audio master.","minimum":0.001,"maximum":300},"bars":{"type":"integer","description":"Length in bars (1..64): pattern generation uses four beats and defaults to 1; preset rendering uses the preset time signature and defaults to 4.","minimum":1,"maximum":64},"sampleRate":{"type":"integer","description":"Output sample rate.","minimum":22050,"maximum":48000,"default":48000},"tail":{"type":"number","description":"Additional effect tail in seconds after transport stops.","minimum":0,"maximum":30,"default":0},"seed":{"type":"integer","description":"Reproducible seed; zero draws a random seed.","minimum":0,"maximum":4294967295,"default":0},"stems":{"type":"boolean","description":"Write each cell stem alongside the master in one render pass."},"input":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$","description":"Audio played into the engine's input, through the PAM cells whose source is External. Without `seconds` or `bars` the render lasts as long as the input, plus `tail`. The id (file_…) of WAV or FLAC audio this account holds: a render output, or an upload once uploads open."},"saveSlot":{"type":"integer","description":"Variation slot, numbered from 1, that holds the saved state; the other slots keep the session's bank. Defaults to the slot the session is on.","minimum":1,"maximum":8},"meta":{"type":"object","description":"Metadata for the preset a render saves, as a JSON object: name, author, description, category, tags and the other browser fields."},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":[],"additionalProperties":false,"dependentSchemas":{"seconds":{"properties":{"render":{"const":true}},"required":["render"]},"bars":{"properties":{"render":{"const":true}},"required":["render"]},"sampleRate":{"properties":{"render":{"const":true}},"required":["render"]},"tail":{"properties":{"render":{"const":true}},"required":["render"]},"seed":{"properties":{"render":{"const":true}},"required":["render"]},"stems":{"properties":{"render":{"const":true}},"required":["render"]},"input":{"properties":{"render":{"const":true}},"required":["render"]},"saveSlot":{"properties":{"render":{"const":true}},"required":["render"]},"meta":{"properties":{"render":{"const":true}},"required":["render"]}}},"examples":{"example":{"summary":"Render 8 bars halfway between two variations of Acid Sprinkle","value":{"preset":"pam:factory/acid-sprinkle","variation":1,"toVariation":3,"at":0.5,"render":true,"bars":8,"seed":7}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"state","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":15.484,"renderMinutes":0.258},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":4459436,"format":"wav","sampleRate":48000,"durationSeconds":15.484,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"},{"role":"preset","name":null,"cell":null,"file":"file_01M6BPRPAWG14FNFS6AKGVPEHH","sha256":"da659a796033a280992f3e665c5eb95ebfe7a08b753aa574d84cf70db61b8b29","bytes":18734,"format":"preset","sampleRate":null,"durationSeconds":null,"url":"https://api.map.audio/v1/download/file_01M6BPRPAWG14FNFS6AKGVPEHH?expires=1793545422&signature=oRSM1YDQ_hhkALQN7N4rgA-xKU4SFZlZGkf6rO28LlI","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":7,"command":{"ok":true,"source":{"kind":"preset","path":"pam:factory/acid-sprinkle","variation":1},"applied":0,"render":{"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"channels":2,"durationSeconds":15.484,"seed":7,"stems":[]},"saved":{"presetPath":"file_01M6BPRPAWG14FNFS6AKGVPEHH","name":"session","variation":1,"product":"pam"},"ms":1840},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":7,"presets":[{"ref":"pam:factory/acid-sprinkle","variation":1,"sha256":"eee63255e1350ec8f03f098656befcc3c1c1c23c0bd7933f93fee84071f9279d"}],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"},{"file":"file_01M6BPRPAWG14FNFS6AKGVPEHH","sha256":"da659a796033a280992f3e665c5eb95ebfe7a08b753aa574d84cf70db61b8b29"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0.258,"audioSeconds":15.484,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"state","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":15.484,"renderMinutes":0.258},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"bars needs render: true.","param":"bars","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","insufficient_credits","render_too_long","preset_not_found","preset_not_served","variation_not_found","not_found","file_not_ready","file_expired","uploads_disabled","invalid_envelope"],"x-mcp":{"tool":"state"},"x-pam-command":{"argv":["state"],"tier":"free","paidWhen":["render"],"mode":"sync","runtimes":["native"],"meters":["stateRows","audioSeconds"],"resultFields":["ok","source","applied","state","missingKeys","changed","transport","render","saved","ms","rows","failed","resultsPath","resultsSha256","rendersDir","inputSha256","engine","workers"],"excluded":{"product":"The API renders PAM presets only; MFX presets wait on MFX's own licence check for server renders (#1719).","batch":"A batch reads a JSON-lines file of rows; send one request per row instead, since each render is its own job with its own seed (docs/plans/MUSIC_API.md, Deferred).","workers":"Splits a batch across engine processes; the API takes no batches."}}}},"/v1/dj/set":{"post":{"operationId":"djSet","tags":["Commands"],"summary":"Render a DJ set of PAM presets to WAV, each boundary on its DJ view transition, without opening PAM.","description":"Render a DJ set: factory presets in order, each boundary on its DJ-view transition (blend, drop, rise, break, sweep or fill), as one WAV. Check the set first with POST /v1/arrangements, which costs nothing and returns the boundaries; GET /v1/transition-presets lists the transitions. It costs render-minutes for the audio it renders: its length in minutes, at least 0.1 a render. Answers 202 with the queued job: poll `GET /v1/jobs/{id}`, stream `GET /v1/jobs/{id}/events`, or send `Prefer: wait=N` (at most 60 s) to get the finished job in this response.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"set":{"type":"object","description":"The set to render. `queue` lists its items in play order: `queue[0]` plays first, and each item names a factory preset (`presetPath`, such as pam:factory/313-disco), its variation (`variationIndex`, counted from 0), its length in `bars` and the `transition` into it. `stepBars`, `launchBars`, `defaultTransition` and `tempo` set the defaults; without `tempo.bpm` the set runs at its first preset's tempo, and `auto: false` is refused because a render steps through the set itself. POST /v1/arrangements checks a set without rendering it; GET /v1/transition-presets lists the transition presets, modes and the set schema's definitions."},"sampleRate":{"type":"integer","description":"Output sample rate.","minimum":22050,"maximum":48000,"default":48000},"tail":{"type":"number","description":"Additional effect tail in seconds after transport stops.","minimum":0,"maximum":30,"default":0},"seed":{"type":"integer","description":"Reproducible seed; zero draws a random seed.","minimum":0,"maximum":4294967295,"default":0},"stems":{"type":"boolean","description":"Write each cell stem alongside the master in one render pass."},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":["set"],"additionalProperties":false},"examples":{"example":{"summary":"Three presets at 124 BPM: an 8-bar blend, then a drop","value":{"set":{"queue":[{"presetPath":"pam:factory/acid-sprinkle","bars":16},{"presetPath":"pam:factory/teknochonic","variationIndex":1,"bars":16,"transition":{"preset":"blend","bars":8}},{"presetPath":"pam:factory/breakbeatrcool","variationIndex":2,"bars":16,"transition":{"preset":"drop"}}],"tempo":{"bpm":124}},"seed":42}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"djSet","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":92.903,"renderMinutes":1.548},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":26756108,"format":"wav","sampleRate":48000,"durationSeconds":92.903,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":42,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"durationSeconds":92.903,"seed":42,"stems":[],"boundaries":[{"index":1,"presetPath":"pam:factory/teknochonic","variationIndex":1,"anchorBar":16,"windowBars":8,"mode":"mix","locked":false},{"index":2,"presetPath":"pam:factory/breakbeatrcool","variationIndex":2,"anchorBar":32,"windowBars":0,"mode":"auto","locked":false}],"bpm":124,"timeSig":[4,4],"bars":48},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":42,"presets":[{"ref":"pam:factory/acid-sprinkle","sha256":"eee63255e1350ec8f03f098656befcc3c1c1c23c0bd7933f93fee84071f9279d"},{"ref":"pam:factory/teknochonic","variation":2,"sha256":"a2e6645b2108343284008cd4ef4b8356ab1f4c47dbd9da63a785d893b31a9266"},{"ref":"pam:factory/breakbeatrcool","variation":3,"sha256":"92916c116f9e0a17fd8217a67a98b57063efc8554de0e66b8398053dda7e3296"}],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":1.548,"audioSeconds":92.903,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The queued job; poll `urls.self` or stream `urls.events`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"queued":{"summary":"Queued","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"djSet","status":"queued","livemode":false,"sequence":1,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":null,"estimate":{"audioSeconds":92.903,"renderMinutes":1.548},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Set cannot render as sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"dj_offline_unsupported":{"summary":"Set cannot render as sent","value":{"error":{"type":"invalid_request","code":"dj_offline_unsupported","message":"set.auto false waits for a hand to advance the set, and a render steps through it on its own; leave out auto or send true.","param":"set.auto","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#dj_offline_unsupported","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable","insufficient_credits","render_too_long","preset_not_found","preset_not_served","variation_not_found","dj_invalid_set","dj_offline_unsupported","dj_preset_missing","dj_unknown_transition_preset"],"x-mcp":{"tool":"render_dj_set"},"x-pam-command":{"argv":["dj","set"],"tier":"paid","paidWhen":[],"mode":"async","runtimes":["native"],"meters":["audioSeconds"],"resultFields":["ok","wavPath","sampleRate","durationSeconds","seed","stems","set","boundaries","bpm","timeSig","bars","missingSamples"],"excluded":{"presets":"The API takes the set document as `set`, so each item's preset, variation, length and transition is checked before rendering; POST /v1/arrangements builds or checks one."}}}},"/v1/pattern/generate":{"post":{"operationId":"patternGenerate","tags":["Commands"],"summary":"Generate seeded genre patterns with the shared MIDI corpus; optionally write MIDI.","description":"Generate seeded drum and bass patterns in a genre from PAM's MIDI corpus, returned as notes per cell and a MIDI file. It renders no audio, so it is free; render presets to audio with POST /v1/renders. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"genre":{"type":"string","description":"Pattern genre.","enum":["trap","drill","boombap","dnb","house","techno","idm"],"default":"trap"},"seed":{"type":"integer","description":"Reproducible seed; zero draws a random seed.","minimum":0,"maximum":4294967295,"default":0},"bpm":{"type":"number","description":"MIDI tempo in beats per minute.","minimum":20,"maximum":400,"default":120},"bars":{"type":"integer","description":"Length in bars (1..64): pattern generation uses four beats and defaults to 1; preset rendering uses the preset time signature and defaults to 4.","minimum":1,"maximum":64},"cells":{"type":"string","description":"Comma-separated PAM cell IDs (1..12); factory roles are used.","default":"1,2,3,6"},"density":{"type":"number","description":"Pattern density; absent uses genre default.","minimum":0,"maximum":1},"syncopation":{"type":"number","description":"Pattern syncopation; absent uses genre default.","minimum":0,"maximum":1},"coherence":{"type":"number","description":"Cross-cell pattern coherence.","minimum":0,"maximum":1,"default":0.5},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":[],"additionalProperties":false},"examples":{"example":{"summary":"Four bars of house at 124 BPM","value":{"genre":"house","bpm":124,"bars":4,"seed":42}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"patternGenerate","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":0,"renderMinutes":0},"result":{"outputs":[{"role":"midi","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":1214,"format":"mid","sampleRate":null,"durationSeconds":null,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":42,"command":{"ok":true,"seed":42,"genre":"house","bpm":124,"lengthBeats":16,"roles":{"1":"kick","2":"snare","3":"hihat","6":"bass"},"corpus":true,"midiPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M"},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":42,"presets":[],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":0,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"patternGenerate","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":0,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"genre must be one of trap, drill, boombap, dnb, house, techno or idm; got \"polka\".","param":"genre","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable"],"x-mcp":{"tool":"pattern_generate"},"x-pam-command":{"argv":["pattern","generate"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["native"],"meters":["patterns"],"resultFields":[],"excluded":{}}}},"/v1/synth/drum":{"post":{"operationId":"synthDrum","tags":["Commands"],"summary":"Render procedural drum engines with named controls and timed triggers.","description":"Synthesize drum hits with one of PAM's drum-synth engines (kick, snare, hats, 808 and more), set by named controls in real units, with trigger times for a pattern of hits. It is free; GET /v1/drum-engines lists the engines and their controls. Free: it counts in GET /v1/usage, never in render-minutes. Answers 200 with the finished job when it ends within `Prefer: wait=N` (30 s unless sent, at most 60), else 202 with the job to poll.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"engine":{"type":"string","description":"Drum engine name or id; GET /v1/drum-engines lists them with their controls.","enum":["1","kick","2","snare","3","hihat","4","clap","5","tom","6","fm","7","cymbal","8","cowbell","9","808","10","shaker","11","rim","12","conga","13","bell","14","pluck","15","zap","16","wave","17","chaos","18","stab","19","acoustic-kick","20","acoustic-snare","21","acoustic-cymbal","22","acoustic-hi-hat"],"default":"kick"},"param":{"type":"string","description":"Comma-separated name=value controls in registry units (Hz, seconds, ratios; pct controls use 0..100). Kick: Tune=30..160 note, P.Depth=1..5 ratio, P.Decay=0.005..0.2 time, Decay=0.03..3 time, Click=0..100 percent, Drive=0..100 percent, Tone=150..16000 freq, Wave=0..100 percent; Snare: Tune=120..400 freq, Noise=0..100 percent, Decay=0.03..0.5 time, N.Decay=0.03..0.6 time, N.Tone=800..8000 freq, P.Depth=1..3 ratio, P.Decay=0.005..0.3 time, Drive=0..100 percent; HiHat: Tune=160..640 freq, Decay=0.02..1 time, Tone=2000..12000 freq, Metal=0..100 percent, Noise=0..100 percent; Clap: Freq=400..3500 freq, Spread=0.004..0.02 time, Decay=0.05..2 time, Reso=1..12 num, Drive=0..100 percent; Tom: Tune=80..400 note, P.Depth=1..3 ratio, Decay=0.05..2.5 time, Tone=120..12000 freq, Noise=0..100 percent, Drive=0..100 percent, P.Decay=0.01..0.8 time; FM: Tune=50..1000 note, Ratio=0.5..8 ratio, FM Amt=0..24 num, Decay=0.03..3 time, FM Decay=0..100 percent, F.Back=0..100 percent, Drive=0..100 percent; Cymbal: Tune=140..560 freq, Decay=0.2..4 time, Tone=3000..14000 freq, Metal=0..100 percent, Sizzle=0..100 percent; Cowbell: Tune=300..900 note, Decay=0.08..0.8 time, Ratio=1.2..1.8 ratio, Tone=700..9000 freq, Drive=0..100 percent; 808: Tune=27.5..220 note, P.Depth=0..36 st, P.Time=0.005..0.12 time, Decay=0.1..8 time, Saturate=0..100 percent, Click=0..100 percent, Tone=80..6000 freq; Shaker: Tune=2000..12000 freq, Color=0..100 percent, Onset=0.0005..0.05 time, Decay=0.02..0.6 time, Rattle=0..0.012 time, Tone=0..100 percent; Rim: Tune=200..2500 note, Ring=0..100 percent, Decay=0.015..0.15 time, Partial=1..2.7 ratio, Snap=0..100 percent, Drive=0..100 percent; Conga: Tune=75..700 note, Slap=1..2.5 ratio, Decay=0.08..0.7 time, Partial=1.4..2 ratio, Tone=300..9000 freq, Skin=0..100 percent, Drive=0..100 percent; Bell: Tune=200..1800 note, Ratio=1.4..7 ratio, FM Amt=0..10 num, Decay=0.2..4 time, Inharm=0..100 percent, Strike=0..100 percent, Tone=800..18000 freq; Pluck: Tune=60..1200 note, Sustain=0..100 percent, Damp=0..100 percent, Excite=0..100 percent, Bright=300..12000 freq, Drive=0..100 percent, Decay=0.3..6 time; Zap: Tune=40..2000 note, Sweep=-6..6 num, S.Time=0.02..1 time, Decay=0.03..1.5 time, Timbre=0..100 percent, Noise=0..100 percent, Drive=0..100 percent, Tone=200..14000 freq; Wave: Tune=40..2000 note, Position=0..100 percent, P.Env=1..4 ratio, Decay=0.03..1.5 time, Bright=300..14000 freq, Fold=0..100 percent, Drive=0..100 percent, Draw=0..100 percent; Chaos: Tune=40..6000 note, Chaos=0..100 percent, Decay=0.03..1.2 time, Tone=300..12000 freq, Drive=0..100 percent, Noise=0..100 percent; Stab: Tune=35..1000 note, Shape=0..100 percent, Width=0..100 percent, Chord=0..6 num, Detune=0..100 percent, Decay=0.05..3 time, Tone=200..16000 freq, Drive=0..100 percent; Acoustic Kick: Tune=35..120 note, Punch=1..4 ratio, Decay=0.12..1.8 time, Beater=0..100 percent, Shell=0..100 percent, Damp=0..100 percent, Tone=200..9000 freq, Drive=0..100 percent; Acoustic Snare: Tune=110..440 note, Depth=0..100 percent, Decay=0.08..1.2 time, Snap=0..100 percent, Wires=0..100 percent, Buzz=0.03..0.9 time, Tone=400..12000 freq, Drive=0..100 percent; Acoustic Cymbal: Size=180..900 freq, Strike=0..100 percent, Decay=0.4..8 time, Bell=0..100 percent, Sizzle=0..100 percent, Tone=200..6000 freq, Spread=0..100 percent, Drive=0..100 percent; Acoustic Hi-Hat: Size=260..1100 freq, Open=0..100 percent, Decay=0.08..4.5 time, Strike=0..100 percent, Chatter=0..100 percent, Sizzle=0..100 percent, Tone=1200..16000 freq, Drive=0..100 percent"},"duration":{"type":"number","description":"Duration in seconds.","minimum":0.05,"maximum":30,"default":1},"velocity":{"type":"number","description":"Drum trigger velocity.","minimum":0,"maximum":1,"default":1},"triggers":{"type":"string","description":"Comma-separated trigger times in seconds.","default":"0"},"sampleRate":{"type":"integer","description":"Output sample rate.","minimum":22050,"maximum":48000,"default":48000},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job."}},"required":[],"additionalProperties":false},"examples":{"example":{"summary":"A two-second 808 tuned to 55 Hz","value":{"engine":"808","param":"Tune=55,Decay=1.5","duration":2}}}}}},"responses":{"200":{"description":"The finished job: `result.outputs` link each file it wrote and `result.command` is the engine's own result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"succeeded":{"summary":"Finished","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"synthDrum","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":2,"renderMinutes":0},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4","bytes":576044,"format":"wav","sampleRate":48000,"durationSeconds":2,"url":"https://api.map.audio/v1/download/file_01M6BPRMNR7PYGFNA66BX2YJ8M?expires=1793545422&signature=GQ2GkmPjqXuxxBSSM4NKBCY7OjU7w3YSeZBrCoxxtbY","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":null,"command":{"ok":true,"wavPath":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sampleRate":48000,"channels":2,"durationSeconds":2,"engine":"808"},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":null,"presets":[],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRMNR7PYGFNA66BX2YJ8M","sha256":"13d41d922519699fc14a7587130eceee7d0f149414350000578de1564866a0d4"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:LEVZHpOHj8BMGZgJh-_Y7SmKbqDlBDR8LqY-XelU6GYK8lntZqg3rRK4b3BH8cy25bK0iWzOXFXmkiGHEYue7A"}},"error":null,"usage":{"renderMinutes":0,"audioSeconds":2,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"202":{"description":"The job, still running when `Prefer: wait` ran out; poll `urls.self`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"},"examples":{"running":{"summary":"Still running","value":{"object":"job","id":"job_01M6BPRFPCH9EBPY7B6JKM7CE1","operation":"synthDrum","status":"running","livemode":false,"sequence":2,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":null,"estimate":{"audioSeconds":2,"renderMinutes":0},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1","events":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRFPCH9EBPY7B6JKM7CE1/cancel"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"},"Location":{"$ref":"#/components/headers/Location"},"Retry-After":{"$ref":"#/components/headers/RetryAfter"},"Idempotent-Replayed":{"$ref":"#/components/headers/IdempotentReplayed"},"Preference-Applied":{"$ref":"#/components/headers/PreferenceApplied"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"invalid_request":{"summary":"Invalid request","value":{"error":{"type":"invalid_request","code":"invalid_request","message":"duration must be at most 30; got 45.","param":"duration","retryable":false,"jobId":null,"docUrl":"https://map.audio/developers/music-api/errors#invalid_request","requestId":"9a3f7c2e5b1d8f40-LHR"}}}}}},"headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}}},"default":{"$ref":"#/components/responses/Error"}},"x-error-codes":["invalid_request","unsupported_media_type","payload_too_large","terms_required","concurrency_limit","idempotency_key_reused","idempotency_in_flight","queue_unavailable"],"x-mcp":{"tool":"synth_drum"},"x-pam-command":{"argv":["synth","drum"],"tier":"free","paidWhen":[],"mode":"sync","runtimes":["native"],"meters":["audioSeconds"],"resultFields":[],"excluded":{}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"An API key (`sk_test_` or `sk_live_` followed by 40 letters and digits), or a map.audio OAuth access token for the https://api.map.audio resource with the `audio` scope. Create keys signed in at https://map.audio/music. Test and live keys reach the same account and spend the same render-minutes."},"signIn":{"type":"http","scheme":"bearer","description":"A map.audio OAuth access token for the https://api.map.audio resource with the `audio` scope, belonging to the map.audio account that wants access. API keys are refused here: every key belongs to an account that has access already."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","description":"Makes a retry safe: the same key with the same body answers the job the first request started (with `Idempotent-Replayed: true`) instead of starting and charging another, for 24 hours. Keys are scoped to the account and to test or live mode; the same key with a different body is 409 idempotency_key_reused. Only the POSTs that start a job take it: POST /v1/renders, the command routes and POST /v1/uploads/{id}/complete. Any other POST answers 400 idempotency_key_unsupported.","schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{8,128}$"},"example":"render-313-disco-0001"},"Prefer":{"name":"Prefer","in":"header","description":"`wait=N` holds the response until the job ends, up to N seconds, and answers 200 with the finished job; a job still running then answers 202. N above 60 waits 60, and a value the API cannot read is ignored. Quick commands wait 30 s unless you send this; renders and the longer commands answer at once. `Preference-Applied` names the wait used.","schema":{"type":"string","pattern":"^wait=\\d+$"},"example":"wait=30"},"JobId":{"name":"id","in":"path","required":true,"description":"A job id (job_…), from the response that created the job or GET /v1/jobs.","schema":{"type":"string","pattern":"^job_[0-9A-HJKMNP-TV-Z]{26}$"},"example":"job_01M6BPRE186QHP9QPYGDX5NNFP"},"FileId":{"name":"id","in":"path","required":true,"description":"A file id (file_…), from a job's `result.outputs` or GET /v1/files.","schema":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$"},"example":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ"},"PlanId":{"name":"id","in":"path","required":true,"description":"A plan id (plan_…), from POST /v1/plans.","schema":{"type":"string","pattern":"^plan_[0-9A-HJKMNP-TV-Z]{26}$"},"example":"plan_01M6BPRCC4FTKB29RFYD2JDKJQ"},"ApiKeyId":{"name":"id","in":"path","required":true,"description":"An API key id (key_…), from GET /v1/api-keys; not the secret.","schema":{"type":"string","pattern":"^key_[0-9A-HJKMNP-TV-Z]{26}$"},"example":"key_01M6BPRAQ0QXZ93APJ3C3FRWXZ"},"WebhookEndpointId":{"name":"id","in":"path","required":true,"description":"A webhook endpoint id (whep_…), from GET /v1/webhook-endpoints.","schema":{"type":"string","pattern":"^whep_[0-9A-HJKMNP-TV-Z]{26}$"},"example":"whep_01M6BPRWZCT8J4PSWZ8KG7EXWV"},"ProvenanceId":{"name":"id","in":"path","required":true,"description":"A provenance record id (prov_…), from a job's `result.provenance.id`.","schema":{"type":"string","pattern":"^prov_[0-9A-HJKMNP-TV-Z]{26}$"},"example":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2"},"UploadId":{"name":"id","in":"path","required":true,"description":"The upload's file id (file_…), from POST /v1/uploads.","schema":{"type":"string","pattern":"^file_[0-9A-HJKMNP-TV-Z]{26}$"},"example":"file_01M6BPRR00A11F2KEPGNR7V3Q9"},"PresetId":{"name":"id","in":"path","required":true,"description":"A factory preset's slug (313-disco) or its URL-encoded reference (pam%3Afactory%2F313-disco).","schema":{"type":"string","maxLength":200},"example":"313-disco"}},"responses":{"Error":{"description":"Any other error: `error.code` names it, `error.param` the field at fault, and `error.docUrl` its entry in the error catalogue.","headers":{"Request-Id":{"$ref":"#/components/headers/RequestId"},"Map-Version":{"$ref":"#/components/headers/MapVersion"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"description":"The body of every error response.","properties":{"error":{"allOf":[{"$ref":"#/components/schemas/ErrorObject"}],"type":"object","required":["requestId"],"properties":{"code":{"type":"string","description":"A stable code to branch on. `x-error-codes` is the whole catalogue, with each code's status, type, whether it is retryable, when it happens and what to do.","x-error-codes":{"invalid_request":{"type":"invalid_request","status":400,"retryable":false,"title":"Invalid request","when":"A field, query parameter or header is missing, has the wrong type or is out of range. `param` names it, in the body's own notation (items[0].name).","fix":"Change the field `param` names as the message says, then send the request again."},"not_invited":{"type":"entitlement","status":403,"retryable":false,"title":"No Music API access yet","when":"The map.audio account behind the access token has no Music API account. `details.customerId` names it, `details.emailConfirmed` says whether this sign-in proved its email address, `details.accessRequest` shows any request already sent and `details.requestAccessUrl` is where to ask.","fix":"Request access at https://map.audio/music (or POST /v1/access-requests with the same token). If `details.emailConfirmed` is false and MAP Audio invited your address, sign in again and confirm it with the emailed code. If an invite went to another address, sign in with that address."},"authentication_failed":{"type":"authentication","status":401,"retryable":false,"title":"Authentication failed","when":"The request has no `Authorization: Bearer` header, or its API key or map.audio access token is malformed, quoted, unknown, revoked or issued for another API. The `WWW-Authenticate` header points OAuth clients at the resource metadata.","fix":"Send `Authorization: Bearer` followed by an API key (sk_test_ or sk_live_ and 40 letters and digits) or a current map.audio access token, with nothing around it. The message says which part was wrong."},"insufficient_scope":{"type":"entitlement","status":403,"retryable":false,"title":"Token lacks the audio scope","when":"The map.audio access token was granted without the `audio` scope.","fix":"Sign in again and ask for the `audio` scope; GET /.well-known/oauth-protected-resource lists it."},"auth_unavailable":{"type":"unavailable","status":503,"retryable":true,"title":"Sign-in check unavailable","when":"The map.audio sign-in service could not check the access token just now. API keys do not depend on this check.","fix":"Retry in a few seconds with the same token; signing in again does not help."},"account_suspended":{"type":"entitlement","status":403,"retryable":false,"title":"Account suspended","when":"The Music API account behind this API key or sign-in is suspended: MAP Audio suspended it, or the map.audio customer was erased.","fix":"Email support@map.audio and quote the response's Request-Id."},"customer_erased":{"type":"conflict","status":409,"retryable":false,"title":"Customer erased","when":"The map.audio customer behind this sign-in was erased, so the Music API cannot open an account or take an access request for them.","fix":"This cannot be undone. Email support@map.audio if you think it is a mistake."},"already_has_access":{"type":"conflict","status":409,"retryable":false,"title":"Already has access","when":"POST /v1/access-requests was sent with the access token of a map.audio account that already has Music API access.","fix":"Nothing to request: call the API with the same token, or create API keys at https://map.audio/music."},"access_request_needs_sign_in":{"type":"entitlement","status":403,"retryable":false,"title":"Access requests need a sign-in","when":"POST /v1/access-requests was sent with an API key. A key always belongs to an account that has access, so a request needs the map.audio access token of the account that wants it.","fix":"Sign in at https://map.audio/music with the map.audio account that needs access and request it there, or send that account's access token."},"rate_limited":{"type":"rate_limit","status":429,"retryable":true,"title":"Rate limited","when":"More requests arrived within a minute than a limit allows. The message names the limit and what it counts: one API key, the map.audio sign-ins of one account, the access requests of one account, or one network address.","fix":"Wait the seconds in `Retry-After`, then send again. To follow a job, use `Prefer: wait`, the job's events stream or a webhook rather than polling."},"route_not_found":{"type":"not_found","status":404,"retryable":false,"title":"No such route","when":"No route has this path, whatever the method. The message repeats the method and path, and suggests a route when one is a typo away. A trailing slash is ignored.","fix":"Check the path against the reference at https://map.audio/developers/music-api/reference or GET /v1/openapi.json."},"method_not_allowed":{"type":"invalid_request","status":405,"retryable":false,"title":"Method not allowed","when":"The path exists, but not with this method. The `Allow` header lists the methods it takes; HEAD is answered wherever GET is.","fix":"Send one of the methods in `Allow`. The message names where a related list lives, such as GET /v1/jobs for the jobs a POST route starts."},"unsupported_media_type":{"type":"invalid_request","status":415,"retryable":false,"title":"Unsupported media type","when":"A route that takes a JSON body got one without `Content-Type: application/json`, with another media type, or compressed (`Content-Encoding`). `param` names the header and the message names what was sent.","fix":"Send the body uncompressed, as JSON, with `Content-Type: application/json`. Routes that take no body (cancel, rotate-secret, test, billing portal) need neither."},"version_unsupported":{"type":"invalid_request","status":400,"retryable":false,"title":"API version not served","when":"The `Map-Version` request header names a version this API does not serve. Every response carries the version it answered with in `Map-Version`.","fix":"Send `Map-Version: 2026-11-01`, or leave the header out to get the current version."},"payload_too_large":{"type":"too_large","status":413,"retryable":false,"title":"Body too large","when":"The body is over the route's limit (256 KiB, or 2 MiB on the command routes), an upload declares more bytes than its kind allows, or one JSON field is over 1 MiB. `param` names the field when one is to blame.","fix":"Send less: shorter envelopes or chains, fewer items per request."},"not_found":{"type":"not_found","status":404,"retryable":false,"title":"Not found","when":"No job, file, plan, API key, webhook endpoint or provenance record with that id is visible to this account. `param` names the id (`id` for a path id). Another account's ids answer exactly as missing ones do.","fix":"Check the id against the list route the message names, such as GET /v1/jobs or GET /v1/files; job and plan ids also get their expected shape in the message."},"idempotency_key_unsupported":{"type":"invalid_request","status":400,"retryable":false,"title":"Idempotency-Key not taken here","when":"An `Idempotency-Key` header was sent to a route that does not replay requests. Only routes that start a job take one: POST /v1/renders, the command routes and POST /v1/uploads/{id}/complete.","fix":"Leave the header out on this route. A route that creates something (a key, a webhook endpoint) creates another on a retry, so list first to see whether the first attempt landed."},"idempotency_key_reused":{"type":"conflict","status":409,"retryable":false,"title":"Idempotency-Key reused","when":"This `Idempotency-Key` was used in the last 24 hours with a different route or body.","fix":"Use a new key for a new request. To replay the first answer, send the first request again unchanged."},"idempotency_in_flight":{"type":"conflict","status":409,"retryable":true,"title":"Same request in flight","when":"A request with this `Idempotency-Key` is still being accepted.","fix":"Retry the same request, with the same key, after a few seconds."},"oauth_required":{"type":"entitlement","status":403,"retryable":false,"title":"Needs the account owner's sign-in","when":"Creating or revoking API keys, buying a plan or render-minutes and opening the billing portal need the account owner signed in at https://map.audio/music. Webhook endpoints take an API key or that sign-in. This request used an API key or another app's sign-in.","fix":"Do it at https://map.audio/music, signed in as the account owner."},"terms_required":{"type":"entitlement","status":403,"retryable":false,"title":"Terms not accepted","when":"The account has not accepted the current prototype terms, which every route that starts work needs. Creating an API key without `acceptTerms` on such an account answers this too.","fix":"Read and accept the terms at https://map.audio/music, or send POST /v1/account/terms with {\"accept\": \"2026-11-01-prototype\"}, or call the MCP tool accept_terms. GET /v1/account shows `termsVersion` and `currentTerms`."},"terms_version_mismatch":{"type":"invalid_request","status":400,"retryable":false,"title":"Wrong terms version","when":"`accept` (POST /v1/account/terms) or `acceptTerms` (POST /v1/api-keys) names a terms version other than the current one.","fix":"Send the version GET /v1/account returns as `currentTerms`, today \"2026-11-01-prototype\"."},"too_many_keys":{"type":"entitlement","status":403,"retryable":false,"title":"Key limit reached","when":"The account already holds 10 active API keys.","fix":"Revoke one at https://map.audio/music (or DELETE /v1/api-keys/{id} signed in there), then create the new key."},"too_many_endpoints":{"type":"entitlement","status":403,"retryable":false,"title":"Webhook endpoint limit reached","when":"The account already has 10 webhook endpoints.","fix":"Delete one with DELETE /v1/webhook-endpoints/{id} (GET /v1/webhook-endpoints lists them), then create the new one."},"rotation_in_progress":{"type":"conflict","status":409,"retryable":false,"title":"Secret rotation in progress","when":"The endpoint's previous secret is still valid from the last rotation, or another rotation changed the secret at the same moment.","fix":"Rotate again once the time in the message has passed, or delete the endpoint and create a new one."},"endpoint_disabled":{"type":"conflict","status":409,"retryable":false,"title":"Webhook endpoint disabled","when":"The endpoint was disabled after repeated failed deliveries, or because the API key that set its secret was revoked.","fix":"Rotate its secret with POST /v1/webhook-endpoints/{id}/rotate-secret, which enables it again."},"billing_unavailable":{"type":"unavailable","status":503,"retryable":false,"title":"Billing unavailable","when":"Plans and render-minutes are not on sale on this stage or not yet, or billing could not be reached. The response's `retryable` is true only in the last case.","fix":"When `retryable` is true, try again shortly; otherwise buy on the production API at https://map.audio/music."},"subscription_exists":{"type":"conflict","status":409,"retryable":false,"title":"Already subscribed","when":"The account already subscribes to a plan.","fix":"Change or cancel the plan from the billing portal (POST /v1/billing/portal, signed in at https://map.audio/music)."},"billing_not_available":{"type":"conflict","status":409,"retryable":false,"title":"No billing account yet","when":"Nothing has been bought on this account, so there is no billing portal to open.","fix":"Buy a plan or render-minutes first (POST /v1/billing/checkout)."},"billing_rate_limited":{"type":"rate_limit","status":429,"retryable":true,"title":"Too many billing requests","when":"Too many checkout or billing portal links were requested for this account in the last hour.","fix":"Wait the seconds in `Retry-After`; open the link already returned meanwhile."},"insufficient_credits":{"type":"entitlement","status":402,"retryable":false,"title":"Not enough render-minutes","when":"The job needs more render-minutes than the account has left this month. `details.needed` and `details.remaining` give both.","fix":"Make the job shorter, wait for next month's allowance, or buy render-minutes or a plan at https://map.audio/music."},"concurrency_limit":{"type":"rate_limit","status":429,"retryable":true,"title":"Too many jobs running","when":"The account's plan runs this many jobs at once (2 on the free plan) and all of them are busy.","fix":"Wait the seconds in `Retry-After`, or for a running job to end (`Prefer: wait`, its events or a webhook), then send again."},"queue_unavailable":{"type":"unavailable","status":503,"retryable":true,"title":"Job not queued","when":"The job was admitted but could not be queued. Nothing was charged.","fix":"Send the same request again; with the same `Idempotency-Key` it starts the job afresh."},"internal_error":{"type":"unavailable","status":500,"retryable":true,"title":"Internal error","when":"Something failed on the API's side. Nothing was charged.","fix":"Retry shortly. If it keeps failing, email support@map.audio with the response's Request-Id."},"preset_not_found":{"type":"not_found","status":404,"retryable":false,"title":"No such preset","when":"No factory preset has this slug or reference. `param` names the field.","fix":"Search with GET /v1/presets?q=<words> and send the `ref` (pam:factory/<slug>) it returns."},"preset_not_served":{"type":"invalid_request","status":400,"retryable":false,"title":"Preset not served","when":"The reference names a pack preset, an MFX preset or an uploaded preset. The API renders factory presets only, and no plan changes that.","fix":"Pick a factory preset: GET /v1/presets lists them."},"variation_not_found":{"type":"invalid_request","status":400,"retryable":false,"title":"Variation not in the preset","when":"The preset has no variation in that slot. The message counts as the field does (`variation` from 1, a DJ set's `variationIndex` from 0) and lists the slots the preset has.","fix":"Use a slot from the message; GET /v1/presets/{id} lists a preset's `variations`."},"quality_unavailable":{"type":"invalid_request","status":400,"retryable":false,"title":"Quality not available","when":"`quality` is elite, which waits for a curated archive of rated presets and no plan unlocks yet.","fix":"Send draft or standard."},"render_too_long":{"type":"invalid_request","status":400,"retryable":false,"title":"Render too long","when":"One render would be over 300 s (its length plus tail), or one job over 600 s of audio in all. The message gives the computed length and the fields that set it; `param` names the one to change.","fix":"Lower the field `param` names (bars, seconds, tail, the count of seeds or items), or split the work into more jobs."},"file_not_ready":{"type":"conflict","status":409,"retryable":true,"title":"File not ready","when":"The file is still being written by its job (`jobId` names it, `Retry-After` says when to look again), or it is an upload that has not been completed or checked yet.","fix":"Retry once the job named in `jobId` succeeds, or complete the upload first."},"file_expired":{"type":"gone","status":410,"retryable":false,"title":"File no longer stored","when":"The file expired (outputs are kept 7 days on the free plan) or was deleted, or the account behind a download link was suspended.","fix":"Render it again. GET /v1/files/{id} shows a file's `expiresAt`."},"download_link_invalid":{"type":"authentication","status":403,"retryable":false,"title":"Download link invalid","when":"The signed download link expired (links last an hour) or was altered.","fix":"Ask for a fresh link: GET /v1/jobs/{id} or GET /v1/files/{id}/content."},"uploads_disabled":{"type":"entitlement","status":403,"retryable":false,"title":"Uploads not open yet","when":"The route needs uploaded files (uploads, project remix, or a command naming an upload), and uploads are not open yet. No plan opens them.","fix":"Render from factory presets (GET /v1/presets), and pass render outputs as files, meanwhile."},"upload_closed":{"type":"conflict","status":409,"retryable":false,"title":"Upload closed","when":"The upload was already completed, deleted or rejected.","fix":"Start a new upload with POST /v1/uploads."},"upload_expired":{"type":"gone","status":410,"retryable":false,"title":"Upload window passed","when":"The upload was not completed within 24 hours of being created.","fix":"Start a new upload with POST /v1/uploads."},"upload_incomplete":{"type":"conflict","status":409,"retryable":false,"title":"Upload parts missing","when":"POST /v1/uploads/{id}/complete was sent before every part arrived with its exact size.","fix":"PUT the missing parts (the message says how many arrived), then complete again."},"upload_processing":{"type":"conflict","status":409,"retryable":true,"title":"Upload check starting","when":"Another completion of this upload is starting its check job.","fix":"Retry after the seconds in `Retry-After`."},"checksum_mismatch":{"type":"invalid_request","status":400,"retryable":false,"title":"Upload does not match its checksum","when":"A job found that an uploaded file does not match the SHA-256 its upload declared. It arrives in the failed job's `error`.","fix":"Upload the file again with its correct `sha256`."},"dj_invalid_set":{"type":"invalid_request","status":400,"retryable":false,"title":"Invalid DJ set","when":"The DJ set does not fit its schema (https://map.audio/schemas/pam/dj-set.schema.json). `param` names the field, such as set.queue[0].bars.","fix":"Change that field. POST /v1/arrangements checks a set and shows its timing without rendering."},"dj_offline_unsupported":{"type":"invalid_request","status":400,"retryable":false,"title":"Set cannot render as sent","when":"The set sets `auto` to false. A render steps through the queue on its own.","fix":"Leave `auto` out, or send true."},"dj_preset_missing":{"type":"invalid_request","status":400,"retryable":false,"title":"DJ set preset not found","when":"A preset in the set's queue is not a factory preset. `param` names the item.","fix":"Use references from GET /v1/presets, such as pam:factory/313-disco."},"dj_unknown_transition_preset":{"type":"invalid_request","status":400,"retryable":false,"title":"Unknown transition preset","when":"A transition names a preset a render cannot use; renders hold only the factory transition presets.","fix":"Pick one from GET /v1/transition-presets, or describe the transition with `bars` and `spec`."},"invalid_envelope":{"type":"invalid_request","status":400,"retryable":false,"title":"Invalid state envelope","when":"An item of `envelopes` is not an object with a `delta` object, or with a `directNodeOps` array and no delta, or its `options` is not an object.","fix":"Send each envelope as {\"delta\": {...}} or {\"directNodeOps\": [...]}, with an optional \"options\" object."},"invalid_batch_line":{"type":"invalid_request","status":400,"retryable":false,"title":"Invalid batch line","when":"The engine refused a line of a state batch.","fix":"Change the line the message names."},"unknown_op":{"type":"invalid_request","status":400,"retryable":false,"title":"Unknown operation","when":"The engine was asked for an operation it does not know.","fix":"Check the request against the route's reference."},"invalid_project":{"type":"invalid_request","status":400,"retryable":false,"title":"Invalid project","when":"The uploaded project could not be read.","fix":"Export the project again and upload it."},"unsupported_project":{"type":"invalid_request","status":415,"retryable":false,"title":"Project format not supported","when":"The uploaded project is in a format the engine does not read.","fix":"Upload a supported project format; the remix route's reference lists them."},"project_too_large":{"type":"too_large","status":413,"retryable":false,"title":"Project too large","when":"The uploaded project is over the engine's size limit.","fix":"Upload a smaller project."},"pack_license_required":{"type":"entitlement","status":403,"retryable":false,"title":"Pack licence required","when":"The render host refused a preset that needs a pack licence. The API sends only factory presets, so this means a factory preset referenced pack content.","fix":"Pick another factory preset, and email support@map.audio with the Request-Id."},"license_required":{"type":"unavailable","status":503,"retryable":true,"title":"Render host licence check failed","when":"The render host's licence check failed. Nothing was charged.","fix":"Retry the job."},"resource_exhausted":{"type":"unavailable","status":503,"retryable":true,"title":"Render host out of resources","when":"The render host ran out of memory or another resource. Nothing was charged.","fix":"Retry the job, or make it shorter."},"engine_busy":{"type":"unavailable","status":503,"retryable":true,"title":"Engine busy","when":"The engine was busy with other work. Nothing was charged.","fix":"Retry the job."},"render_busy":{"type":"unavailable","status":503,"retryable":true,"title":"Renderer busy","when":"The renderer was busy with other work. Nothing was charged.","fix":"Retry the job."},"engine_unavailable":{"type":"unavailable","status":503,"retryable":true,"title":"No render host","when":"No render host took the job in time, or one failed three times. Nothing was charged beyond a preview already delivered.","fix":"Send the job again; with a new `Idempotency-Key` it starts afresh."},"timeout":{"type":"engine","status":504,"retryable":false,"title":"Job deadline passed","when":"The job ran past its deadline and was stopped. Nothing was charged.","fix":"Make the job shorter or split it."},"engine_failed":{"type":"engine","status":500,"retryable":true,"title":"Engine failed","when":"The engine failed, or did not write an output it should have. Nothing was charged.","fix":"Retry the job; if it fails again, email support@map.audio with the job id."},"encode_failed":{"type":"engine","status":500,"retryable":false,"title":"Encoding failed","when":"A rendered WAV could not be encoded to the requested format. Nothing was charged.","fix":"Render again with format wav, and email support@map.audio with the job id."},"no_candidate_passed":{"type":"engine","status":422,"retryable":false,"title":"No candidate passed","when":"A quality: standard search rendered every candidate and none passed the limit gate (silence, clipping, loudness). Nothing was charged.","fix":"Try another seed or preset, or another `search.targetLufs`."}}},"requestId":{"type":"string","description":"The request's id, also in the `Request-Id` header."}}}}},"PresetRef":{"type":"string","description":"A factory preset `pam:factory/<slug>`, or its bare slug.","maxLength":200},"PresetSource":{"type":"object","required":["preset"],"additionalProperties":false,"properties":{"preset":{"$ref":"#/components/schemas/PresetRef"},"variation":{"type":"integer","minimum":1,"maximum":16,"description":"A variation slot of the preset, numbered from 1; GET /v1/presets/{id} lists the slots it has. Default: its base state."}},"description":"A factory preset, and optionally one of its variation slots."},"Account":{"type":"object","properties":{"object":{"const":"account"},"id":{"type":"string","description":"The Music API account (acct_…)."},"email":{"type":["string","null"],"description":"The email address the account was opened for, if any."},"status":{"enum":["invited","active","suspended"],"type":"string","description":"`invited` until the account accepts the terms, then `active`."},"termsVersion":{"type":["string","null"],"description":"The terms version the account accepted; null until it accepts."},"limits":{"$ref":"#/components/schemas/Limits","description":"This account's tier limits."},"credits":{"$ref":"#/components/schemas/Credits"},"currentTerms":{"type":"string","description":"The prototype terms version an account must accept before it starts work."},"livemode":{"type":"boolean","description":"`false` for a request made with a test key; `true` for a live key or a map.audio sign-in."}}},"Limits":{"type":"object","properties":{"renderMinutesPerMonth":{"type":"number","description":"The tier's monthly render-minute allowance."},"maxRenderSeconds":{"type":"number","description":"The longest single render, in seconds, tail included."},"maxSampleRate":{"type":"integer","description":"The highest output sample rate, in Hz."},"concurrentJobs":{"type":"integer","description":"Jobs that may run at once; another answers 429 concurrency_limit."},"requestsPerMinute":{"type":"integer","description":"Requests a minute per API key, or per account for a map.audio sign-in."},"maxDrumSeconds":{"type":"number","description":"The longest drum hit POST /v1/synth/drum renders, in seconds."},"outputRetentionDays":{"type":"integer","description":"Days a rendered file is kept on the account's tier."}}},"Credits":{"type":"object","properties":{"object":{"const":"credits"},"period":{"type":"string","description":"YYYY-MM, UTC."},"unit":{"const":"render_minute"},"tier":{"$ref":"#/components/schemas/Tier"},"granted":{"type":"number","description":"The tier's monthly allowance."},"used":{"type":"number","description":"Render-minutes jobs have used this period."},"reserved":{"type":"number","description":"Render-minutes running jobs hold until they settle."},"remaining":{"type":"number","description":"What jobs can still draw: the allowance left plus the credits left, less what running jobs reserved."},"grants":{"type":"array","description":"The tier's allowance this period, then each unexpired credit grant, soonest expiry first; jobs draw on them in that order.","items":{"type":"object","properties":{"id":{"type":"string","description":"The credit grant; absent on the allowance."},"source":{"enum":["free","subscription","purchase","artist","operator"],"type":"string"},"amount":{"type":"number"},"remaining":{"type":"number"},"expiresAt":{"type":"string","format":"date-time","description":"When this allowance resets or this grant expires."}}}}}},"Usage":{"type":"object","properties":{"object":{"const":"usage"},"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"},"data":{"type":"array","items":{"type":"object","properties":{"keyId":{"type":["string","null"],"description":"The API key the usage was recorded under; null for requests made with a map.audio sign-in."},"meter":{"type":"string","description":"`renderMinutes`, `audioSeconds`, `computeMs`, or a free command's meter: `analysisSeconds`, `editSeconds`, `patterns`, `stateRows`, `remixes`, `candidates`."},"quantity":{"type":"number"}}}}}},"ApiKey":{"type":"object","properties":{"object":{"const":"api_key"},"id":{"type":"string"},"name":{"type":["string","null"]},"mode":{"enum":["test","live"],"type":"string"},"prefix":{"type":"string","description":"The first characters of the secret, for recognising it."},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time","description":"When the key last authenticated a request, to the hour."},"revokedAt":{"type":["string","null"],"format":"date-time"}}},"ApiKeyList":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}},"ApiKeyCreate":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":80,"description":"A label you choose, to tell keys apart."},"mode":{"enum":["test","live"],"default":"test","type":"string","description":"`test` or `live`. Both draw on the same render-minutes; the prefix separates Idempotency-Key namespaces and marks test renders' provenance."},"acceptTerms":{"type":"string","description":"The prototype terms version being accepted, required until the account has accepted it."}}},"ApiKeyCreated":{"allOf":[{"$ref":"#/components/schemas/ApiKey"},{"type":"object","required":["secret"],"properties":{"secret":{"type":"string","description":"The key itself, shown in this response only. Send it as `Authorization: Bearer <secret>`."}}}]},"Preset":{"type":"object","properties":{"object":{"const":"preset"},"ref":{"type":"string","description":"The reference renders take: pam:factory/<slug>."},"slug":{"type":"string"},"product":{"const":"pam"},"name":{"type":"string"},"author":{"type":"string"},"description":{"type":"string"},"bpm":{"type":["number","null"],"description":"The preset's tempo, which sets how long a bar renders."},"timeSignature":{"type":"array","items":{"type":"integer"},"minItems":2,"maxItems":2},"category":{"type":["string","null"]},"subcategory":{"type":["string","null"]},"tags":{"type":"array","items":{"type":"string"}},"variations":{"type":"array","items":{"type":"integer"},"description":"The variation slots the preset has, numbered from 1."},"hasSong":{"type":"boolean","description":"Whether the preset carries a song arrangement the API can render; false for every factory preset today."}}},"PresetList":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Preset"}},"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` for the next page; null on the last."},"total":{"type":"integer","description":"Presets that match, across every page."}}},"DrumEngine":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"controls":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"unit":{"type":"string"},"min":{"type":"number"},"max":{"type":"number"},"default":{"type":"number"}}},"description":"The engine's controls, set by `label` in POST /v1/synth/drum's `param`; percent controls take 0 to 100."}}},"Format":{"type":"object","additionalProperties":false,"properties":{"container":{"enum":["wav","flac","mp3"],"default":"wav","type":"string"},"bitrate":{"enum":[96,112,128,160,192,224,256,320],"default":320,"description":"MP3 only, kbit/s. At 22050 Hz the most is 160, which is then the default.","type":"integer"}},"description":"WAV and FLAC are 24-bit, as pam writes them; MP3 is CBR at `bitrate`."},"EventType":{"description":"Events a webhook endpoint receives; `job.expired` follows when retention deletes a job's outputs.","enum":["job.preview","job.succeeded","job.failed","job.cancelled","job.expired","webhook.test"],"type":"string"},"Morph":{"type":"object","required":["to"],"additionalProperties":false,"properties":{"to":{"$ref":"#/components/schemas/PresetSource"},"at":{"type":"number","minimum":-1,"maximum":2,"default":0.5,"description":"Morph position: 0 is the start, 1 the target; values outside 0..1 extrapolate along the same line."},"curve":{"enum":["linear","ease","exp","log"],"default":"ease","type":"string","description":"How the morph position eases, as a live Glide shapes its window."},"pattern":{"enum":["dissolve","wipe","cells"],"type":"string","description":"Stage the cells' patterns at `at` as a Steps transition does; without it the patterns stay the start's below 1."},"patternSeed":{"type":"integer","minimum":0,"maximum":4294967295,"description":"Draws each step of a `dissolve`, so the same seed gives the same steps."}}},"BlendItem":{"type":"object","required":["preset","weight"],"additionalProperties":false,"properties":{"preset":{"$ref":"#/components/schemas/PresetRef"},"variation":{"type":"integer","minimum":1,"maximum":16,"description":"The preset's variation slot to blend; default: its base state."},"weight":{"type":"number","exclusiveMinimum":0}}},"PlanSpec":{"type":"object","required":["base"],"additionalProperties":false,"properties":{"product":{"const":"pam","default":"pam"},"base":{"$ref":"#/components/schemas/PresetSource"},"tempo":{"type":"number","minimum":20,"maximum":400,"description":"Render at this tempo instead of the preset's, in BPM."},"morph":{"$ref":"#/components/schemas/Morph"},"blend":{"type":"array","minItems":2,"maxItems":16,"items":{"$ref":"#/components/schemas/BlendItem"}},"envelopes":{"type":"array","maxItems":64,"items":{"type":"object"},"description":"State envelopes ({delta, options?}) applied in order before rendering: the same envelopes POST /v1/state takes."},"arrangement":{"type":"object","additionalProperties":false,"required":["kind"],"properties":{"kind":{"enum":["loop","variations"],"type":"string"},"bars":{"type":"integer","minimum":1,"maximum":64},"variations":{"type":"array","items":{"type":"integer","minimum":1,"maximum":16},"maxItems":16}},"description":"`loop` renders `bars` of the base; `variations` renders each listed slot."}}},"PlanCreate":{"type":"object","additionalProperties":false,"properties":{"planner":{"enum":["rules","caller"],"default":"rules","type":"string","description":"`rules` plans from `prompt` and `constraints`; `caller` stores the `spec` you send."},"prompt":{"type":"string","maxLength":500,"description":"What you want, in a few words: genre, mood, instruments, a tempo such as 128 bpm, or \"variations\"."},"spec":{"$ref":"#/components/schemas/PlanSpec"},"seed":{"type":"integer","minimum":0,"maximum":4294967295,"default":0,"description":"Breaks ties between equally good presets; the same seed and prompt give the same plan."},"constraints":{"type":["object","null"],"additionalProperties":false,"properties":{"tempo":{"type":"number","minimum":20,"maximum":400},"category":{"type":"string","maxLength":60},"candidates":{"type":"integer","minimum":1,"maximum":10,"default":3}}}}},"Plan":{"type":"object","properties":{"object":{"const":"plan"},"id":{"type":"string"},"seed":{"type":"integer"},"prompt":{"type":["string","null"]},"planner":{"type":"object","properties":{"kind":{"enum":["rules","caller"],"type":"string"},"version":{"type":"string"},"model":{"type":"null"}}},"candidates":{"type":"array","items":{"type":"object","properties":{"preset":{"type":"string"},"name":{"type":"string"},"score":{"type":"number"},"match":{"type":"array","items":{"type":"string"}}}}},"spec":{"$ref":"#/components/schemas/PlanSpec"},"createdAt":{"type":"string","format":"date-time"},"provenance":{"type":"object","properties":{"aiModels":{"type":"array","maxItems":0},"presets":{"type":"array","items":{"type":"string"}}}}}},"RenderCreate":{"type":"object","additionalProperties":false,"description":"Exactly one of `source` and `plan`. At most one of `variations`, `items` and `quality: standard`.","properties":{"source":{"$ref":"#/components/schemas/PresetSource","description":"The preset to render; give `source` or `plan`."},"plan":{"type":"string","pattern":"^plan_","description":"A stored plan's id (plan_…), instead of `source`."},"bars":{"type":"integer","minimum":1,"maximum":64,"description":"Length in bars of the preset's time signature, at its tempo (or the plan's). Default 4; give `bars` or `seconds`."},"seconds":{"type":"number","exclusiveMinimum":0,"description":"Length in seconds, instead of `bars`.","maximum":300},"tail":{"type":"number","minimum":0,"default":0,"description":"Seconds of effect tail after the transport stops, added to the length.","maximum":30},"seed":{"type":"integer","minimum":0,"maximum":4294967295,"default":0,"description":"Seed for everything random in the render; 0 draws one, which the job reports, and sending that seed again renders the same audio."},"stems":{"type":"boolean","default":false,"description":"Also write one stem per cell, captured after cell effects and before the master chain, encoded like the master."},"sampleRate":{"enum":[22050,32000,44100,48000],"type":"integer","description":"Output sample rate in Hz.","default":48000},"format":{"$ref":"#/components/schemas/Format","description":"Container and MP3 bitrate for every output; WAV unless you ask."},"quality":{"enum":["draft","standard","elite"],"default":"draft","description":"standard renders `search.candidates` seeds, measures each and returns the best that pass the limit gate; elite is refused until a curated archive exists.","type":"string"},"search":{"type":"object","description":"Only with quality standard.","additionalProperties":false,"properties":{"candidates":{"type":"integer","minimum":2,"default":4,"maximum":8},"return":{"type":"integer","minimum":1,"maximum":4,"default":1},"targetLufs":{"type":"number","minimum":-40,"maximum":-6}}},"variations":{"oneOf":[{"type":"object","required":["kind"],"additionalProperties":false,"properties":{"kind":{"const":"slots"},"slots":{"type":"array","minItems":1,"maxItems":16,"items":{"type":"integer","minimum":1,"maximum":16}}}},{"type":"object","required":["kind","count"],"additionalProperties":false,"properties":{"kind":{"const":"seeds"},"count":{"type":"integer","minimum":2,"maximum":8}}},{"type":"object","required":["kind","to","at"],"additionalProperties":false,"properties":{"kind":{"const":"morph"},"to":{"$ref":"#/components/schemas/PresetSource"},"at":{"type":"array","minItems":2,"maxItems":8,"items":{"type":"number","minimum":0,"maximum":1}},"curve":{"enum":["linear","ease","exp","log"],"type":"string"},"pattern":{"enum":["dissolve","wipe","cells"],"type":"string"},"patternSeed":{"type":"integer","minimum":0,"maximum":4294967295}}},{"type":"object","required":["kind","presets"],"additionalProperties":false,"properties":{"kind":{"const":"blend"},"presets":{"type":"array","minItems":2,"maxItems":16,"items":{"$ref":"#/components/schemas/BlendItem"}}}}],"description":"Several outputs from one job: `slots` renders variation slots, `seeds` takes from derived seeds, `morph` renders positions between the source and `to`, `blend` renders a weighted blend of presets."},"items":{"type":"array","minItems":1,"maxItems":8,"items":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,40}$"},"variation":{"type":"integer","minimum":1,"maximum":16},"bars":{"type":"integer","minimum":1,"maximum":64},"cutdown":{"type":"object","description":"Fits the preset to this length across its variations. An item with a cutdown takes no variation or bars.","required":["seconds"],"additionalProperties":false,"properties":{"seconds":{"type":"number","minimum":5,"maximum":300}}}}},"description":"Named outputs of their own lengths: a variation for some bars, or a `cutdown` fitted to seconds across the preset's variations."},"preview":{"type":"object","additionalProperties":false,"description":"A short render published first, as a `job.preview` event. A job that succeeds pays for its render or its preview, whichever is longer; if it fails or is cancelled, the preview is still charged at its own length.","properties":{"bars":{"type":"integer","minimum":1,"maximum":8,"default":4}}},"metadata":{"type":"object","maxProperties":20,"additionalProperties":{"type":"string","maxLength":200},"propertyNames":{"maxLength":40},"description":"Up to 20 string pairs stored with the job and returned with it."}}},"ArrangementCreate":{"type":"object","additionalProperties":false,"properties":{"source":{"$ref":"#/components/schemas/PresetSource","description":"The preset a cutdown fits; give `source` or `plan`."},"plan":{"type":"string","pattern":"^plan_","description":"A stored plan whose base preset and tempo a cutdown fits."},"cutdown":{"type":"object","required":["seconds"],"additionalProperties":false,"properties":{"seconds":{"type":"number","minimum":5,"maximum":300}},"description":"Fit the preset to about this many seconds, as an opening, a main section and an ending over its variations."},"set":{"type":"object","description":"A DJ set to check: `queue` lists its items in play order, each naming a factory preset (`presetPath`), its variation (`variationIndex`, counted from 0), its length in `bars` and the `transition` into it. GET /v1/transition-presets lists the transitions and the set schema's definitions."}},"description":"`cutdown` fits one preset (from `source` or `plan`) to a length; `set` checks a DJ set you wrote. Either way nothing renders: send the result to POST /v1/dj/set."},"Arrangement":{"type":"object","properties":{"object":{"const":"arrangement"},"set":{"type":"object","description":"The set in preset references, with the tempo filled in: send it as `set` to POST /v1/dj/set."},"seconds":{"type":"number","description":"The set's length in seconds."},"bpm":{"type":"number"},"boundaries":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"preset":{"type":"string"},"variation":{"type":["integer","null"]},"startBar":{"type":"integer"},"startSeconds":{"type":"number"},"bars":{"type":"integer"}}},"description":"Where each item starts. `variation` counts from 1, as everywhere outside a DJ set's `variationIndex`."},"bars":{"type":"integer","description":"The set's length in bars."}}},"JobStatus":{"description":"`expired`: retention deleted the outputs; the record and its provenance stay.","enum":["queued","running","succeeded","failed","cancelled","expired"],"type":"string"},"Output":{"type":"object","properties":{"role":{"enum":["master","stem","midi","preset","preview"],"type":"string","description":"`master` for a render's output, `stem` for a cell, `preview` for a preview render, `midi` for a pattern, `preset` for a saved or remixed preset."},"name":{"type":["string","null"],"description":"The output's name within the job: an item, slot, seed or candidate name; null for a single output."},"cell":{"type":["integer","null"],"description":"The cell a stem comes from; null otherwise."},"file":{"type":"string","description":"The output's file id, which later commands take as input."},"url":{"type":"string","description":"A signed download link that needs no Authorization header."},"expiresAt":{"type":"string","description":"When `url` stops working, unless the file's own retention (`GET /v1/files/{id}`, `expiresAt`) ends first; `GET /v1/files/{id}/content` signs a fresh one.","format":"date-time"},"sha256":{"type":"string"},"bytes":{"type":"integer"},"format":{"type":"string"},"sampleRate":{"type":["integer","null"]},"durationSeconds":{"type":["number","null"]}}},"Job":{"type":"object","required":["object","id","status"],"properties":{"object":{"const":"job"},"id":{"type":"string","description":"The job (job_…)."},"operation":{"type":"string","description":"`renders.create`, `uploads.complete`, or a command's operationId such as `presetRender`."},"status":{"$ref":"#/components/schemas/JobStatus"},"livemode":{"type":"boolean","description":"`false` for a job started with a test key."},"sequence":{"type":"integer","description":"How many events the job has had; it rises with every change."},"progress":{"type":"number","minimum":0,"maximum":1},"queuePosition":{"type":["integer","null"],"description":"Not computed yet; always null."},"createdAt":{"type":"string","format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"},"estimate":{"type":"object","properties":{"renderMinutes":{"type":"number"},"audioSeconds":{"type":"number"}},"description":"What the job is expected to render and charge, reserved from the account's render-minutes when it is admitted."},"result":{"type":["object","null"],"properties":{"outputs":{"type":"array","items":{"$ref":"#/components/schemas/Output"}},"seed":{"type":["integer","null"]},"command":{"type":"object","description":"The engine command's own JSON result, with paths replaced by file ids."},"spec":{"type":"object","description":"For POST /v1/renders, the request as the job ran it, with defaults filled in."},"provenance":{"anyOf":[{"$ref":"#/components/schemas/Provenance"},{"type":"null"}],"description":"Null for analysis the Worker ran itself, which makes no audio."}},"description":"Null until the job succeeds."},"error":{"anyOf":[{"$ref":"#/components/schemas/ErrorObject"},{"type":"null"}],"description":"Why the job failed; null otherwise."},"usage":{"type":["object","null"],"description":"What the job was charged, once it ends: its outputs' real length, not the estimate.","properties":{"renderMinutes":{"type":"number"},"audioSeconds":{"type":"number"},"computeMs":{"type":"number"}}},"metadata":{"type":"object","description":"The `metadata` the request sent."},"urls":{"type":"object","properties":{"self":{"type":"string"},"events":{"type":"string"},"cancel":{"type":"string"}},"description":"Where to poll, stream and cancel the job."}}},"JobList":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Job"}},"nextCursor":{"type":["string","null"]}}},"File":{"type":"object","properties":{"object":{"const":"file"},"id":{"type":"string"},"kind":{"enum":["output","sample","audio","preset","project","projectFolder"],"type":"string"},"status":{"enum":["uploading","processing","pending","ready","rejected","expired","deleted"],"type":"string","description":"`pending` while its job runs, `ready`, then `expired` or `deleted`; uploads also pass `uploading` and `processing`, and end `rejected` when their check fails."},"name":{"type":"string"},"contentType":{"type":"string"},"bytes":{"type":"integer"},"sha256":{"type":["string","null"]},"jobId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":["string","null"],"description":"When retention deletes the file.","format":"date-time"},"role":{"type":["string","null"],"description":"For an output, its role in the job (master, stem, preview, midi or preset); null for an upload."}}},"FileList":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/File"}},"nextCursor":{"type":["string","null"]}}},"UploadCreate":{"type":"object","required":["kind","name","bytes","sha256"],"additionalProperties":false,"properties":{"kind":{"enum":["audio","sample","project"],"description":"`sample` is an alias of `audio`. Preset and project-folder uploads are not served yet.","type":"string"},"name":{"type":"string","maxLength":255},"bytes":{"type":"integer","minimum":1},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"}}},"Upload":{"type":"object","properties":{"object":{"const":"upload"},"id":{"type":"string"},"file":{"type":"string"},"partBytes":{"type":"integer"},"parts":{"type":"integer"},"expiresAt":{"type":"string","description":"When an unfinished upload is aborted.","format":"date-time"},"kind":{"type":"string"},"status":{"enum":["uploading","processing","ready","rejected","expired","deleted"],"type":"string"}}},"WebhookEndpointCreate":{"type":"object","required":["url"],"additionalProperties":false,"properties":{"url":{"type":"string","format":"uri","pattern":"^https://","description":"A public HTTPS URL with a host name; deliveries are POSTs to it."},"events":{"type":"array","description":"Event types to receive; `*` receives every event.","items":{"anyOf":[{"$ref":"#/components/schemas/EventType"},{"const":"*"}]}},"description":{"type":"string","maxLength":200}}},"WebhookEndpoint":{"type":"object","properties":{"object":{"const":"webhook_endpoint"},"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"enum":["enabled","disabled"],"type":"string","description":"`disabled` after three deliveries in a row ran out of retries; rotating the secret enables it again."},"secret":{"type":"string","description":"Only when created or rotated."},"createdAt":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"deleted":{"type":"boolean","description":"Only in the answer to a delete."}}},"WebhookEndpointList":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"Event":{"type":"object","properties":{"id":{"type":"string","description":"The event (evt_…), also the `webhook-id` header; a retried delivery keeps it."},"type":{"$ref":"#/components/schemas/EventType"},"createdAt":{"type":"string","format":"date-time"},"apiVersion":{"type":"string"},"data":{"type":"object","properties":{"object":{"type":"object"},"jobId":{"type":"string","description":"On `job.preview`: the job the preview belongs to."},"outputs":{"type":"array","items":{"type":"object"},"description":"On `job.preview`: the preview outputs, shaped like a job result's outputs."}},"description":"On `job.succeeded`, `job.failed`, `job.cancelled` and `job.expired`, `object` is the job as it stands when the event is delivered. On `job.preview`, `jobId` and `outputs` describe the preview. On `webhook.test`, `object` is the endpoint."}}},"Provenance":{"type":"object","properties":{"object":{"const":"provenance"},"id":{"type":"string"},"jobId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"engine":{"type":"object","properties":{"product":{"type":"string"},"version":{"type":["string","null"],"description":"Null until the render image reports its engine version; `image` names the exact build."},"runtime":{"type":"string"},"image":{"type":"string"}}},"contracts":{"type":"object"},"seed":{"type":["integer","null"]},"presets":{"type":"array","items":{"type":"object"},"description":"Every preset the render read, with its variation and SHA-256."},"packs":{"type":"array","items":{"type":"string"}},"userFiles":{"type":"array","description":"Uploads among the inputs, with the SHA-256 the caller sent.","items":{"type":"object"}},"inputs":{"type":"array","description":"Every file the engine read: earlier outputs, and uploads as their canonical WAV.","items":{"type":"object","properties":{"file":{"type":"string"},"sha256":{"type":"string"}}}},"outputs":{"type":"array","items":{"type":"object","properties":{"file":{"type":"string"},"sha256":{"type":"string"}}}},"planner":{"type":["object","null"]},"aiModels":{"type":"array","maxItems":0,"description":"Always empty: no AI model takes part in a render."},"audioByModel":{"const":false,"description":"Always false: no model made the audio."},"license":{"type":"object","description":"The licence the account's tier gave the render; a test-mode render's id ends `_test`."},"kid":{"type":"string","description":"The signing key, in GET /.well-known/jwks.json."},"signature":{"type":"string","description":"ed25519: base64url signature over the record's canonical JSON without `signature`."}}},"Tier":{"type":"object","description":"The account's tier. Paid tiers are bought signed in at https://map.audio/music.","properties":{"id":{"type":"string","description":"free, or a paid tier.","enum":["free","creator","pro","app"]},"name":{"type":"string"},"currentPeriodEnd":{"type":["string","null"],"description":"When the paid period ends; null on the free tier.","format":"date-time"},"cancelAtPeriodEnd":{"type":"boolean"}}},"BillingCheckout":{"type":"object","additionalProperties":false,"description":"Either a paid tier to subscribe to, or render-minutes to buy.","properties":{"tier":{"type":"string","description":"A paid tier to subscribe to.","enum":["creator","pro","app"]},"renderMinutes":{"type":"integer","description":"Whole render-minutes of pay-as-you-go credit to buy.","minimum":334,"maximum":100000},"consent":{"type":"object","additionalProperties":false,"required":["analytics","advertising"],"description":"The buyer's analytics and advertising choice on map.audio, which the purchase's analytics and ad reports follow. Without it, both count as denied.","properties":{"analytics":{"type":"string","enum":["granted","denied"]},"advertising":{"type":"string","enum":["granted","denied"]}}}},"oneOf":[{"required":["tier"]},{"required":["renderMinutes"]}]},"BillingLink":{"type":"object","properties":{"object":{"const":"billing_link"},"url":{"type":"string","format":"uri","description":"A Stripe page to open in a browser."}}},"AccessRequestCreate":{"type":"object","additionalProperties":false,"properties":{"useCase":{"type":["string","null"],"minLength":1,"maxLength":1000,"description":"What you want to build with the API, in a sentence or two. null clears a saved one; leaving it out keeps it."},"website":{"type":["string","null"],"maxLength":200,"pattern":"^https://","description":"A public https URL for you or your product: a host name, not an IP address, localhost or a URL with credentials. null clears a saved one; leaving it out keeps it."}}},"AccessRequest":{"type":"object","required":["object","id","status","email","useCase","website","createdAt","updatedAt"],"properties":{"object":{"const":"access_request"},"id":{"type":"string","pattern":"^areq_"},"status":{"type":"string","enum":["pending","invited","dismissed"]},"email":{"type":["string","null"]},"useCase":{"type":["string","null"]},"website":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ErrorObject":{"type":"object","description":"What went wrong: the `error` of an error response, and a failed job's `error`.","required":["type","code","message","param","retryable","jobId","docUrl"],"properties":{"type":{"type":"string","enum":["invalid_request","authentication","entitlement","not_found","conflict","gone","too_large","rate_limit","engine","unavailable"],"description":"The family of the error. The status of each code is in the error catalogue (`x-error-codes` on `Error.error.code`)."},"code":{"type":"string","description":"A stable code to branch on; every one is in the error catalogue."},"message":{"type":"string","description":"What went wrong and what to do next. Its wording can change; branch on `code`."},"param":{"type":["string","null"],"description":"The field at fault in the body's own notation (`items[0].name`), or a query parameter or header name."},"details":{"type":"object","description":"Facts some codes add, such as `needed` and `remaining` render-minutes for insufficient_credits."},"retryable":{"type":"boolean","description":"`true` when the same request can succeed later unchanged."},"jobId":{"type":["string","null"],"description":"The job the error belongs to, when there is one."},"docUrl":{"type":"string","format":"uri","description":"This code's entry in the error catalogue."}}},"TransitionPresets":{"type":"object","description":"What a DJ set transition can use.","properties":{"object":{"const":"transition_presets"},"presets":{"type":"array","items":{"type":"string"},"description":"Transition presets a render knows, by id."},"modes":{"type":"array","items":{"type":"string"},"description":"Values a transition's `mode` takes."},"curves":{"type":"array","items":{"type":"string"},"description":"Values a transition's `curve` takes."},"maxBars":{"type":"number","description":"The longest transition window, in bars."},"schema":{"type":"string","format":"uri","description":"The DJ set schema's id."},"definitions":{"type":"object","description":"The DJ set schema's definitions: DjSetDocument, DjSetItem, DjTransition and the rest."}}},"UploadPart":{"type":"object","properties":{"object":{"const":"upload_part"},"upload":{"type":"string","description":"The upload's file id."},"part":{"type":"integer"},"bytes":{"type":"integer"}}}},"headers":{"RequestId":{"description":"This request's id in MAP Audio's logs; error bodies repeat it as `error.requestId`. Quote it when you report a problem.","schema":{"type":"string"},"example":"9a3f7c2e5b1d8f40-LHR"},"MapVersion":{"description":"The API version that answered. Every JSON response carries it.","schema":{"type":"string"},"example":"2026-11-01"},"RateLimitPolicy":{"description":"The request limit this credential is under: `120;w=60` is 120 requests in each 60 s window. Every response to an accepted credential carries it.","schema":{"type":"string"},"example":"120;w=60"},"PreferenceApplied":{"description":"The wait this response used, as `wait=N`; sent when the request asked for one with `Prefer`.","schema":{"type":"string"},"example":"wait=30"},"Location":{"description":"The job's URL, to poll.","schema":{"type":"string","format":"uri"},"example":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP"},"RetryAfter":{"description":"Seconds to wait before polling again or retrying.","schema":{"type":"integer","minimum":0},"example":2},"IdempotentReplayed":{"description":"`true` when this response replays the job an earlier request with the same Idempotency-Key started.","schema":{"type":"string","enum":["true"]}}},"examples":{"RenderQueued":{"summary":"Queued","value":{"object":"job","id":"job_01M6BPRE186QHP9QPYGDX5NNFP","operation":"renders.create","status":"queued","livemode":false,"sequence":1,"progress":0,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":null,"finishedAt":null,"estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":null,"error":null,"usage":null,"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP","events":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/cancel"}}},"RenderSucceeded":{"summary":"Succeeded: 16 s of 313 Disco","value":{"object":"job","id":"job_01M6BPRE186QHP9QPYGDX5NNFP","operation":"renders.create","status":"succeeded","livemode":false,"sequence":3,"progress":1,"queuePosition":null,"createdAt":"2026-11-01T14:03:31.512Z","startedAt":"2026-11-01T14:03:33.104Z","finishedAt":"2026-11-01T14:03:41.877Z","estimate":{"audioSeconds":16,"renderMinutes":0.267},"result":{"outputs":[{"role":"master","name":null,"cell":null,"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b","bytes":4608044,"format":"wav","sampleRate":48000,"durationSeconds":16,"url":"https://api.map.audio/v1/download/file_01M6BPRK0M34NBP2XKJ1RMX1TQ?expires=1793545422&signature=yaoMrgCHcK9T8MaVnCVtXZc4Ym0FWWM8P-0feZDMObk","expiresAt":"2026-11-01T15:03:42.000Z"}],"seed":42,"command":{"ok":true,"wavPath":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sampleRate":48000,"channels":2,"durationSeconds":16,"seed":42,"stems":[],"stemTap":"post_cell_pre_master","latencySamples":0,"missingSamples":[]},"spec":{"source":{"preset":"pam:factory/313-disco"},"plan":null,"bars":8,"seconds":null,"tail":0,"seed":42,"stems":false,"sampleRate":48000,"format":{"container":"wav"},"quality":"draft","tempo":120},"provenance":{"object":"provenance","id":"prov_01M6BPRVA8ZC7F7J737SQ0EPN2","jobId":"job_01M6BPRE186QHP9QPYGDX5NNFP","createdAt":"2026-11-01T14:03:41.877Z","engine":{"product":"pam","version":null,"runtime":"native-linux-x86_64","image":"registry.cloudflare.com/c7c2e61448617e81ced650f444fb6787/pam-render@sha256:5c5ffe3fabc103e277280fbd65a08988d31361f00fe7857e36f603d67bcec42d"},"seed":42,"presets":[{"ref":"pam:factory/313-disco","sha256":"3afbf5dea1003b2d17385955017785a57d74c65f77f97b58cf5d7cec9794ca1c"}],"packs":[],"userFiles":[],"inputs":[],"outputs":[{"file":"file_01M6BPRK0M34NBP2XKJ1RMX1TQ","sha256":"5a3485b7a3221be5f7ead6ab953cbc198988a7246158215b32bb937acbd3852b"}],"planner":null,"contracts":{"api":"2026-11-01","pam.cli":1},"aiModels":[],"audioByModel":false,"license":{"id":"lic_api_prototype_test","commercialUse":false,"attribution":true},"kid":"6c2f0a9d4b7e1358","signature":"ed25519:jsfkW3eF1r4kChqccp6AKLTvjTK5Re8acrEusqigz7MDUu6uZhsJXVnuQEl6EsErDgVYNXOkos9d0mMyt2CVCg"}},"error":null,"usage":{"renderMinutes":0.267,"audioSeconds":16,"computeMs":6273},"metadata":{},"urls":{"self":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP","events":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/events","cancel":"https://api.map.audio/v1/jobs/job_01M6BPRE186QHP9QPYGDX5NNFP/cancel"}}}}},"externalDocs":{"description":"Music API docs: quickstart, recipes, reference and error codes","url":"https://map.audio/developers/music-api"},"x-universal-error-codes":["authentication_failed","not_invited","insufficient_scope","auth_unavailable","account_suspended","rate_limited","version_unsupported","internal_error"]}