{
  "openapi": "3.1.0",
  "info": {
    "title": "Scarleta API",
    "version": "1.0.0",
    "description": "The Scarleta API analyzes audio and runs audio workflows over HTTPS. Usage is prepaid in tokens: 1 token is 1 second of audio, billed at $0.10 per minute. A free account includes a one-time grant of 300 tokens. Authenticate every request with an API key in the Authorization header.",
    "license": {
      "name": "Proprietary",
      "url": "https://www.scarleta.ai/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.scarleta.ai"
    }
  ],
  "tags": [
    {
      "name": "Analysis",
      "description": "Submit audio analyses, read their status and logs, and cancel jobs that have not finished."
    },
    {
      "name": "Analysis results",
      "description": "Read the finished analyses of a file and download the MIDI file a melody analysis produced."
    },
    {
      "name": "Archives",
      "description": "Pack selected files or your whole library into downloadable zip archives, in parts when the selection is large."
    },
    {
      "name": "Batch",
      "description": "Run a recipe over many audio files in one background batch, then read, retry, or cancel it."
    },
    {
      "name": "Chat",
      "description": "Send a message to the Scarleta assistant and read the background jobs it runs."
    },
    {
      "name": "Conversation shares",
      "description": "Create, list, and revoke public links that let anyone read a conversation without an API key."
    },
    {
      "name": "Conversations",
      "description": "Create, read, list, delete, and control chat conversations with the Scarleta assistant, including their turns and read state."
    },
    {
      "name": "Documents",
      "description": "Save, read, list, and prune the versioned documents the assistant or your tools produce."
    },
    {
      "name": "Feedback",
      "description": "Rate a request outcome with a thumbs up or thumbs down, with an optional comment."
    },
    {
      "name": "File actions",
      "description": "Rename, star, archive, delete, and mark the best version of stored files in bulk."
    },
    {
      "name": "File conversations",
      "description": "List the conversations that were started about one stored file."
    },
    {
      "name": "File details",
      "description": "Read and edit a file's metadata, and get, set, or remove its cover image."
    },
    {
      "name": "Files",
      "description": "Upload, list, download, and delete stored audio files, and check storage usage."
    },
    {
      "name": "Imports and duplicates",
      "description": "Import a file from a public link and check which files you already have by hash."
    },
    {
      "name": "Library",
      "description": "List, search, and count your stored library, and run a recipe over a saved view or a set of filters."
    },
    {
      "name": "MCP",
      "description": "Use the Model Context Protocol JSON-RPC endpoint and its event stream from AI clients."
    },
    {
      "name": "Media links",
      "description": "Refresh an expired signed link for one of your media files."
    },
    {
      "name": "Notes",
      "description": "Add, list, and delete text notes on a file."
    },
    {
      "name": "Recipe catalog",
      "description": "Browse the recipe catalog, read an author's recipes, and read or post recipe comments."
    },
    {
      "name": "Recipes",
      "description": "Generate, validate, save, fork, compare, execute, and manage recipes, including approvals and runs."
    },
    {
      "name": "Renders",
      "description": "List the files that were made from an original: crops, effects, noise-reduced versions, and stems."
    },
    {
      "name": "Saved views",
      "description": "Create, list, read, update, and delete saved library views, including views built in a conversation."
    },
    {
      "name": "Shares",
      "description": "Create, list, and revoke public share links for individual files."
    },
    {
      "name": "Similar sounds",
      "description": "Find files in your library that sound like a file you own or a reference link."
    },
    {
      "name": "Sound grouping",
      "description": "Start a job that groups your files by how they sound, then read and name the groups."
    },
    {
      "name": "Tags",
      "description": "List, add, remove, rename, merge, color, and adopt tags on your files."
    },
    {
      "name": "Trash",
      "description": "List, restore, and permanently delete files in the trash."
    },
    {
      "name": "Upload sessions",
      "description": "Start, resume, complete, and cancel resumable multipart upload sessions."
    },
    {
      "name": "Versions",
      "description": "Group files as versions of one track, ungroup them, and find files that are not yet grouped."
    },
    {
      "name": "Webhooks",
      "description": "Get, rotate, and revoke the secret that signs your webhook deliveries, and register the addresses that receive them."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/v1/analyze": {
      "post": {
        "operationId": "submit_analysis",
        "tags": [
          "Analysis"
        ],
        "summary": "Submit an analysis",
        "description": "Starts a full analysis of one audio file and returns `202` at once with a `job_id`. Poll `GET /v1/analyze/{job_id}` until `status` is final; the analysis itself normally takes seconds to a minute.\n\n`audio_url` must be a public `http` or `https` URL, or the URL of a file in your own library. Files longer than 60 minutes are refused with 400 `audio_too_long`. Unreadable or unsupported files are refused with 400 `unsupported_format` or `audio_processing_failed`; a file that cannot be downloaded from the URL is refused with 404 `audio_not_found`. Your balance is checked before the job starts; if it cannot cover the file the call returns 402 `insufficient_balance` and nothing is charged. Supply `features` to name the measurements you care about; leave it out to get the standard set.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "tokens",
          "rule": "Charged when the analysis finishes: tokens per second of audio, at the rate for a full analysis. The submit response reports the amount in `expected_tokens`. A file longer than the maximum, or a balance too low to cover the file, is refused before anything starts."
        },
        "x-scarleta-error-codes": [
          "analysis_failed",
          "analysis_service_error",
          "audio_not_found",
          "audio_processing_failed",
          "audio_too_long",
          "auth_unavailable",
          "configuration_error",
          "insufficient_balance",
          "invalid_audio_duration",
          "invalid_audio_url",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "media_not_owned",
          "missing_api_key",
          "missing_audio_url",
          "missing_auth",
          "persistence_failed",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "service_unavailable",
          "unauthorized",
          "unsupported_format"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096,
                    "description": "Where to fetch the audio, at most 4096 characters. Must be public `http` or `https`, or a file in your own library."
                  },
                  "features": {
                    "description": "Dotted feature ids to request, for example `spectral.centroid`. Ids that are not recognised are ignored and the standard set is used.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "audio_url"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_url": "https://example.com/track-1.wav"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. The job is queued. Carries an `X-Job-ID` header with the same `job_id`,.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string",
                              "description": "Identifier to poll, cancel and read logs with."
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "IN_QUEUE",
                                "IN_PROGRESS",
                                "COMPLETED",
                                "FAILED",
                                "CANCELLED",
                                "TIMEOUT"
                              ],
                              "description": "`IN_QUEUE` when accepted."
                            },
                            "message": {
                              "type": "string"
                            },
                            "tenant_id": {
                              "description": "Your account identifier. Absent for free accounts.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "audio_url": {
                              "type": "string",
                              "description": "The file being analyzed, with any credentials stripped from the URL."
                            },
                            "workflow": {
                              "type": "string",
                              "const": "direct-api"
                            },
                            "created_at": {
                              "type": "string",
                              "description": "ISO 8601 timestamp."
                            },
                            "response_time_ms": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "How long accepting the job took, in milliseconds."
                            },
                            "expected_duration": {
                              "description": "Length of the audio in seconds.",
                              "type": "number"
                            },
                            "expected_tokens": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Tokens this analysis will cost when it finishes."
                            },
                            "cache_hit": {
                              "type": "boolean",
                              "description": "True when the file had been read before and was reused."
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "message",
                            "audio_url",
                            "workflow",
                            "created_at",
                            "response_time_ms",
                            "expected_tokens",
                            "cache_hit"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44",
                    "status": "IN_QUEUE",
                    "message": "Analysis job submitted. Use GET /v1/analyze/{job_id} to retrieve results.",
                    "tenant_id": "8c1d0b52-3f6a-4e0d-9d7b-2a41c5e90f13",
                    "audio_url": "https://example.com/track-1.wav",
                    "workflow": "direct-api",
                    "created_at": "2026-10-21T03:41:37.272Z",
                    "response_time_ms": 610,
                    "expected_duration": 5.2,
                    "expected_tokens": 26,
                    "cache_hit": false
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON, a missing `audio_url`, an unacceptable URL, or a file that cannot be read as audio (`error.details.supported_formats` lists the accepted formats).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_url",
                    "message": "audio_url is required in request body",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_url"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "402": {
            "description": "The balance cannot cover this file. `error.details.required_tokens` says how much is needed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "insufficient_balance",
                    "message": "This audio requires 26 tokens (5.2s duration), but you have insufficient balance.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#insufficient_balance"
                  }
                }
              }
            }
          },
          "403": {
            "description": "`audio_url` points at a library file owned by another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "media_not_owned",
                    "message": "That file belongs to a different account.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#media_not_owned"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file at `audio_url` could not be downloaded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "audio_not_found",
                    "message": "Unable to download audio file from the provided URL. Please ensure the URL is correct and the file is accessible.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#audio_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The analysis could not be started. Nothing was charged; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "analysis_service_error",
                    "message": "Audio analysis service returned an error. Please try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#analysis_service_error"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The job could not be recorded. Nothing was charged; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "persistence_failed",
                    "message": "Unable to create job tracking record. Please retry.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#persistence_failed"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/analyze/{job_id}": {
      "get": {
        "operationId": "get_analysis",
        "tags": [
          "Analysis"
        ],
        "summary": "Get an analysis",
        "description": "Returns the state of one analysis job and, once `status` is `COMPLETED`, its `results`. Poll this route every few seconds until `status` is `FAILED`, `CANCELLED` or `TIMEOUT`, or `COMPLETED` with `results` present. You can only read your own jobs; any other job id returns 404 `job_not_found`. For a few seconds after `status` first reads `COMPLETED`, `results` can still be null: keep polling until it is an object. `results` is a JSON object whose keys depend on the analysis and can grow over time: read the keys you need and ignore the rest.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_job_id",
          "invalid_key",
          "invalid_key_format",
          "job_not_found",
          "missing_api_key",
          "missing_auth",
          "missing_job_id",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "retrieval_failed",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The `job_id` returned when the analysis was submitted, for example `analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The job exists. `results` is null until `status` is `COMPLETED`.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string"
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "IN_QUEUE",
                                "IN_PROGRESS",
                                "COMPLETED",
                                "FAILED",
                                "CANCELLED",
                                "TIMEOUT"
                              ]
                            },
                            "workflow": {
                              "type": "string",
                              "description": "How the job was started; `direct-api` for jobs created by `POST /v1/analyze`."
                            },
                            "audio_url": {
                              "type": "string",
                              "description": "The analyzed file. A library file comes back as a short-lived signed link."
                            },
                            "features": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "The feature ids you asked for; empty when you took the standard set."
                            },
                            "results": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "propertyNames": {
                                    "type": "string"
                                  },
                                  "additionalProperties": {}
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "The measurements, or null until the job completes."
                            },
                            "error": {
                              "description": "Why the job failed, or null."
                            },
                            "created_at": {
                              "type": "string",
                              "description": "ISO 8601 timestamp."
                            },
                            "completed_at": {
                              "description": "ISO 8601 timestamp, or null while the job runs.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "workflow",
                            "audio_url",
                            "features",
                            "results",
                            "error",
                            "created_at",
                            "completed_at"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44",
                    "status": "COMPLETED",
                    "workflow": "direct-api",
                    "audio_url": "https://example.com/track-1.wav",
                    "features": [],
                    "results": {
                      "success": true,
                      "summary": {
                        "duration_seconds": 5,
                        "dominant_key": "A",
                        "rms_energy": 0.856
                      }
                    },
                    "error": null,
                    "created_at": "2026-10-21T03:41:37.272Z",
                    "completed_at": "2026-10-21T03:41:56.630Z"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`job_id` has characters outside letters, digits and `_ . : -`, or is too long.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_job_id",
                    "message": "job_id must match ^[A-Za-z0-9_.:-]{1,128}$",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_job_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No job with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "job_not_found",
                    "message": "Job analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44 not found or access denied",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#job_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The job could not be read. Retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "retrieval_failed",
                    "message": "Failed to retrieve analysis results",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#retrieval_failed"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/analyze/{job_id}/cancel": {
      "post": {
        "operationId": "cancel_analysis",
        "tags": [
          "Analysis"
        ],
        "summary": "Cancel an analysis",
        "description": "Stops an analysis that has not finished and marks it `CANCELLED`. The call is idempotent: a job that is already final is left alone and its current `status` is returned, so a second cancel is not an error. A job cancelled before it finishes is not charged.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. A cancelled job is not charged."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_job_id",
          "invalid_key",
          "invalid_key_format",
          "job_not_found",
          "missing_api_key",
          "missing_auth",
          "missing_job_id",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The `job_id` returned when the analysis was submitted, for example `analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string"
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "IN_QUEUE",
                                "IN_PROGRESS",
                                "COMPLETED",
                                "FAILED",
                                "CANCELLED",
                                "TIMEOUT"
                              ],
                              "description": "`CANCELLED` when this call stopped the job; otherwise the final state the job was already in."
                            }
                          },
                          "required": [
                            "job_id",
                            "status"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44",
                    "status": "CANCELLED"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`job_id` has characters outside letters, digits and `_ . : -`, or is too long.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_job_id",
                    "message": "job_id must match ^[A-Za-z0-9_.:-]{1,128}$",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_job_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No job with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "job_not_found",
                    "message": "Job 'analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44' not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#job_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/analyze/{job_id}/logs": {
      "get": {
        "operationId": "get_analysis_logs",
        "tags": [
          "Analysis"
        ],
        "summary": "Get the logs of an analysis",
        "description": "Returns the execution log entries recorded for one of your jobs, oldest first, at most 200 entries. A job that has not started a step, or an analysis submitted with `POST /v1/analyze`, can have no entries: `logs` is then an empty array. Use the logs to diagnose a failed job.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_job_id",
          "invalid_key",
          "invalid_key_format",
          "job_not_found",
          "missing_api_key",
          "missing_auth",
          "missing_job_id",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The `job_id` returned when the analysis was submitted, for example `analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string"
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "IN_QUEUE",
                                "IN_PROGRESS",
                                "COMPLETED",
                                "FAILED",
                                "CANCELLED",
                                "TIMEOUT"
                              ]
                            },
                            "log_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Entries in `logs`."
                            },
                            "logs": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "job_id": {
                                    "type": "string"
                                  },
                                  "tool_name": {
                                    "description": "Name of the step that produced the entry.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "worker_id": {
                                    "description": "Opaque identifier of the machine that ran the step.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "success": {
                                    "description": "Whether the step succeeded.",
                                    "type": [
                                      "boolean",
                                      "null"
                                    ]
                                  },
                                  "total_time_ms": {
                                    "description": "How long the step took, in milliseconds.",
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "error_message": {
                                    "description": "Why the step failed, when it did.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "stdout_tail": {
                                    "description": "The last lines the step printed.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "created_at": {
                                    "description": "When the entry was recorded.",
                                    "type": [
                                      "string",
                                      "number",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "job_id",
                                  "tool_name",
                                  "worker_id",
                                  "success",
                                  "total_time_ms",
                                  "error_message",
                                  "stdout_tail",
                                  "created_at"
                                ],
                                "additionalProperties": false
                              }
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "log_count",
                            "logs"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44",
                    "status": "COMPLETED",
                    "log_count": 0,
                    "logs": []
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`job_id` has characters outside letters, digits and `_ . : -`, or is too long.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_job_id",
                    "message": "job_id must match ^[A-Za-z0-9_.:-]{1,128}$",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_job_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No job with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "job_not_found",
                    "message": "Job 'analysis_8f3c2a41-6d57-4b1e-9a02-5c7e1d0b9a44' not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#job_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio": {
      "get": {
        "operationId": "list_files",
        "tags": [
          "Files"
        ],
        "summary": "List stored files",
        "description": "Returns the files stored under your account, 100 per page by default, in storage order. Follow `pagination.cursor` while `pagination.has_more` is true. The list shows what is in storage: a file you deleted stays listed until it is removed for good (7 days after deletion, or when you delete it forever). Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Files per page. Defaults to 100; values above 1000 are clamped to 1000, and a value below 1 or not a number falls back to the default.",
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "description": "The `pagination.cursor` of the previous page. Opaque.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of files. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "files": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "file_id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                                "description": "Identifier of the file."
                              },
                              "key": {
                                "type": "string",
                                "description": "Storage path of the file inside your account."
                              },
                              "size": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Size in bytes."
                              },
                              "size_mb": {
                                "type": "string",
                                "description": "Size in mebibytes with two decimals."
                              },
                              "uploaded": {
                                "type": "string",
                                "description": "When the file was stored, as an ISO 8601 timestamp."
                              }
                            },
                            "required": [
                              "file_id",
                              "key",
                              "size",
                              "size_mb",
                              "uploaded"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "pagination": {
                          "type": "object",
                          "properties": {
                            "limit": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "The page size used."
                            },
                            "cursor": {
                              "description": "Pass as `cursor` to get the next page. Absent on the last page.",
                              "type": "string"
                            },
                            "has_more": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "limit",
                            "has_more"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "files",
                        "pagination"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "files": [
                      {
                        "file_id": "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b",
                        "key": "00000000-0000-4000-8000-000000000001/audio/3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav",
                        "size": 176478,
                        "size_mb": "0.17",
                        "uploaded": "2026-10-20T11:53:45.938Z"
                      }
                    ],
                    "pagination": {
                      "limit": 100,
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/analyses": {
      "get": {
        "operationId": "list_file_analyses",
        "tags": [
          "Analysis results"
        ],
        "summary": "List the finished analyses of a file",
        "description": "Returns the analyses that are finished for one of your files: for each, its `category` and the stored `summary`. Analyses that are still running or failed are not listed (the library list shows them as pending or failed). A file with no finished analysis answers an empty list. A file that is not yours, does not exist or is in the trash is 404 `not_found`. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait. Success is `{ data }` without `meta`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or the file id of one of your files."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The finished analyses of the file.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_id": {
                          "type": "string",
                          "description": "Registry identifier of the file."
                        },
                        "analyses": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "category": {
                                "type": "string",
                                "description": "The kind of analysis, for example `rhythm` or `spectral`."
                              },
                              "summary": {
                                "description": "The stored result of that analysis. Its keys depend on the category. Left out when `include_summaries=false`."
                              }
                            },
                            "required": [
                              "category"
                            ],
                            "additionalProperties": false
                          },
                          "description": "The finished analyses."
                        }
                      },
                      "required": [
                        "audio_id",
                        "analyses"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_id": "audio_3f9c1a7d2b60",
                    "analyses": [
                      {
                        "category": "rhythm",
                        "summary": {
                          "tempo": {
                            "bpm": 119.8
                          }
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist, is in the trash, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "File not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/cover": {
      "delete": {
        "operationId": "delete_file_cover",
        "tags": [
          "File details"
        ],
        "summary": "Remove the cover image of a file",
        "description": "Removes the cover image of one of your files. The answer is 204 with no body. Removing a cover that is not there also answers 204. A file that is not yours, does not exist or is in the trash is 404 `not_found`. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or the file id of one of your files."
            }
          }
        ],
        "responses": {
          "204": {
            "description": "The cover is removed. There is no body."
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist, is in the trash, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "File not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_file_cover",
        "tags": [
          "File details"
        ],
        "summary": "Download the cover image of a file",
        "description": "Returns the cover image of one of your files. The response body is the image itself (`image/jpeg`, `image/png` or `image/webp`), not JSON, and may be cached privately for five minutes. Works for files in the trash too. A file with no cover is 404 `cover_not_found`; a file that is not yours or does not exist is 404 `not_found`. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "cover_not_found",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or the file id of one of your files."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The cover image. The body is binary, not JSON.",
            "content": {
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/webp": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file has no cover (`cover_not_found`), or it does not exist or is not yours (`not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cover_not_found",
                    "message": "This file has no cover image",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cover_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "set_file_cover",
        "tags": [
          "File details"
        ],
        "summary": "Set the cover image of a file",
        "description": "Stores a cover image for one of your files, replacing any earlier one. The request body is the image itself, not JSON: a JPEG, PNG or WebP of at most 4 MiB (4194304 bytes). Send the matching `Content-Type`; the format is recognised from the bytes, so a file in another format, or an empty body, is 400 `invalid_image`, and a larger one is 413 `image_too_large`. A file that is not yours, does not exist or is in the trash is 404 `not_found`. The answer is the address to fetch the cover from. If storage or the database is briefly unavailable the route answers 503 `upload_unavailable`; retry after a short wait. Success is `{ data }` without `meta`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "image_too_large",
          "invalid_auth_format",
          "invalid_image",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "upload_unavailable"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or the file id of one of your files."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary",
                "contentEncoding": "binary",
                "description": "The image bytes: JPEG, PNG or WebP, at most 4 MiB."
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary",
                "contentEncoding": "binary",
                "description": "The image bytes: JPEG, PNG or WebP, at most 4 MiB."
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "format": "binary",
                "contentEncoding": "binary",
                "description": "The image bytes: JPEG, PNG or WebP, at most 4 MiB."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The cover is stored.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "cover_url": {
                          "type": "string",
                          "description": "Address to fetch the cover from. Send your API key with the request."
                        }
                      },
                      "required": [
                        "cover_url"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "cover_url": "https://api.scarleta.ai/v1/audio/audio_3f9c1a7d2b60/cover"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is empty or is not a JPEG, PNG or WebP image.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_image",
                    "message": "That doesn't look like a JPEG, PNG or WebP image",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_image"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist, is in the trash, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "File not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The image is larger than 4 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "image_too_large",
                    "message": "Cover images must be 4 MB or smaller",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#image_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/details": {
      "get": {
        "operationId": "get_file_details",
        "tags": [
          "File details"
        ],
        "summary": "Get the details of a file",
        "description": "Returns the editable details of one of your files (title, artist, album, project, credits, tempo and key you entered) next to the tempo and key the analyses found, so you can show either. Works for files in the trash too, so the file page of a trashed file still loads. A file that is not yours or does not exist is 404 `not_found`. `cover_url` is where to fetch the cover image; it is null when the file has none. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait. Success is `{ data }` without `meta`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or the file id of one of your files."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The details of the file.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_id": {
                          "type": "string",
                          "description": "Registry identifier of the file; it starts with `audio_`."
                        },
                        "title": {
                          "description": "Title you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "artist": {
                          "description": "Artist you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "album": {
                          "description": "Album you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "project": {
                          "description": "Project you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits": {
                          "description": "Free-text credits you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "user_bpm": {
                          "description": "Tempo you entered by hand, or null.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "user_key_label": {
                          "description": "Musical key you entered by hand, for example `A minor`, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "analysis_bpm": {
                          "description": "Tempo found by the rhythm analysis, or null when the file has none.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "analysis_key_label": {
                          "description": "Key found by the harmony analysis, or null when the file has none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "embedded": {
                          "anyOf": [
                            {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Tags read from inside the uploaded file (title, artist and so on), or null."
                        },
                        "archived_at": {
                          "description": "When the file was archived, or null.",
                          "type": [
                            "string",
                            "number",
                            "null"
                          ]
                        },
                        "trashed_at": {
                          "description": "When the file was moved to the trash, or null.",
                          "type": [
                            "string",
                            "number",
                            "null"
                          ]
                        },
                        "cover_url": {
                          "description": "Address of the cover image, or null when the file has no cover. Fetch it with your API key.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "audio_id",
                        "title",
                        "artist",
                        "album",
                        "project",
                        "credits",
                        "user_bpm",
                        "user_key_label",
                        "analysis_bpm",
                        "analysis_key_label",
                        "embedded",
                        "archived_at",
                        "trashed_at",
                        "cover_url"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_id": "audio_3f9c1a7d2b60",
                    "title": "Morning Session",
                    "artist": "Example Artist",
                    "album": null,
                    "project": "Demo EP",
                    "credits": "Recorded at home",
                    "user_bpm": 120,
                    "user_key_label": "A minor",
                    "analysis_bpm": 119.8,
                    "analysis_key_label": "A minor",
                    "embedded": null,
                    "archived_at": null,
                    "trashed_at": null,
                    "cover_url": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "File not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update_file_details",
        "tags": [
          "File details"
        ],
        "summary": "Edit the details of a file",
        "description": "Changes the details of one of your files. Send only the fields you want to change; a field you leave out stays as it is, and `null` clears it. A blank text becomes null. `title`, `artist`, `album` and `project` take at most 200 characters, `credits` at most 2000. `user_bpm` is a number from 20 to 300. `user_key_label` is a key such as `A minor` or `C# major`; it is stored in that normal form. Fields the route does not know are ignored. The answer is the updated details, as `GET` returns them. A file that is not yours, does not exist or is in the trash is 404 `not_found`; the file is checked before the fields.\n\nA text field that is not a string is `invalid_field`; a text field longer than its limit is `field_too_long`; a `user_key_label` that is not a valid key is `invalid_key_label`. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait. Success is `{ data }` without `meta`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "field_too_long",
          "invalid_auth_format",
          "invalid_bpm",
          "invalid_field",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_key_label",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "payload_too_large",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or the file id of one of your files."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "description": "Title, at most 200 characters, or null to clear.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "artist": {
                    "description": "Artist, at most 200 characters, or null to clear.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "album": {
                    "description": "Album, at most 200 characters, or null to clear.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "project": {
                    "description": "Project, at most 200 characters, or null to clear.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "credits": {
                    "description": "Credits, at most 2000 characters, or null to clear.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "user_bpm": {
                    "description": "Tempo in beats per minute, from 20 to 300, or null to clear.",
                    "anyOf": [
                      {
                        "type": "number",
                        "minimum": 20,
                        "maximum": 300
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "user_key_label": {
                    "description": "Musical key such as `A minor` or `C# major`, or null to clear.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "title": "Morning Session (final)",
                "user_bpm": 120,
                "user_key_label": "A minor"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_id": {
                          "type": "string",
                          "description": "Registry identifier of the file; it starts with `audio_`."
                        },
                        "title": {
                          "description": "Title you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "artist": {
                          "description": "Artist you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "album": {
                          "description": "Album you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "project": {
                          "description": "Project you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "credits": {
                          "description": "Free-text credits you set, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "user_bpm": {
                          "description": "Tempo you entered by hand, or null.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "user_key_label": {
                          "description": "Musical key you entered by hand, for example `A minor`, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "analysis_bpm": {
                          "description": "Tempo found by the rhythm analysis, or null when the file has none.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "analysis_key_label": {
                          "description": "Key found by the harmony analysis, or null when the file has none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "embedded": {
                          "anyOf": [
                            {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Tags read from inside the uploaded file (title, artist and so on), or null."
                        },
                        "archived_at": {
                          "description": "When the file was archived, or null.",
                          "type": [
                            "string",
                            "number",
                            "null"
                          ]
                        },
                        "trashed_at": {
                          "description": "When the file was moved to the trash, or null.",
                          "type": [
                            "string",
                            "number",
                            "null"
                          ]
                        },
                        "cover_url": {
                          "description": "Address of the cover image, or null when the file has no cover. Fetch it with your API key.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "audio_id",
                        "title",
                        "artist",
                        "album",
                        "project",
                        "credits",
                        "user_bpm",
                        "user_key_label",
                        "analysis_bpm",
                        "analysis_key_label",
                        "embedded",
                        "archived_at",
                        "trashed_at",
                        "cover_url"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_id": "audio_3f9c1a7d2b60",
                    "title": "Morning Session (final)",
                    "artist": "Example Artist",
                    "album": null,
                    "project": "Demo EP",
                    "credits": "Recorded at home",
                    "user_bpm": 120,
                    "user_key_label": "A minor",
                    "analysis_bpm": 119.8,
                    "analysis_key_label": "A minor",
                    "embedded": null,
                    "archived_at": null,
                    "trashed_at": null,
                    "cover_url": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON (`invalid_json`); a text field is not a string (`invalid_field`) or is too long (`field_too_long`); `user_bpm` is out of range (`invalid_bpm`); or `user_key_label` is not a valid key (`invalid_key_label`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "field_too_long",
                    "message": "title must be 200 characters or fewer",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#field_too_long"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist, is in the trash, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "File not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The request body is larger than 64 KB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "payload_too_large",
                    "message": "Request body must be 64 KB or smaller",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#payload_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/midi": {
      "get": {
        "operationId": "download_file_midi",
        "tags": [
          "Analysis results"
        ],
        "summary": "Download the MIDI file of a melody analysis",
        "description": "Returns the melody that the melody analysis found in one of your files as a standard MIDI file. The response body is the file itself (`Content-Type: audio/midi`) with a `Content-Disposition: attachment` header. Send `name` to choose the file name it is saved under; without it the name is the file id with `.mid`. A file with no melody analysis, an analysis without MIDI, or a file that is not yours is 404 `midi_not_found`. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. The melody analysis that creates the MIDI is billed when you run it."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "midi_not_found",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or the file id of one of your files."
            }
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "description": "File name to save the download under. The `.mid` extension is added when missing.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The MIDI file. The body is binary, not JSON.",
            "content": {
              "audio/midi": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file has no melody analysis with a MIDI export, or it is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "midi_not_found",
                    "message": "MIDI file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#midi_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/notes": {
      "get": {
        "operationId": "list_version_notes",
        "tags": [
          "Notes"
        ],
        "summary": "List the notes of a file",
        "description": "Returns the notes you wrote on one file, newest first. A file that is not yours, or does not exist, simply has no notes: the answer is an empty list. On success this route answers `{ data, meta }`, and `meta.request_id` is not the id used in error bodies; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or file id of one of your files."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The notes, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                            "description": "Identifier of the note."
                          },
                          "audio_id": {
                            "type": "string",
                            "description": "The version the note belongs to."
                          },
                          "body": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "description": "ISO 8601 time."
                          },
                          "updated_at": {
                            "type": "string",
                            "description": "ISO 8601 time."
                          }
                        },
                        "required": [
                          "id",
                          "audio_id",
                          "body",
                          "created_at",
                          "updated_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Number of notes returned."
                        }
                      },
                      "required": [
                        "request_id",
                        "count"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                      "audio_id": "audio_3f9c1a7d2b60",
                      "body": "Vocals too loud in the second chorus",
                      "created_at": "2026-10-21T06:13:09.068Z",
                      "updated_at": "2026-10-21T06:13:09.068Z"
                    }
                  ],
                  "meta": {
                    "request_id": "1f6c2a9e-3b47-4d58-9a10-6e2d8c4b7f03",
                    "count": 1
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_version_note",
        "tags": [
          "Notes"
        ],
        "summary": "Add a note to a file",
        "description": "Adds a text note to one of your files. The text is trimmed, must not be empty, and is at most 10000 characters. A file that is not yours, or does not exist, is 404 `not_found`. On success this route answers `{ data, meta }`, and `meta.request_id` is not the id used in error bodies; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "body_too_long",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_body",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or file id of one of your files."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000,
                    "description": "The note text, 1 to 10000 characters after trimming."
                  }
                },
                "required": [
                  "body"
                ],
                "additionalProperties": false
              },
              "example": {
                "body": "Vocals too loud in the second chorus"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The note was created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the note."
                        },
                        "audio_id": {
                          "type": "string",
                          "description": "The version the note belongs to."
                        },
                        "body": {
                          "type": "string"
                        },
                        "created_at": {
                          "type": "string",
                          "description": "ISO 8601 time."
                        },
                        "updated_at": {
                          "type": "string",
                          "description": "ISO 8601 time."
                        }
                      },
                      "required": [
                        "id",
                        "audio_id",
                        "body",
                        "created_at",
                        "updated_at"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "audio_id": "audio_3f9c1a7d2b60",
                    "body": "Vocals too loud in the second chorus",
                    "created_at": "2026-10-21T06:13:09.068Z",
                    "updated_at": "2026-10-21T06:13:09.068Z"
                  },
                  "meta": {
                    "request_id": "1f6c2a9e-3b47-4d58-9a10-6e2d8c4b7f03"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON, `body` is missing or blank (`missing_body`), or it is longer than the limit (`body_too_long`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_body",
                    "message": "body is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_body"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Version audio_0123456789ab not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/notes/{noteId}": {
      "delete": {
        "operationId": "delete_version_note",
        "tags": [
          "Notes"
        ],
        "summary": "Delete a note",
        "description": "Deletes one of your notes. Deleting a note twice, or a note that is not yours, is 404 `not_found`. On success this route answers `{ data, meta }`, and `meta.request_id` is not the id used in error bodies; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_id",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or file id of one of your files."
            }
          },
          {
            "name": "noteId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `id` of the note."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The note is deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "The deleted note."
                        },
                        "status": {
                          "type": "string",
                          "const": "deleted"
                        }
                      },
                      "required": [
                        "id",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "status": "deleted"
                  },
                  "meta": {
                    "request_id": "1f6c2a9e-3b47-4d58-9a10-6e2d8c4b7f03"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`noteId` is not a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_id",
                    "message": "noteId must be a valid UUID",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The note does not exist, is already deleted, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Note 7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/shares": {
      "get": {
        "operationId": "list_audio_shares",
        "tags": [
          "Shares"
        ],
        "summary": "List the share links of a file",
        "description": "Returns every link you created for one file, newest first, including revoked and expired ones (check `active`). A file that is not yours simply has none. On success this route answers `{ data, meta }`, and `meta.request_id` is not the id used in error bodies; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or file id of one of your files."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The links, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                            "description": "Identifier of the share."
                          },
                          "token": {
                            "type": "string",
                            "description": "The secret part of the link. Anyone with the link can open the file, so treat it like a password."
                          },
                          "public_url": {
                            "type": "string",
                            "description": "Path of the public page: `/share/<token>` on www.scarleta.ai."
                          },
                          "audio_id": {
                            "type": "string"
                          },
                          "allow_download": {
                            "type": "boolean",
                            "description": "True when visitors may download the file."
                          },
                          "include_analyses": {
                            "type": "boolean",
                            "description": "True when visitors also see the analysis results."
                          },
                          "expires_at": {
                            "description": "When the link stops working, in milliseconds since the Unix epoch; null for a link that never expires.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "revoked_at": {
                            "description": "When you revoked the link, in milliseconds since the Unix epoch, or null.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "created_at": {
                            "type": "number",
                            "description": "Milliseconds since the Unix epoch."
                          },
                          "active": {
                            "type": "boolean",
                            "description": "False once the link is revoked or has expired."
                          }
                        },
                        "required": [
                          "id",
                          "token",
                          "public_url",
                          "audio_id",
                          "allow_download",
                          "include_analyses",
                          "expires_at",
                          "revoked_at",
                          "created_at",
                          "active"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Links returned."
                        },
                        "active_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "How many of them are still active."
                        }
                      },
                      "required": [
                        "request_id",
                        "count",
                        "active_count"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                      "token": "example-share-token",
                      "public_url": "/share/example-share-token",
                      "audio_id": "audio_3f9c1a7d2b60",
                      "allow_download": false,
                      "include_analyses": false,
                      "expires_at": null,
                      "revoked_at": null,
                      "created_at": 1791333870854,
                      "active": true
                    }
                  ],
                  "meta": {
                    "request_id": "1f6c2a9e-3b47-4d58-9a10-6e2d8c4b7f03",
                    "count": 1,
                    "active_count": 1
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_audio_share",
        "tags": [
          "Shares"
        ],
        "summary": "Create a public share link for a file",
        "description": "Creates a link that lets anyone open one of your files without an account. The defaults are the most private: no download and no analysis results. Send `expires_in_seconds` for a link that stops working, otherwise it never expires. The body is optional; an empty body uses the defaults. `expires_in_seconds` must be positive and at most 315360000. A file that is not yours, or does not exist, is 404 `not_found`. On success this route answers `{ data, meta }`, and `meta.request_id` is not the id used in error bodies; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_expiry",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or file id of one of your files."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expires_in_seconds": {
                    "description": "Seconds until the link stops working, above 0 and at most 315360000. Omit for a link that never expires.",
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 315360000
                  },
                  "allow_download": {
                    "description": "True lets visitors download the file. Defaults to false.",
                    "type": "boolean"
                  },
                  "include_analyses": {
                    "description": "True shows visitors the analysis results. Defaults to false.",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "expires_in_seconds": 3600,
                "allow_download": false,
                "include_analyses": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The link was created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the share."
                        },
                        "token": {
                          "type": "string",
                          "description": "The secret part of the link. Anyone with the link can open the file, so treat it like a password."
                        },
                        "public_url": {
                          "type": "string",
                          "description": "Path of the public page: `/share/<token>` on www.scarleta.ai."
                        },
                        "audio_id": {
                          "type": "string"
                        },
                        "allow_download": {
                          "type": "boolean",
                          "description": "True when visitors may download the file."
                        },
                        "include_analyses": {
                          "type": "boolean",
                          "description": "True when visitors also see the analysis results."
                        },
                        "expires_at": {
                          "description": "When the link stops working, in milliseconds since the Unix epoch; null for a link that never expires.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "revoked_at": {
                          "description": "When you revoked the link, in milliseconds since the Unix epoch, or null.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "created_at": {
                          "type": "number",
                          "description": "Milliseconds since the Unix epoch."
                        },
                        "active": {
                          "type": "boolean",
                          "description": "False once the link is revoked or has expired."
                        }
                      },
                      "required": [
                        "id",
                        "token",
                        "public_url",
                        "audio_id",
                        "allow_download",
                        "include_analyses",
                        "expires_at",
                        "revoked_at",
                        "created_at",
                        "active"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "token": "example-share-token",
                    "public_url": "/share/example-share-token",
                    "audio_id": "audio_3f9c1a7d2b60",
                    "allow_download": false,
                    "include_analyses": false,
                    "expires_at": null,
                    "revoked_at": null,
                    "created_at": 1791333870854,
                    "active": true
                  },
                  "meta": {
                    "request_id": "1f6c2a9e-3b47-4d58-9a10-6e2d8c4b7f03"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON (`invalid_json`), or `expires_in_seconds` is not a positive number within the limit (`invalid_expiry`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_expiry",
                    "message": "expires_in_seconds must be a positive number of seconds",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_expiry"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Version audio_0123456789ab not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{audioId}/shares/{shareId}": {
      "delete": {
        "operationId": "revoke_audio_share",
        "tags": [
          "Shares"
        ],
        "summary": "Revoke a share link",
        "description": "Stops a link from working. The answer is the link with `revoked_at` set and `active` false. Revoking a link twice, a link that is not yours, or an id that is not a UUID is 404 `not_found`. On success this route answers `{ data, meta }`, and `meta.request_id` is not the id used in error bodies; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audioId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or file id of one of your files."
            }
          },
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `id` of the share."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The link is revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the share."
                        },
                        "token": {
                          "type": "string",
                          "description": "The secret part of the link. Anyone with the link can open the file, so treat it like a password."
                        },
                        "public_url": {
                          "type": "string",
                          "description": "Path of the public page: `/share/<token>` on www.scarleta.ai."
                        },
                        "audio_id": {
                          "type": "string"
                        },
                        "allow_download": {
                          "type": "boolean",
                          "description": "True when visitors may download the file."
                        },
                        "include_analyses": {
                          "type": "boolean",
                          "description": "True when visitors also see the analysis results."
                        },
                        "expires_at": {
                          "description": "When the link stops working, in milliseconds since the Unix epoch; null for a link that never expires.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "revoked_at": {
                          "description": "When you revoked the link, in milliseconds since the Unix epoch, or null.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "created_at": {
                          "type": "number",
                          "description": "Milliseconds since the Unix epoch."
                        },
                        "active": {
                          "type": "boolean",
                          "description": "False once the link is revoked or has expired."
                        }
                      },
                      "required": [
                        "id",
                        "token",
                        "public_url",
                        "audio_id",
                        "allow_download",
                        "include_analyses",
                        "expires_at",
                        "revoked_at",
                        "created_at",
                        "active"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "token": "example-share-token",
                    "public_url": "/share/example-share-token",
                    "audio_id": "audio_3f9c1a7d2b60",
                    "allow_download": false,
                    "include_analyses": false,
                    "expires_at": null,
                    "revoked_at": 1791333930854,
                    "created_at": 1791333870854,
                    "active": false
                  },
                  "meta": {
                    "request_id": "1f6c2a9e-3b47-4d58-9a10-6e2d8c4b7f03"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The link does not exist, is already revoked, or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Share 7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{fileId}": {
      "delete": {
        "operationId": "delete_file",
        "tags": [
          "Files"
        ],
        "summary": "Delete a file",
        "description": "Moves one of your files to the trash. It is not erased at once: it stays recoverable for 7 days (`purge_after`), after which it is removed for good. Only your own files can be deleted; any other id, and a file already in the trash, returns 404. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "file_not_found",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `file_id` of one of your files, as returned by the upload routes and the file list. A trailing media extension such as `.wav` is ignored."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file is in the trash. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "file_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the file."
                        },
                        "status": {
                          "type": "string",
                          "const": "trashed"
                        },
                        "trashed_at": {
                          "type": "string",
                          "description": "When the file was moved to the trash, as an ISO 8601 timestamp."
                        },
                        "purge_after": {
                          "type": "string",
                          "description": "When the file is removed for good, as an ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "file_id",
                        "status",
                        "trashed_at",
                        "purge_after"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "file_id": "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b",
                    "status": "trashed",
                    "trashed_at": "2026-10-21T03:40:58.310Z",
                    "purge_after": "2026-10-28T03:40:58.310Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No file with this id in your account, or it is already in the trash.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_not_found",
                    "message": "Audio file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{fileId}/children": {
      "get": {
        "operationId": "list_file_renders",
        "tags": [
          "Renders"
        ],
        "summary": "List the files made from a file",
        "description": "Returns the files that were made from one of your files: crops, effects, noise-reduced versions and stems (the \"renders\" of a take), newest first. Archived renders are left out. Each entry has the `audio_url` to use when analysing it. A file with no renders, a file that does not exist and a file that is not yours all answer an empty list; the route never reveals another account's files. On success this route answers `{ data, meta }`, and `meta` carries counts but no `request_id`. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` of one of your files. A trailing media extension such as `.wav` is ignored."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The renders of the file, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "audio_id": {
                            "type": "string",
                            "description": "Registry identifier of the derived file; it starts with `audio_`."
                          },
                          "name": {
                            "description": "Display name of the derived file, or null.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "relationship_type": {
                            "description": "How it was made from the parent, for example `crop`, `effect`, `stem` or `noise_reduction`.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "derived_role": {
                            "description": "For a stem, which part it is (for example `vocals`); null for the other kinds.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "format": {
                            "description": "File format, for example `wav`, when known.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "file_size_bytes": {
                            "description": "Size in bytes, when known.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "duration_seconds": {
                            "description": "Length of the audio, when known.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "uploaded": {
                            "description": "When the file was created, in milliseconds since the Unix epoch.",
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "analyzed_categories": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Analysis categories this file already has results for."
                          },
                          "audio_url": {
                            "description": "URL to pass as `audio_url` when running an analysis on this file.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "playback_url": {
                            "description": "Link for playing the file in a browser; the same as `audio_url` where that link is signed.",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "audio_id",
                          "name",
                          "relationship_type",
                          "derived_role",
                          "format",
                          "file_size_bytes",
                          "duration_seconds",
                          "uploaded",
                          "analyzed_categories",
                          "audio_url",
                          "playback_url"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Renders returned."
                        }
                      },
                      "required": [
                        "count"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "audio_id": "audio_a81e5c40d7f2",
                      "name": "Stem: vocals",
                      "relationship_type": "stem",
                      "derived_role": "vocals",
                      "format": "wav",
                      "file_size_bytes": 5290044,
                      "duration_seconds": 30.2,
                      "uploaded": 1791333870854,
                      "analyzed_categories": [],
                      "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav",
                      "playback_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav"
                    }
                  ],
                  "meta": {
                    "count": 1
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{fileId}/conversations": {
      "get": {
        "operationId": "list_file_conversations",
        "tags": [
          "File conversations"
        ],
        "summary": "List the conversations about a file",
        "description": "Returns your conversations that were started on one file, newest activity first, so a file page can show the discussions about it. A conversation counts when it was created with the file's `audio_url`, under any of the addresses the same file has been known by. Deleted conversations are left out. Page with `cursor`: while `meta.has_more` is true, pass `meta.cursor` as `cursor` in the next request. A file with no conversations, a file that does not exist and a file that is not yours all answer an empty list. On success this route answers `{ data, meta }`, and `meta` carries counts but no `request_id`. `meta` here also has `cursor` and `has_more`. If the database is briefly unavailable the list is empty rather than an error.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` of one of your files. A trailing media extension such as `.wav` is ignored."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "description": "The `meta.cursor` of the previous page.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of conversations, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "conversation_id": {
                            "type": "string",
                            "description": "Identifier of the conversation."
                          },
                          "title": {
                            "description": "Title of the conversation, or null.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "updated_at": {
                            "description": "When the conversation last changed, in milliseconds since the Unix epoch.",
                            "type": [
                              "number",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "conversation_id",
                          "title",
                          "updated_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Conversations in this page."
                        },
                        "cursor": {
                          "description": "Pass this as `cursor` to get the next page; null on the last page.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_more": {
                          "type": "boolean",
                          "description": "True when more conversations follow."
                        }
                      },
                      "required": [
                        "count",
                        "cursor",
                        "has_more"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "conversation_id": "c3a9f1d2-7b46-4e80-9d15-2f6a8b0c4e71",
                      "title": "Mix notes",
                      "updated_at": 1791333870854
                    }
                  ],
                  "meta": {
                    "count": 1,
                    "cursor": null,
                    "has_more": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/{fileId}/download-url": {
      "post": {
        "operationId": "create_download_url",
        "tags": [
          "Files"
        ],
        "summary": "Create a download link",
        "description": "Creates a link for downloading one of your files. Fetch `download_url` with a plain `GET` and no API key; the response is the file with a `Content-Disposition: attachment` header. The link works once, and only until `expires_in` seconds have passed (60 to 86400; 3600 if you send no body). A second request, or one after expiry, gets 403 `invalid_download_token`; create a new link instead. Only your own files can be linked: any other id returns 404.\n\nSend `filename` to choose the name the download is saved under (ignored when longer than 200 characters). The body is optional; one that is not valid JSON is treated as empty. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "file_not_found",
          "file_too_large",
          "invalid_audio_file",
          "invalid_auth_format",
          "invalid_expires_in",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `file_id` of one of your files, as returned by the upload routes and the file list. A trailing media extension such as `.wav` is ignored."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expires_in": {
                    "description": "Seconds the link stays valid, 60 to 86400. Defaults to 3600.",
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 86400
                  },
                  "filename": {
                    "description": "File name for the download, at most 200 characters.",
                    "type": "string"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "expires_in": 3600,
                "filename": "morning-session.wav"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Link created. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "download_url": {
                          "type": "string",
                          "description": "Address to `GET` the file from. Works once."
                        },
                        "file_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the file."
                        },
                        "expires_in": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Seconds the link stays valid."
                        }
                      },
                      "required": [
                        "download_url",
                        "file_id",
                        "expires_in"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "download_url": "https://api.scarleta.ai/v1/audio/download/dt_v1_859fca05-4d2f-41ce-89b7-bd1d8681adc9?sig=632d9afd5adb5160267986aa97911c50&fn=morning-session.wav",
                    "file_id": "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b",
                    "expires_in": 3600
                  }
                }
              }
            }
          },
          "400": {
            "description": "`expires_in` is not an integer in range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_expires_in",
                    "message": "expires_in must be an integer between 60 and 86400",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_expires_in"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No file with this id in your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_not_found",
                    "message": "Audio file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The stored file is over the size limit and cannot be linked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_too_large",
                    "message": "Uploaded file exceeds the per-file size limit",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_too_large"
                  }
                }
              }
            }
          },
          "415": {
            "description": "The stored file is not audio and cannot be linked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_audio_file",
                    "message": "Stored file is not a supported audio/media format",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_audio_file"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/archive": {
      "post": {
        "operationId": "archive_files",
        "tags": [
          "File actions"
        ],
        "summary": "Archive or unarchive files",
        "description": "Moves up to 100 files into the archive (hidden from the main library, kept in storage) or back out of it with `archived: false`. Archiving is not deleting: the files still count toward your storage. Ids that are not your files are skipped, and `updated` counts the files the call was applied to (files already in the requested state are counted too). Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_archived",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_audio_ids",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "too_many_ids",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "The files: library identifiers (`audio_id`) or storage identifiers (`file_id`) of your files, 1 to 100."
                  },
                  "archived": {
                    "description": "`true` (the default) to archive, `false` to bring the files back.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "audio_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_bbb14949dc19"
                ],
                "archived": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call was applied. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "updated": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Your files the call was applied to."
                        },
                        "requested": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Distinct files named in the request, after ids that name the same file are merged."
                        },
                        "archived": {
                          "type": "boolean",
                          "description": "The state that was applied."
                        }
                      },
                      "required": [
                        "updated",
                        "requested",
                        "archived"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "updated": 2,
                    "requested": 2,
                    "archived": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, `archived` is not a boolean, or `audio_ids` is missing, empty (`missing_audio_ids`) or too long (`too_many_ids`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_archived",
                    "message": "archived must be a boolean",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_archived"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The change could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/archives": {
      "post": {
        "operationId": "create_archive",
        "tags": [
          "Archives"
        ],
        "summary": "Download files as a zip",
        "description": "Packs files you choose into a zip. Send up to 5000 `audio_ids` of your own files. A selection of at most 1000 files and 2 GiB is answered at once with `mode: \"stream\"` and a `download_url`: fetch it with a plain `GET` and no API key within 10 minutes; it works once and returns the zip. A larger selection returns `202` with `mode: \"async\"`: the zip is built in the background in parts, read the archive until it is `completed`, then fetch each part (the archive stays downloadable for 7 days). Every id must be one of your files, otherwise nothing is packed and the call returns 404 `files_not_found` naming the ids it could not find. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "archive_unavailable",
          "auth_unavailable",
          "db_unavailable",
          "file_unavailable",
          "files_not_found",
          "invalid_audio_ids",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "maxItems": 5000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "Library identifiers (`audio_id`) of the files to pack, 1 to 5000."
                  }
                },
                "required": [
                  "audio_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_bbb14949dc19"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A one-time download link. The body is `{ data }` without `meta`. The response carries `Cache-Control: no-store`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "mode": {
                          "type": "string",
                          "const": "stream"
                        },
                        "job_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the archive."
                        },
                        "download_url": {
                          "type": "string",
                          "description": "Address to `GET` the zip from, with no API key. Works once."
                        },
                        "expires_at": {
                          "type": "string",
                          "description": "When the link stops working, as an ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "mode",
                        "job_id",
                        "download_url",
                        "expires_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "mode": "stream",
                    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
                    "download_url": "https://api.scarleta.ai/v1/audio/archives/stream/Zk3p0q8vN1x2Y4b6C8d0E2f4G6h8J0kL2mN4pQ6rS8t",
                    "expires_at": "2026-10-20T12:03:45.938Z"
                  }
                }
              }
            }
          },
          "202": {
            "description": "The archive is being built. Read it until it is completed. Same body shape rules as the 200.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "mode": {
                          "type": "string",
                          "const": "async"
                        },
                        "job_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the archive."
                        }
                      },
                      "required": [
                        "mode",
                        "job_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "mode": "async",
                    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`audio_ids` is empty, too long, or has an entry that is not a non-empty string.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_audio_ids",
                    "message": "audio_ids must be a list of 1–5000 file ids",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_audio_ids"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "At least one id is not one of your files; `error.details.missing` lists them.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "files_not_found",
                    "message": "Some of these files were not found.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#files_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "A file in the selection has no readable content at the moment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_unavailable",
                    "message": "“morning-session.wav” can't be downloaded right now.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_unavailable"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The background build could not start. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "archive_unavailable",
                    "message": "Your download couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#archive_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/archives/{jobId}": {
      "get": {
        "operationId": "get_archive",
        "tags": [
          "Archives"
        ],
        "summary": "Get an archive",
        "description": "Returns the state of an archive you requested: its status, progress and, once finished, its parts. Only your own archives can be read; any other id returns 404. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "archive_not_found",
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `job_id` returned when the archive was requested."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The archive. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "job_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the archive."
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "selection",
                            "takeout"
                          ],
                          "description": "`selection` for files you chose, `takeout` for your whole library."
                        },
                        "mode": {
                          "type": "string",
                          "enum": [
                            "stream",
                            "async"
                          ],
                          "description": "`stream` is a one-time download link; `async` is built in the background in parts."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "queued",
                            "running",
                            "completed",
                            "failed",
                            "expired"
                          ]
                        },
                        "file_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "total_bytes": {
                          "type": "number",
                          "description": "Total size of the files in bytes."
                        },
                        "progress_bytes": {
                          "type": "number",
                          "description": "Bytes processed so far."
                        },
                        "parts": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "n": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "bytes": {
                                "type": "number"
                              },
                              "file_count": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            "required": [
                              "n",
                              "bytes",
                              "file_count"
                            ],
                            "additionalProperties": false
                          },
                          "description": "The finished zip parts, once `completed`."
                        },
                        "error": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        },
                        "completed_at": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "expires_at": {
                          "description": "When the download stops working.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "job_id",
                        "kind",
                        "mode",
                        "status",
                        "file_count",
                        "total_bytes",
                        "progress_bytes",
                        "parts",
                        "error",
                        "created_at",
                        "completed_at",
                        "expires_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
                    "kind": "selection",
                    "mode": "stream",
                    "status": "queued",
                    "file_count": 1,
                    "total_bytes": 1920044,
                    "progress_bytes": 0,
                    "parts": [],
                    "error": null,
                    "created_at": "2026-10-20T11:53:45.938Z",
                    "completed_at": null,
                    "expires_at": "2026-10-20T12:03:45.938Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No archive with this id in your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "archive_not_found",
                    "message": "Download not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#archive_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The archive could not be read. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available; try again",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/archives/{jobId}/parts/{n}/url": {
      "get": {
        "operationId": "get_archive_part_url",
        "tags": [
          "Archives"
        ],
        "summary": "Get the download link of an archive part",
        "description": "For an archive that is built in the background (`mode: \"async\"`), returns a link for one finished zip part. Fetch `url` with a plain `GET` and no API key within 60 minutes; ask again for a fresh link when it expires. Part numbers start at 1 and are listed in the archive's `parts`. A one-time download link (`mode: \"stream\"`) has no parts. The response carries `Cache-Control: no-store`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "archive_expired",
          "archive_not_found",
          "archive_not_ready",
          "archive_part_not_found",
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "storage_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `job_id` of the archive."
            }
          },
          {
            "name": "n",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d+$",
              "description": "Part number, starting at 1."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A link for the part. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "description": "Where to `GET` the part. Opaque; use it as returned."
                        },
                        "expires_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "url",
                        "expires_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "url": "https://storage.example.com/archives/part-1.zip?signature=…",
                    "expires_at": "2026-10-21T05:00:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No archive with this id in your account (`archive_not_found`), or it has no such part.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "archive_part_not_found",
                    "message": "Download part not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#archive_part_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The archive has not finished building. Read it until its status is `completed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "archive_not_ready",
                    "message": "This download is not ready yet.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#archive_not_ready"
                  }
                }
              }
            }
          },
          "410": {
            "description": "The archive is past its retention time. Start a new one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "archive_expired",
                    "message": "This download has expired.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#archive_expired"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Storage cannot create the link at the moment (`storage_unavailable`), or the database is unavailable (`db_unavailable`). Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "storage_unavailable",
                    "message": "Download links are not available right now; try again",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#storage_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/archives/takeout": {
      "post": {
        "operationId": "start_takeout",
        "tags": [
          "Archives"
        ],
        "summary": "Download your whole library",
        "description": "Starts a background build of a zip of your entire library (originals and their renders), split into parts of at most 50 GiB. Read the archive with the returned `job_id` until it is `completed`, then fetch each part with the part URL route; the parts stay downloadable for 7 days. Only one takeout can be in progress at a time: asking again while one is queued or running returns the same `job_id` with HTTP 200 instead of 202. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "archive_unavailable",
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "A takeout is already in progress; this is its identifier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "job_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the takeout already in progress."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "queued",
                            "running"
                          ]
                        }
                      },
                      "required": [
                        "job_id",
                        "status"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
                    "status": "running"
                  }
                }
              }
            }
          },
          "202": {
            "description": "A new takeout was started. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "job_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the archive."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "queued",
                            "running"
                          ]
                        }
                      },
                      "required": [
                        "job_id",
                        "status"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "job_id": "5d7f9b1c-3e5a-4c7e-9b0d-1f2a3b4c5d6e",
                    "status": "queued"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The background build could not start. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "archive_unavailable",
                    "message": "Your download couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#archive_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/best": {
      "post": {
        "operationId": "mark_best_version",
        "tags": [
          "File actions"
        ],
        "summary": "Mark a file as the best version",
        "description": "Marks one file as the best version of its track: every other version of the same track loses the mark. A file that is not part of a track is simply marked. Only your own, current files qualify: an id that is not yours, a file in the archive and a temporary file return 404. Use the `audio_id` (a `file_id` is not accepted here). Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_audio_id",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Library identifier (`audio_id`) of the file."
                  }
                },
                "required": [
                  "audio_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_id": "audio_bbb14949dc19"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The file is now the best version. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_id": {
                          "type": "string"
                        },
                        "is_best": {
                          "type": "boolean",
                          "const": true
                        }
                      },
                      "required": [
                        "audio_id",
                        "is_best"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_id": "audio_bbb14949dc19",
                    "is_best": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON or has no `audio_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_id",
                    "message": "audio_id is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No current file of yours has this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Audio not found or not owned",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The mark could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/bulk-delete": {
      "post": {
        "operationId": "bulk_delete_files",
        "tags": [
          "File actions"
        ],
        "summary": "Delete several files",
        "description": "Moves up to 100 files to the trash in one call, with one result per id. Like deleting a single file, this is not final: trashed files stay recoverable for 7 days. An id that is not one of your files returns `deleted: false` with `reason: \"not_found\"`, and a file already in the trash returns `reason: \"already_trashed\"`; neither fails the call. If the database is unavailable the call still returns 200 with `reason: \"db_unavailable\"` on every id, so check each result. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_audio_ids",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "too_many_ids",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "The files to delete: library identifiers (`audio_id`) or storage identifiers (`file_id`) of your files, 1 to 100."
                  }
                },
                "required": [
                  "audio_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_bbb14949dc19"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per id. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "audio_id": {
                                "type": "string",
                                "description": "The file that was trashed, or the id you sent when it was not."
                              },
                              "deleted": {
                                "type": "boolean"
                              },
                              "reason": {
                                "description": "Why `deleted` is false.",
                                "type": "string",
                                "enum": [
                                  "not_found",
                                  "already_trashed",
                                  "db_unavailable"
                                ]
                              }
                            },
                            "required": [
                              "audio_id",
                              "deleted"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "results"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "results": [
                      {
                        "audio_id": "audio_bbb14949dc19",
                        "deleted": true
                      },
                      {
                        "audio_id": "audio_000000000000",
                        "deleted": false,
                        "reason": "not_found"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, `audio_ids` is missing or empty, or it names more files than the limit (`too_many_ids`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_ids",
                    "message": "audio_ids must be a non-empty array",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_ids"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/duplicates/check": {
      "post": {
        "operationId": "check_duplicates",
        "tags": [
          "Imports and duplicates"
        ],
        "summary": "Check files for duplicates",
        "description": "Tells you which of your files you already have, before you upload them. Send up to 1000 items, each with the SHA-256 of a file's bytes; the answer lists the items whose hash matches a file in your library (originals only, not renders). An item with no match is simply absent from `matches`. Hashes you sent at upload time are checked against the real bytes later, so a match is reliable but a brand-new upload may not match yet. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; this route does not use up the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "duplicates_unavailable",
          "invalid_auth_format",
          "invalid_items",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_sha256",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "minItems": 1,
                    "maxItems": 1000,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "ref": {
                          "type": "string",
                          "minLength": 1,
                          "description": "Your own label for the file (a path or an id). Echoed back on a match."
                        },
                        "sha256": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{64}$",
                          "description": "SHA-256 of the file bytes as 64 lowercase hexadecimal characters."
                        },
                        "size_bytes": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Size of the file in bytes."
                        }
                      },
                      "required": [
                        "ref",
                        "sha256",
                        "size_bytes"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Files to check, 1 to 1000 items."
                  }
                },
                "required": [
                  "items"
                ],
                "additionalProperties": false
              },
              "example": {
                "items": [
                  {
                    "ref": "morning-session.wav",
                    "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
                    "size_bytes": 1920044
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The matching items. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "matches": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "ref": {
                                "type": "string",
                                "description": "The `ref` of the matching item you sent."
                              },
                              "audio_id": {
                                "type": "string",
                                "description": "Library identifier of the file you already have."
                              },
                              "file_id": {
                                "description": "Storage identifier of that file, when known.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "name": {
                                "description": "Display name of that file.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "uploaded_at": {
                                "type": "string",
                                "description": "When that file was uploaded, as an ISO 8601 timestamp."
                              },
                              "track_group_id": {
                                "description": "Identifier of the track the file is a version of, if any.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "ref",
                              "audio_id",
                              "file_id",
                              "name",
                              "uploaded_at",
                              "track_group_id"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "matches"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "matches": [
                      {
                        "ref": "morning-session.wav",
                        "audio_id": "audio_bbb14949dc19",
                        "file_id": "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b",
                        "name": "morning-session.wav",
                        "uploaded_at": "2026-10-20T11:53:45.938Z",
                        "track_group_id": null
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "`items` is empty or too long, or an item has no `ref`, a malformed `sha256` or a negative size.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_items",
                    "message": "items must be a non-empty array",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_items"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The check is temporarily unavailable. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "duplicates_unavailable",
                    "message": "Couldn't check for duplicates. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#duplicates_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/imports": {
      "get": {
        "operationId": "list_imports",
        "tags": [
          "Imports and duplicates"
        ],
        "summary": "List imports",
        "description": "Returns your imports, newest first, at most 100; there is no paging, so older imports are not returned. Add `active=1` to list only the ones still in progress (`queued` or `running`). Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "active",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Set to `1` to list only imports that are still in progress.",
              "type": "string",
              "const": "1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Your imports. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "imports": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "import_id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                                "description": "Identifier of the import."
                              },
                              "provider": {
                                "type": "string",
                                "enum": [
                                  "link",
                                  "google_drive",
                                  "dropbox"
                                ],
                                "description": "Where the file comes from. Only `link` can be requested today."
                              },
                              "source_label": {
                                "type": "string",
                                "description": "The host and path of the link, without any query string."
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "queued",
                                  "running",
                                  "completed",
                                  "failed",
                                  "rejected"
                                ],
                                "description": "`queued` and `running` are in progress; the other three are final."
                              },
                              "audio_id": {
                                "description": "Library identifier of the imported file once `completed`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "bytes": {
                                "description": "Size of the imported file in bytes once `completed`.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "tags": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "error_code": {
                                "description": "Why the import failed or was rejected, when it did.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "error_message": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              },
                              "updated_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              }
                            },
                            "required": [
                              "import_id",
                              "provider",
                              "source_label",
                              "status",
                              "audio_id",
                              "bytes",
                              "tags",
                              "error_code",
                              "error_message",
                              "created_at",
                              "updated_at"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "imports"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "imports": [
                      {
                        "import_id": "2b4d6f80-1a3c-4e5f-8071-92a3b4c5d6e7",
                        "provider": "link",
                        "source_label": "example.com/audio/morning-session.wav",
                        "status": "completed",
                        "audio_id": "audio_bbb14949dc19",
                        "bytes": 1920044,
                        "tags": [
                          "morning"
                        ],
                        "error_code": null,
                        "error_message": null,
                        "created_at": "2026-10-20T11:53:45.938Z",
                        "updated_at": "2026-10-20T11:53:45.938Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The list could not be read. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available; try again",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_import",
        "tags": [
          "Imports and duplicates"
        ],
        "summary": "Import a file from a link",
        "description": "Asks Scarleta to fetch an audio file from a public link and add it to your library, so you do not have to download and re-upload it. The call returns `202` at once with the import in state `queued`; read the import (or list the active ones) until its `status` is final. A completed import carries the new file's `audio_id`. The link must be a public `http` or `https` address that serves audio; links to private or internal addresses are refused with 400 `invalid_url`, and a rejected request is still recorded in your import list with status `rejected`. Only `provider: \"link\"` is available today; any other provider returns 400 `unsupported_provider`. If the import service cannot start the job, the call still returns `202` with the import already `failed` (`error_code: \"import_unavailable\"`). Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge; the imported file counts toward your storage."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_tags",
          "invalid_url",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "tag_too_long",
          "too_many_tags",
          "unauthorized",
          "unsupported_provider"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "provider": {
                    "type": "string",
                    "const": "link",
                    "description": "The source type. Only `link` is available."
                  },
                  "url": {
                    "type": "string",
                    "description": "Public address of the audio file."
                  },
                  "tags": {
                    "description": "Tags to put on the imported file, at most 50 of at most 64 characters each.",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 64
                    }
                  }
                },
                "required": [
                  "provider",
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "provider": "link",
                "url": "https://example.com/audio/morning-session.wav",
                "tags": [
                  "morning"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The import is queued. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "imports": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "import_id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                                "description": "Identifier of the import."
                              },
                              "provider": {
                                "type": "string",
                                "enum": [
                                  "link",
                                  "google_drive",
                                  "dropbox"
                                ],
                                "description": "Where the file comes from. Only `link` can be requested today."
                              },
                              "source_label": {
                                "type": "string",
                                "description": "The host and path of the link, without any query string."
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "queued",
                                  "running",
                                  "completed",
                                  "failed",
                                  "rejected"
                                ],
                                "description": "`queued` and `running` are in progress; the other three are final."
                              },
                              "audio_id": {
                                "description": "Library identifier of the imported file once `completed`.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "bytes": {
                                "description": "Size of the imported file in bytes once `completed`.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "tags": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "error_code": {
                                "description": "Why the import failed or was rejected, when it did.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "error_message": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              },
                              "updated_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              }
                            },
                            "required": [
                              "import_id",
                              "provider",
                              "source_label",
                              "status",
                              "audio_id",
                              "bytes",
                              "tags",
                              "error_code",
                              "error_message",
                              "created_at",
                              "updated_at"
                            ],
                            "additionalProperties": false
                          },
                          "description": "One entry for the import just created."
                        }
                      },
                      "required": [
                        "imports"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "imports": [
                      {
                        "import_id": "2b4d6f80-1a3c-4e5f-8071-92a3b4c5d6e7",
                        "provider": "link",
                        "source_label": "example.com/audio/morning-session.wav",
                        "status": "queued",
                        "audio_id": null,
                        "bytes": null,
                        "tags": [
                          "morning"
                        ],
                        "error_code": null,
                        "error_message": null,
                        "created_at": "2026-10-20T11:53:45.938Z",
                        "updated_at": "2026-10-20T11:53:45.938Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "The provider is not supported, the link is empty, malformed, or points to a private or unsafe address, or `tags` is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_url",
                    "message": "That link can't be imported.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_url"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The import could not be recorded. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available; try again",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/imports/{importId}": {
      "get": {
        "operationId": "get_import",
        "tags": [
          "Imports and duplicates"
        ],
        "summary": "Get an import",
        "description": "Returns one import. Poll it after creating the import until `status` is `completed`, `failed` or `rejected`. Only imports created by your own account can be read; any other id returns 404. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "import_not_found",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "importId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `import_id` returned when the import was created."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The import. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "import_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the import."
                        },
                        "provider": {
                          "type": "string",
                          "enum": [
                            "link",
                            "google_drive",
                            "dropbox"
                          ],
                          "description": "Where the file comes from. Only `link` can be requested today."
                        },
                        "source_label": {
                          "type": "string",
                          "description": "The host and path of the link, without any query string."
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "queued",
                            "running",
                            "completed",
                            "failed",
                            "rejected"
                          ],
                          "description": "`queued` and `running` are in progress; the other three are final."
                        },
                        "audio_id": {
                          "description": "Library identifier of the imported file once `completed`.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "bytes": {
                          "description": "Size of the imported file in bytes once `completed`.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "tags": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "error_code": {
                          "description": "Why the import failed or was rejected, when it did.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "error_message": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        },
                        "updated_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "import_id",
                        "provider",
                        "source_label",
                        "status",
                        "audio_id",
                        "bytes",
                        "tags",
                        "error_code",
                        "error_message",
                        "created_at",
                        "updated_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "import_id": "2b4d6f80-1a3c-4e5f-8071-92a3b4c5d6e7",
                    "provider": "link",
                    "source_label": "example.com/audio/morning-session.wav",
                    "status": "completed",
                    "audio_id": "audio_bbb14949dc19",
                    "bytes": 1920044,
                    "tags": [
                      "morning"
                    ],
                    "error_code": null,
                    "error_message": null,
                    "created_at": "2026-10-20T11:53:45.938Z",
                    "updated_at": "2026-10-20T11:53:45.938Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No import with this id in your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "import_not_found",
                    "message": "Import not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#import_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The import could not be read. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available; try again",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library": {
      "get": {
        "operationId": "list_library",
        "tags": [
          "Library"
        ],
        "summary": "List the library",
        "description": "Lists your files grouped into tracks, newest first by default. A track holds one file, or several versions of the same song that you grouped. Each version includes the analyses it already has, plus its tags and archive state. Only your own files are ever returned.\n\nPage with `limit` and `cursor`: pass `pagination.cursor` from one response as `cursor` in the next while `pagination.has_more` is true. `limit` is 1 to 200. The analysis results make responses large; send `include_summaries=false` to receive only the category names. With summaries, an array inside a summary object that holds more than 2048 values in total (counting every number or string, also inside nested arrays, such as an embedding or a spectrogram; each record of a list of records counts as one, plus any array inside it) is left out of the list, and its path is named in the summary's `omitted_large_arrays`. A summary that is itself an array is returned whole. `GET /v1/audio/:audioId/analyses` returns the complete summary.\n\n**View mode.** Send `view` (a saved view id) and/or `q` (a view definition as base64url JSON, `{\"version\":2,\"filters\":{...}}`) and the route reads the library through that view instead. The response then carries the standard `{ data, meta }` envelope with an `X-Request-ID` header, `data` also has `total_tracks`, `coverage` and `view`, tracks have `hidden_versions` and `group_keys`, versions have `values`, `details`, `starred` and `duration_seconds`, and `limit` is at most 100. An unknown `view` is 404 `view_not_found`; an invalid `q` is 400 `invalid_config`; grouping by sound before building sound groups is 400 `invalid_group`.\n\nWithout `view` and `q` the route answers with the older body shape: success is `{ data }` with no `meta`, errors for bad query values are `{ error, message }`, and the older bodies have no `request_id` of their own.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_config",
          "invalid_group",
          "invalid_key",
          "invalid_key_format",
          "invalid_limit",
          "invalid_sort_dir",
          "invalid_sort_key",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "too_many_filter_tags",
          "unauthorized",
          "view_not_found"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Tracks per page, 1 to 200 (at most 100 in view mode).",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "description": "The `pagination.cursor` of the previous page.",
              "type": "string"
            }
          },
          {
            "name": "sort_key",
            "in": "query",
            "required": false,
            "schema": {
              "description": "What to sort by. Defaults to `uploaded`.",
              "type": "string",
              "enum": [
                "uploaded",
                "name",
                "size",
                "last_activity",
                "tags"
              ]
            }
          },
          {
            "name": "sort_dir",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Sort direction. Defaults to `desc`.",
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "filter_tags",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Comma-separated tags to keep, at most 25.",
              "type": "string"
            }
          },
          {
            "name": "filter_analysis_type",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Keep files that have this analysis category.",
              "type": "string"
            }
          },
          {
            "name": "filter_date_from",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Keep files uploaded at or after this time, in milliseconds since the Unix epoch.",
              "type": "number"
            }
          },
          {
            "name": "filter_date_to",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Keep files uploaded at or before this time, in milliseconds since the Unix epoch.",
              "type": "number"
            }
          },
          {
            "name": "filter_archived",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`true` returns only archived files. Archived files are hidden otherwise.",
              "type": "string",
              "enum": [
                "true"
              ]
            }
          },
          {
            "name": "view",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Id of one of your saved views. Switches the route to view mode; see the description.",
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "description": "A view definition, JSON encoded as base64url. Switches the route to view mode; see the description.",
              "type": "string"
            }
          },
          {
            "name": "include_summaries",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`false` leaves out the stored analysis results and keeps only the category names. Defaults to `true`.",
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of tracks. Without `view` and `q` this response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "storage": {
                          "type": "object",
                          "properties": {
                            "used_bytes": {
                              "type": "number",
                              "description": "Bytes your files currently use."
                            },
                            "cap_bytes": {
                              "type": "number",
                              "description": "The storage allowance shown for the account, in bytes."
                            },
                            "tier": {
                              "type": "string",
                              "enum": [
                                "free",
                                "paid"
                              ],
                              "description": "Whether the account is on the free or the paid tier."
                            },
                            "past_due": {
                              "type": "boolean",
                              "description": "True when the account has an unpaid storage overage."
                            },
                            "enforced": {
                              "type": "boolean",
                              "description": "True when storage locks are actually applied."
                            }
                          },
                          "required": [
                            "used_bytes",
                            "cap_bytes",
                            "tier",
                            "past_due",
                            "enforced"
                          ],
                          "additionalProperties": false
                        },
                        "tracks": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Track identifier."
                              },
                              "name": {
                                "type": "string",
                                "description": "Name of the newest version."
                              },
                              "versions": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "string",
                                      "description": "Identifier of this version of the track. Use it wherever a route asks for a file id."
                                    },
                                    "audio_id": {
                                      "type": "string",
                                      "description": "Registry identifier of the file; it starts with `audio_`."
                                    },
                                    "name": {
                                      "type": "string",
                                      "description": "Display name of the file."
                                    },
                                    "label": {
                                      "type": "string",
                                      "description": "Short label shown for this version."
                                    },
                                    "uploaded": {
                                      "description": "When the file was uploaded, in milliseconds since the Unix epoch.",
                                      "type": [
                                        "number",
                                        "null"
                                      ]
                                    },
                                    "file_size_bytes": {
                                      "description": "Size of the stored file in bytes, when known.",
                                      "type": [
                                        "number",
                                        "null"
                                      ]
                                    },
                                    "format": {
                                      "description": "File format, for example `wav`, when known.",
                                      "type": [
                                        "string",
                                        "null"
                                      ]
                                    },
                                    "download_available": {
                                      "type": "boolean",
                                      "description": "True when the original file is stored and can be downloaded."
                                    },
                                    "audio_url": {
                                      "description": "URL to pass as `audio_url` when running an analysis on this file. Null when the original is not stored.",
                                      "type": [
                                        "string",
                                        "null"
                                      ]
                                    },
                                    "playback_url": {
                                      "description": "Short-lived URL for playing the file in a browser. Null when `audio_url` is null.",
                                      "type": [
                                        "string",
                                        "null"
                                      ]
                                    },
                                    "analyses": {
                                      "type": "array",
                                      "items": {
                                        "type": "object",
                                        "properties": {
                                          "category": {
                                            "type": "string",
                                            "description": "The kind of analysis, for example `rhythm` or `spectral`."
                                          },
                                          "summary": {
                                            "description": "The stored result of that analysis. Its keys depend on the category. Left out when `include_summaries=false`."
                                          }
                                        },
                                        "required": [
                                          "category"
                                        ],
                                        "additionalProperties": false
                                      },
                                      "description": "The analyses this file already has."
                                    },
                                    "locked": {
                                      "type": "boolean",
                                      "description": "True when the file is locked because of an unpaid storage overage. Locked files stay listed."
                                    },
                                    "pending_categories": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      },
                                      "description": "Analysis categories still running on this file."
                                    },
                                    "failed_categories": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      },
                                      "description": "Analysis categories that failed and have no completed result."
                                    },
                                    "tags": {
                                      "type": "array",
                                      "items": {
                                        "type": "string"
                                      },
                                      "description": "Tags you added to this file."
                                    },
                                    "is_best": {
                                      "type": "boolean",
                                      "description": "True when this version is marked as the best take of its track."
                                    },
                                    "archived_at": {
                                      "description": "When the file was archived, or null.",
                                      "type": [
                                        "string",
                                        "number",
                                        "null"
                                      ]
                                    },
                                    "last_activity": {
                                      "description": "The latest of upload time, newest analysis result and newest note, in milliseconds since the Unix epoch.",
                                      "type": [
                                        "number",
                                        "null"
                                      ]
                                    },
                                    "duration_seconds": {
                                      "description": "Length of the audio. Present only when you send `view` or `q`.",
                                      "type": [
                                        "number",
                                        "null"
                                      ]
                                    },
                                    "values": {
                                      "description": "The searchable values of this file (`bpm`, `key_label`, ...) with `bpm_source` and `key_source`. Present only when you send `view` or `q`.",
                                      "type": "object",
                                      "propertyNames": {
                                        "type": "string"
                                      },
                                      "additionalProperties": {}
                                    },
                                    "details": {
                                      "description": "File details such as title, artist and trash times. Present only when you send `view` or `q`.",
                                      "type": "object",
                                      "propertyNames": {
                                        "type": "string"
                                      },
                                      "additionalProperties": {}
                                    },
                                    "starred": {
                                      "description": "True when the file is starred. Present only when you send `view` or `q`.",
                                      "type": "boolean"
                                    },
                                    "similarity": {
                                      "description": "Similarity to a `sounds_like` reference. Present only with that filter.",
                                      "type": [
                                        "number",
                                        "null"
                                      ]
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "audio_id",
                                    "name",
                                    "label",
                                    "uploaded",
                                    "file_size_bytes",
                                    "format",
                                    "download_available",
                                    "audio_url",
                                    "playback_url",
                                    "analyses",
                                    "locked",
                                    "pending_categories",
                                    "failed_categories",
                                    "tags",
                                    "is_best",
                                    "archived_at",
                                    "last_activity"
                                  ],
                                  "additionalProperties": false
                                },
                                "description": "Versions of the track, newest first."
                              },
                              "hidden_versions": {
                                "description": "Versions the view hides. View mode only.",
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "group_keys": {
                                "description": "The group buckets of the track. View mode only.",
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "versions"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "pagination": {
                          "type": "object",
                          "properties": {
                            "limit": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "The page size used, or null when you sent no `limit`."
                            },
                            "cursor": {
                              "description": "Pass this as `cursor` to get the next page.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "has_more": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "limit",
                            "cursor",
                            "has_more"
                          ],
                          "additionalProperties": false
                        },
                        "total_tracks": {
                          "description": "Tracks the view matches. View mode only.",
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "coverage": {
                          "description": "How many files have each searchable value. View mode only.",
                          "type": "object",
                          "properties": {
                            "total_library_size": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files in scope before any value filter."
                            },
                            "indexed": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "description": "For each searchable value (`bpm`, `key_label`, ...), how many files in scope have it."
                            }
                          },
                          "required": [
                            "total_library_size",
                            "indexed"
                          ],
                          "additionalProperties": false
                        },
                        "view": {
                          "description": "The view that was applied. View mode only.",
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "name": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "definition": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            },
                            "dropped": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "definition",
                            "dropped"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "storage",
                        "tracks",
                        "pagination"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "storage": {
                      "used_bytes": 184220160,
                      "cap_bytes": 1099511627776,
                      "tier": "paid",
                      "past_due": false,
                      "enforced": true
                    },
                    "tracks": [
                      {
                        "id": "audio_3f9c1a7d2b60",
                        "name": "demo-mix.wav",
                        "versions": [
                          {
                            "id": "audio_3f9c1a7d2b60",
                            "audio_id": "audio_3f9c1a7d2b60",
                            "name": "demo-mix.wav",
                            "label": "demo-mix.wav",
                            "uploaded": 1791333870854,
                            "file_size_bytes": 5290044,
                            "format": "wav",
                            "download_available": true,
                            "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav",
                            "playback_url": null,
                            "analyses": [
                              {
                                "category": "rhythm"
                              }
                            ],
                            "locked": false,
                            "pending_categories": [],
                            "failed_categories": [],
                            "tags": [
                              "demo"
                            ],
                            "is_best": false,
                            "archived_at": null,
                            "last_activity": 1791333870854
                          }
                        ]
                      }
                    ],
                    "pagination": {
                      "limit": 25,
                      "cursor": "1791333870854_audio_3f9c1a7d2b60",
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "A query value is not allowed: `limit` out of range, an unsupported `sort_key` or `sort_dir`, or too many `filter_tags` (body `{ error, message }`); in view mode, an invalid `q`, `view` or `group`, or a `limit` above the view cap (standard error body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyError"
                },
                "example": {
                  "error": "invalid_limit",
                  "message": "limit must be an integer between 1 and 200"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "View mode: the saved view does not exist or is not yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "view_not_found",
                    "message": "View not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#view_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/batch": {
      "post": {
        "operationId": "run_recipe_on_library_view",
        "tags": [
          "Library"
        ],
        "summary": "Run a recipe on a set of library files",
        "description": "Runs one recipe on every library file that matches a saved view (`view_id`) or a set of `filters`, as a batch. Send exactly one of the two. Batches are available on paid accounts only; a free-account key receives 403 `batch_paid_only`.\n\nSend `dry_run: true` first: it changes nothing, charges nothing, and returns how many files matched and what the run would cost. Without `dry_run` the run starts and the call returns `202` with a `batch_id`; follow it with the batch routes. At most 500 files may match (`max_items` can lower that); a bigger match is refused with 422 `query_result_too_large` and an empty match with 422 `query_result_empty`. A real run is charged and rate limited exactly like a batch submit; see the Batch reference for the cost rule.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "tokens",
          "rule": "A dry run is free. A real run is charged per file when its run finishes, like a batch submit. Use `dry_run` to see the estimate first."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "batch_paid_only",
          "db_unavailable",
          "insufficient_balance",
          "invalid_auth_format",
          "invalid_config",
          "invalid_dry_run",
          "invalid_filter",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_max_items",
          "missing_api_key",
          "missing_auth",
          "missing_recipe_id",
          "query_result_empty",
          "query_result_too_large",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_not_found",
          "unauthorized",
          "view_not_found"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The recipe to run on every matched file."
                  },
                  "view_id": {
                    "description": "Id of one of your saved views. Send this or `filters`, not both.",
                    "type": "string"
                  },
                  "filters": {
                    "type": "object",
                    "properties": {
                      "bpm": {
                        "description": "Tempo range `{min, max}`, or `{near, tolerance}` (tolerance defaults to 3).",
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "min": {
                                "type": "number"
                              },
                              "max": {
                                "type": "number"
                              }
                            },
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "near": {
                                "type": "number"
                              },
                              "tolerance": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "near"
                            ],
                            "additionalProperties": false
                          }
                        ]
                      },
                      "tempo_stability": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "loudness_integrated": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "loudness_range": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "true_peak_dbfs": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "pitch_lowest_midi": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "pitch_highest_midi": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "notes_per_second": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "duration_seconds": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "key_label": {
                        "description": "One key name or a list, for example `A minor`.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "key_root": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "key_mode": {
                        "type": "string",
                        "enum": [
                          "major",
                          "minor"
                        ]
                      },
                      "meter": {
                        "description": "One time signature or a list, for example `4/4`.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "speech_language": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "format": {
                        "description": "File formats to keep, for example `[\"wav\", \"mp3\"]`.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "transcript_contains": {
                        "description": "Keep files whose transcript contains this text.",
                        "type": "string"
                      },
                      "sound_description": {
                        "type": "string"
                      },
                      "name_contains": {
                        "description": "Keep files whose name contains this text.",
                        "type": "string"
                      },
                      "user_tags": {
                        "description": "Tag rules: keep files with any, with all, or with none of the listed tags.",
                        "type": "object",
                        "properties": {
                          "any": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "all": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "none": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "additionalProperties": false
                      },
                      "auto_tags": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "analyzed": {
                        "description": "Keep files that have results for every listed analysis category.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "analyzed_any": {
                        "description": "Keep files that have results for at least one listed category.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "not_analyzed": {
                        "description": "True keeps only files with no analysis results.",
                        "type": "boolean"
                      },
                      "missing": {
                        "description": "Keep files that lack a value, for example `[\"bpm\"]`.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "uploaded_after": {
                        "description": "Milliseconds since the Unix epoch.",
                        "type": "number"
                      },
                      "uploaded_before": {
                        "description": "Milliseconds since the Unix epoch.",
                        "type": "number"
                      },
                      "starred": {
                        "type": "boolean"
                      },
                      "archived": {
                        "description": "Archived files: hidden (default), included, or the only ones shown.",
                        "type": "string",
                        "enum": [
                          "hide",
                          "include",
                          "only"
                        ]
                      },
                      "include_derived": {
                        "description": "True also returns files made from other files, such as stems.",
                        "type": "boolean"
                      },
                      "sounds_like": {
                        "description": "Keep files that sound like the given file.",
                        "type": "object",
                        "properties": {
                          "audio_id": {
                            "type": "string"
                          },
                          "min_score": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "audio_id"
                        ],
                        "additionalProperties": false
                      },
                      "sound_group": {
                        "description": "Keep the files of one sound group from a grouping job.",
                        "type": "object",
                        "properties": {
                          "job_id": {
                            "type": "string"
                          },
                          "group_id": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "job_id",
                          "group_id"
                        ],
                        "additionalProperties": false
                      },
                      "trash": {
                        "description": "Trashed files: hidden (default), included, or the only ones shown.",
                        "type": "string",
                        "enum": [
                          "hide",
                          "include",
                          "only"
                        ]
                      },
                      "duplicates": {
                        "description": "True keeps only files that have an identical copy.",
                        "type": "boolean"
                      },
                      "artist": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "project": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "album": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "title_contains": {
                        "type": "string"
                      },
                      "credits_contains": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "Which files to keep. Every field you send narrows the result; an empty object keeps every file. An unknown field is refused with 400 `invalid_filter`."
                  },
                  "max_items": {
                    "description": "Refuse the run when more files than this match. 1 to 500; defaults to 500.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 500
                  },
                  "dry_run": {
                    "description": "True returns the estimate and starts nothing. Defaults to false.",
                    "type": "boolean"
                  },
                  "name": {
                    "description": "A label for the batch (real runs only).",
                    "type": "string"
                  },
                  "webhook_url": {
                    "description": "Where to POST the `batch_completed` event (real runs only). At most 4096 bytes.",
                    "type": "string"
                  },
                  "metadata": {
                    "description": "Free-form JSON kept with the batch (real runs only), at most 8192 bytes when serialized.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "recipe_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe_id": "rec_1005_cat_spectral",
                "filters": {
                  "analyzed": [
                    "rhythm"
                  ],
                  "name_contains": "demo"
                },
                "max_items": 20,
                "dry_run": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Dry run: the estimate. Nothing was started.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "matched_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files the view or filters matched."
                        },
                        "recipe_id": {
                          "type": "string"
                        },
                        "total_cost": {
                          "type": "number",
                          "description": "Tokens the run would cost."
                        },
                        "total_duration_seconds": {
                          "type": "number",
                          "description": "Audio length the estimate covers, in seconds."
                        },
                        "unknown_duration_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files whose length could not be read; they add nothing to `total_cost`."
                        },
                        "approximate": {
                          "type": "boolean",
                          "description": "True when some lengths were reported by the uploader or unknown, so the real charge can differ."
                        },
                        "per_file": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "audio_id": {
                                "type": "string"
                              },
                              "audio_url": {
                                "type": "string"
                              },
                              "duration_seconds": {
                                "description": "Length of the file, or null when it could not be read.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "cost": {
                                "type": "number",
                                "description": "Tokens this file would cost."
                              }
                            },
                            "required": [
                              "audio_id",
                              "audio_url",
                              "duration_seconds",
                              "cost"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "matched_count",
                        "recipe_id",
                        "total_cost",
                        "total_duration_seconds",
                        "unknown_duration_count",
                        "approximate",
                        "per_file"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "matched_count": 2,
                    "recipe_id": "rec_1005_cat_spectral",
                    "total_cost": 40,
                    "total_duration_seconds": 7.2,
                    "unknown_duration_count": 0,
                    "approximate": false,
                    "per_file": [
                      {
                        "audio_id": "audio_3f9c1a7d2b60",
                        "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav",
                        "duration_seconds": 4,
                        "cost": 20
                      },
                      {
                        "audio_id": "audio_a81e5c40d7f2",
                        "audio_url": "https://api.scarleta.ai/v1/audio/media/2c4e6a80-1b3d-4f57-8a9c-0e1d2c3b4a59.wav",
                        "duration_seconds": 3.2,
                        "cost": 20
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "202": {
            "description": "Accepted. The batch is queued.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "batch_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the new batch."
                        },
                        "matched_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files the batch will process."
                        },
                        "status": {
                          "type": "string",
                          "description": "`IN_QUEUE` when accepted."
                        }
                      },
                      "required": [
                        "batch_id",
                        "matched_count",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        },
                        "idempotent": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                    "matched_count": 2,
                    "status": "IN_QUEUE"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not a JSON object, has an unknown field, lacks `recipe_id`, names both or neither of `view_id` and `filters`, or a value such as `max_items` or `dry_run` is not valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_config",
                    "message": "Provide exactly one of view_id or filters",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_config"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "402": {
            "description": "A real run needs a token balance or auto-recharge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "insufficient_balance",
                    "message": "Your team has no token balance and auto-recharge is not active. Top up to submit batches.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#insufficient_balance"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key belongs to a free account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_paid_only",
                    "message": "Batch processing is available on paid plans only.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_paid_only"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The saved view or the recipe does not exist or is not visible to your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "view_not_found",
                    "message": "View not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#view_not_found"
                  }
                }
              }
            }
          },
          "422": {
            "description": "No file matches, or more than `max_items` files match. `error.details.matched_count` says how many matched.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "query_result_empty",
                    "message": "No files in this view.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#query_result_empty"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/builtin-counts": {
      "get": {
        "operationId": "get_library_counts",
        "tags": [
          "Library"
        ],
        "summary": "Count files in the standard views",
        "description": "Returns one count per standard library view: everything, recently added, starred, not yet analyzed, duplicates and trash. Use it for a quick header without paging through the library. Only your own files are ever returned.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "all": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files in the library, not counting trash and archive."
                        },
                        "recent_30d": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files added recently; the key name states the window."
                        },
                        "starred": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Starred files."
                        },
                        "not_analyzed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files with no analysis results yet."
                        },
                        "duplicates": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files that have an identical copy."
                        },
                        "trash": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files in the trash."
                        },
                        "library_files_total": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Every file in your library, including archived and derived ones, but not files in the trash."
                        },
                        "unverified_hash_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files whose content fingerprint has not been checked yet."
                        }
                      },
                      "required": [
                        "all",
                        "recent_30d",
                        "starred",
                        "not_analyzed",
                        "duplicates",
                        "trash",
                        "library_files_total",
                        "unverified_hash_count"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "all": 42,
                    "recent_30d": 7,
                    "starred": 3,
                    "not_analyzed": 11,
                    "duplicates": 2,
                    "trash": 1,
                    "library_files_total": 50,
                    "unverified_hash_count": 0
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/cluster": {
      "post": {
        "operationId": "start_sound_grouping",
        "tags": [
          "Sound grouping"
        ],
        "summary": "Group your files by how they sound",
        "description": "Starts a job that sorts your files into groups that sound alike. The answer is 202 at once with the job in state `queued`; read the job (or the latest completed one) until its `status` is `completed`, then use `clusters`. `n_clusters` is a whole number from 2 to 20 (default 8); `filters` narrows which files are grouped (same filters as the library query; default all files); `embedding_model` picks the fingerprint kind, by default the one most of the chosen files have. Only files with a sound fingerprint are grouped. Every check runs before a job is created, so a refused request leaves nothing behind: fewer fingerprinted files than groups is 422 `not_enough_files`, more than 5000 files is 422 `cluster_too_large` (add filters), and a second start while one job is queued or running is 409 `cluster_in_progress` (its `error.details.job_id` names the running job). Sound grouping is for paid accounts: a free key gets 403 `cluster_paid_only`. A job cannot be deleted; completed jobs stay readable. If grouping cannot start right now the route answers 503 `cluster_unavailable`; retry later.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge to start. Files need an embedding analysis first, which is billed when you run it."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "cluster_in_progress",
          "cluster_paid_only",
          "cluster_too_large",
          "cluster_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_config",
          "invalid_embedding_model",
          "invalid_filter",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_n_clusters",
          "missing_api_key",
          "missing_auth",
          "not_enough_files",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "n_clusters": {
                    "description": "How many groups to make, 2 to 20. Defaults to 8.",
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 20
                  },
                  "filters": {
                    "type": "object",
                    "properties": {
                      "bpm": {
                        "description": "Tempo range `{min, max}`, or `{near, tolerance}` (tolerance defaults to 3).",
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "min": {
                                "type": "number"
                              },
                              "max": {
                                "type": "number"
                              }
                            },
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "near": {
                                "type": "number"
                              },
                              "tolerance": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "near"
                            ],
                            "additionalProperties": false
                          }
                        ]
                      },
                      "tempo_stability": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "loudness_integrated": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "loudness_range": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "true_peak_dbfs": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "pitch_lowest_midi": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "pitch_highest_midi": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "notes_per_second": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "duration_seconds": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "key_label": {
                        "description": "One key name or a list, for example `A minor`.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "key_root": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "key_mode": {
                        "type": "string",
                        "enum": [
                          "major",
                          "minor"
                        ]
                      },
                      "meter": {
                        "description": "One time signature or a list, for example `4/4`.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "speech_language": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "format": {
                        "description": "File formats to keep, for example `[\"wav\", \"mp3\"]`.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "transcript_contains": {
                        "description": "Keep files whose transcript contains this text.",
                        "type": "string"
                      },
                      "sound_description": {
                        "type": "string"
                      },
                      "name_contains": {
                        "description": "Keep files whose name contains this text.",
                        "type": "string"
                      },
                      "user_tags": {
                        "description": "Tag rules: keep files with any, with all, or with none of the listed tags.",
                        "type": "object",
                        "properties": {
                          "any": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "all": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "none": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "additionalProperties": false
                      },
                      "auto_tags": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "analyzed": {
                        "description": "Keep files that have results for every listed analysis category.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "analyzed_any": {
                        "description": "Keep files that have results for at least one listed category.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "not_analyzed": {
                        "description": "True keeps only files with no analysis results.",
                        "type": "boolean"
                      },
                      "missing": {
                        "description": "Keep files that lack a value, for example `[\"bpm\"]`.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "uploaded_after": {
                        "description": "Milliseconds since the Unix epoch.",
                        "type": "number"
                      },
                      "uploaded_before": {
                        "description": "Milliseconds since the Unix epoch.",
                        "type": "number"
                      },
                      "starred": {
                        "type": "boolean"
                      },
                      "archived": {
                        "description": "Archived files: hidden (default), included, or the only ones shown.",
                        "type": "string",
                        "enum": [
                          "hide",
                          "include",
                          "only"
                        ]
                      },
                      "include_derived": {
                        "description": "True also returns files made from other files, such as stems.",
                        "type": "boolean"
                      },
                      "sounds_like": {
                        "description": "Keep files that sound like the given file.",
                        "type": "object",
                        "properties": {
                          "audio_id": {
                            "type": "string"
                          },
                          "min_score": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "audio_id"
                        ],
                        "additionalProperties": false
                      },
                      "sound_group": {
                        "description": "Keep the files of one sound group from a grouping job.",
                        "type": "object",
                        "properties": {
                          "job_id": {
                            "type": "string"
                          },
                          "group_id": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "job_id",
                          "group_id"
                        ],
                        "additionalProperties": false
                      },
                      "trash": {
                        "description": "Trashed files: hidden (default), included, or the only ones shown.",
                        "type": "string",
                        "enum": [
                          "hide",
                          "include",
                          "only"
                        ]
                      },
                      "duplicates": {
                        "description": "True keeps only files that have an identical copy.",
                        "type": "boolean"
                      },
                      "artist": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "project": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "album": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "title_contains": {
                        "type": "string"
                      },
                      "credits_contains": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "Which files to keep. Every field you send narrows the result; an empty object keeps every file. An unknown field is refused with 400 `invalid_filter`."
                  },
                  "embedding_model": {
                    "description": "Name of the fingerprint kind to compare, as returned in `embedding_model`. Defaults to the kind most chosen files have.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "n_clusters": 2,
                "filters": {
                  "name_contains": "demo"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The job is queued.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string",
                              "description": "Identifier of the new job."
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "queued"
                              ],
                              "description": "Always `queued` at this point."
                            },
                            "file_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files the job will group."
                            },
                            "embedding_model": {
                              "type": "string",
                              "description": "Name of the fingerprint kind that will be compared."
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "file_count",
                            "embedding_model"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "status": "queued",
                    "file_count": 120,
                    "embedding_model": "fingerprint-6144"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON (`invalid_json`), has an unknown field (`invalid_config`), has a bad `n_clusters` (`invalid_n_clusters`), `embedding_model` (`invalid_embedding_model`) or filter (`invalid_filter`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_n_clusters",
                    "message": "n_clusters must be an integer from 2 to 20",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_n_clusters"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key belongs to a free account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cluster_paid_only",
                    "message": "Sound grouping is available on paid plans only. Upgrade to a paid plan to group your library by sound.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cluster_paid_only"
                  }
                }
              }
            }
          },
          "409": {
            "description": "A job of yours is already queued or running.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cluster_in_progress",
                    "message": "A sound grouping is already running. Wait for it to finish.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cluster_in_progress"
                  }
                }
              }
            }
          },
          "422": {
            "description": "Too few files with a fingerprint (`not_enough_files`), or more than the limit (`cluster_too_large`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_enough_files",
                    "message": "Grouping into 2 groups needs at least 2 files with a sound fingerprint; 0 found.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_enough_files"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Grouping cannot start right now (`cluster_unavailable`), or the database is briefly unavailable (`db_unavailable`); retry shortly. A key that cannot be checked is `auth_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cluster_unavailable",
                    "message": "Sound grouping is not available right now. Please try again later.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cluster_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/cluster/{job_id}": {
      "get": {
        "operationId": "get_sound_grouping",
        "tags": [
          "Sound grouping"
        ],
        "summary": "Get a sound grouping job",
        "description": "Returns one grouping job. `clusters` is empty until `status` is `completed`. Files you deleted or trashed since the job ran are left out of every group. A job that stopped making progress is marked `failed` when you read it, with an `error` message. A job that is not yours, does not exist or whose id is not a UUID is 404 `cluster_job_not_found`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "cluster_job_not_found",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `job_id` returned when the grouping was started."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The job and its groups.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string",
                              "description": "Identifier of the grouping job."
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "queued",
                                "running",
                                "completed",
                                "failed"
                              ],
                              "description": "`queued` and `running` while the job works, then `completed` or `failed`."
                            },
                            "n_clusters": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "How many groups the job was asked for."
                            },
                            "embedding_model": {
                              "type": "string",
                              "description": "Name of the fingerprint kind the job compared."
                            },
                            "file_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files the job covers."
                            },
                            "filters": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The filters the job was started with."
                            },
                            "iterations": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Rounds the grouping needed, once it has finished; null before."
                            },
                            "error": {
                              "description": "Why a failed job failed, or null.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "created_at": {
                              "type": "number",
                              "description": "When the job was created, in milliseconds since the Unix epoch."
                            },
                            "updated_at": {
                              "type": "number",
                              "description": "When the job last changed, in milliseconds since the Unix epoch."
                            },
                            "clusters": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "cluster_id": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Number of the group inside the job. Use it as `group_id` to name the group."
                                  },
                                  "label": {
                                    "description": "Name you gave the group, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "file_count": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Files in the group that still exist."
                                  },
                                  "members": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    },
                                    "description": "`audio_id` of every file in the group, closest to the centre first."
                                  },
                                  "representative_files": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "audio_id": {
                                          "type": "string"
                                        },
                                        "name": {
                                          "type": "string",
                                          "description": "Display name of the file."
                                        }
                                      },
                                      "required": [
                                        "audio_id",
                                        "name"
                                      ],
                                      "additionalProperties": false
                                    },
                                    "description": "The files nearest the centre of the group, to show as a preview."
                                  },
                                  "centroid_audio_id": {
                                    "description": "The file nearest the centre, or null when the group is empty.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "cluster_id",
                                  "label",
                                  "file_count",
                                  "members",
                                  "representative_files",
                                  "centroid_audio_id"
                                ],
                                "additionalProperties": false
                              },
                              "description": "The groups. Empty until the job is `completed`."
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "n_clusters",
                            "embedding_model",
                            "file_count",
                            "filters",
                            "iterations",
                            "error",
                            "created_at",
                            "updated_at",
                            "clusters"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "status": "completed",
                    "n_clusters": 2,
                    "embedding_model": "fingerprint-6144",
                    "file_count": 2,
                    "filters": {},
                    "iterations": 3,
                    "error": null,
                    "created_at": 1791333870854,
                    "updated_at": 1791333874854,
                    "clusters": [
                      {
                        "cluster_id": 0,
                        "label": "Drums",
                        "file_count": 1,
                        "members": [
                          "audio_3f9c1a7d2b60"
                        ],
                        "representative_files": [
                          {
                            "audio_id": "audio_3f9c1a7d2b60",
                            "name": "demo-mix.wav"
                          }
                        ],
                        "centroid_audio_id": "audio_3f9c1a7d2b60"
                      },
                      {
                        "cluster_id": 1,
                        "label": null,
                        "file_count": 1,
                        "members": [
                          "audio_a81e5c40d7f2"
                        ],
                        "representative_files": [
                          {
                            "audio_id": "audio_a81e5c40d7f2",
                            "name": "demo-mix-2.wav"
                          }
                        ],
                        "centroid_audio_id": "audio_a81e5c40d7f2"
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No grouping job with this id exists in your account (an id that is not a UUID is the same 404).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cluster_job_not_found",
                    "message": "Sound grouping job not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cluster_job_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/cluster/{job_id}/groups/{group_id}": {
      "put": {
        "operationId": "name_sound_group",
        "tags": [
          "Sound grouping"
        ],
        "summary": "Name one group of a sound grouping",
        "description": "Sets the `label` of one group (`group_id` is the group's `cluster_id`) of a completed job. The label is 1 to 60 characters after trimming, with no control characters. The answer is the whole job. The body and label are checked first (`invalid_json`, `invalid_config` for any field other than `label`, `invalid_label`), then the job (a job that is not yours, does not exist or whose id is not a uuid is 404 `cluster_job_not_found`.), then the group id and the job state, in this order: a `group_id` that is not a whole number is 404 `cluster_group_not_found`, a job that has not completed is 409 `cluster_job_not_ready`, and a number the job has no group for is 404 `cluster_group_not_found`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "cluster_group_not_found",
          "cluster_job_not_found",
          "cluster_job_not_ready",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_config",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_label",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `job_id` returned when the grouping was started."
            }
          },
          {
            "name": "group_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The group's `cluster_id`, a whole number."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60,
                    "description": "The new name, 1 to 60 characters; spaces around it are removed first, so the schema limit applies to the trimmed text."
                  }
                },
                "required": [
                  "label"
                ],
                "additionalProperties": false
              },
              "example": {
                "label": "Drums"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The job with the new label.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string",
                              "description": "Identifier of the grouping job."
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "queued",
                                "running",
                                "completed",
                                "failed"
                              ],
                              "description": "`queued` and `running` while the job works, then `completed` or `failed`."
                            },
                            "n_clusters": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "How many groups the job was asked for."
                            },
                            "embedding_model": {
                              "type": "string",
                              "description": "Name of the fingerprint kind the job compared."
                            },
                            "file_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files the job covers."
                            },
                            "filters": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The filters the job was started with."
                            },
                            "iterations": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Rounds the grouping needed, once it has finished; null before."
                            },
                            "error": {
                              "description": "Why a failed job failed, or null.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "created_at": {
                              "type": "number",
                              "description": "When the job was created, in milliseconds since the Unix epoch."
                            },
                            "updated_at": {
                              "type": "number",
                              "description": "When the job last changed, in milliseconds since the Unix epoch."
                            },
                            "clusters": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "cluster_id": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Number of the group inside the job. Use it as `group_id` to name the group."
                                  },
                                  "label": {
                                    "description": "Name you gave the group, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "file_count": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Files in the group that still exist."
                                  },
                                  "members": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    },
                                    "description": "`audio_id` of every file in the group, closest to the centre first."
                                  },
                                  "representative_files": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "audio_id": {
                                          "type": "string"
                                        },
                                        "name": {
                                          "type": "string",
                                          "description": "Display name of the file."
                                        }
                                      },
                                      "required": [
                                        "audio_id",
                                        "name"
                                      ],
                                      "additionalProperties": false
                                    },
                                    "description": "The files nearest the centre of the group, to show as a preview."
                                  },
                                  "centroid_audio_id": {
                                    "description": "The file nearest the centre, or null when the group is empty.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "cluster_id",
                                  "label",
                                  "file_count",
                                  "members",
                                  "representative_files",
                                  "centroid_audio_id"
                                ],
                                "additionalProperties": false
                              },
                              "description": "The groups. Empty until the job is `completed`."
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "n_clusters",
                            "embedding_model",
                            "file_count",
                            "filters",
                            "iterations",
                            "error",
                            "created_at",
                            "updated_at",
                            "clusters"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "status": "completed",
                    "n_clusters": 2,
                    "embedding_model": "fingerprint-6144",
                    "file_count": 2,
                    "filters": {},
                    "iterations": 3,
                    "error": null,
                    "created_at": 1791333870854,
                    "updated_at": 1791333874854,
                    "clusters": [
                      {
                        "cluster_id": 0,
                        "label": "Drums",
                        "file_count": 1,
                        "members": [
                          "audio_3f9c1a7d2b60"
                        ],
                        "representative_files": [
                          {
                            "audio_id": "audio_3f9c1a7d2b60",
                            "name": "demo-mix.wav"
                          }
                        ],
                        "centroid_audio_id": "audio_3f9c1a7d2b60"
                      },
                      {
                        "cluster_id": 1,
                        "label": null,
                        "file_count": 1,
                        "members": [
                          "audio_a81e5c40d7f2"
                        ],
                        "representative_files": [
                          {
                            "audio_id": "audio_a81e5c40d7f2",
                            "name": "demo-mix-2.wav"
                          }
                        ],
                        "centroid_audio_id": "audio_a81e5c40d7f2"
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON (`invalid_json`), has a field other than `label` (`invalid_config`), or the label is empty, too long or has control characters (`invalid_label`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_label",
                    "message": "label must be 1 to 60 characters",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_label"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The job does not exist (`cluster_job_not_found`) or has no such group (`cluster_group_not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cluster_group_not_found",
                    "message": "Sound group not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cluster_group_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The job is still queued or running, or failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cluster_job_not_ready",
                    "message": "This grouping job has not finished yet.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cluster_job_not_ready"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/cluster/latest": {
      "get": {
        "operationId": "get_latest_sound_grouping",
        "tags": [
          "Sound grouping"
        ],
        "summary": "Get your latest finished sound grouping",
        "description": "Returns your most recent completed grouping job with its groups. Send `embedding_model` to get the latest one of one fingerprint kind. When you have no completed job the answer is 404 `cluster_job_not_found`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "cluster_job_not_found",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "embedding_model",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Only consider jobs of this fingerprint kind.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The latest completed job.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string",
                              "description": "Identifier of the grouping job."
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "queued",
                                "running",
                                "completed",
                                "failed"
                              ],
                              "description": "`queued` and `running` while the job works, then `completed` or `failed`."
                            },
                            "n_clusters": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "How many groups the job was asked for."
                            },
                            "embedding_model": {
                              "type": "string",
                              "description": "Name of the fingerprint kind the job compared."
                            },
                            "file_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files the job covers."
                            },
                            "filters": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The filters the job was started with."
                            },
                            "iterations": {
                              "anyOf": [
                                {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "Rounds the grouping needed, once it has finished; null before."
                            },
                            "error": {
                              "description": "Why a failed job failed, or null.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "created_at": {
                              "type": "number",
                              "description": "When the job was created, in milliseconds since the Unix epoch."
                            },
                            "updated_at": {
                              "type": "number",
                              "description": "When the job last changed, in milliseconds since the Unix epoch."
                            },
                            "clusters": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "cluster_id": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Number of the group inside the job. Use it as `group_id` to name the group."
                                  },
                                  "label": {
                                    "description": "Name you gave the group, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "file_count": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Files in the group that still exist."
                                  },
                                  "members": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    },
                                    "description": "`audio_id` of every file in the group, closest to the centre first."
                                  },
                                  "representative_files": {
                                    "type": "array",
                                    "items": {
                                      "type": "object",
                                      "properties": {
                                        "audio_id": {
                                          "type": "string"
                                        },
                                        "name": {
                                          "type": "string",
                                          "description": "Display name of the file."
                                        }
                                      },
                                      "required": [
                                        "audio_id",
                                        "name"
                                      ],
                                      "additionalProperties": false
                                    },
                                    "description": "The files nearest the centre of the group, to show as a preview."
                                  },
                                  "centroid_audio_id": {
                                    "description": "The file nearest the centre, or null when the group is empty.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "cluster_id",
                                  "label",
                                  "file_count",
                                  "members",
                                  "representative_files",
                                  "centroid_audio_id"
                                ],
                                "additionalProperties": false
                              },
                              "description": "The groups. Empty until the job is `completed`."
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "n_clusters",
                            "embedding_model",
                            "file_count",
                            "filters",
                            "iterations",
                            "error",
                            "created_at",
                            "updated_at",
                            "clusters"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "status": "completed",
                    "n_clusters": 2,
                    "embedding_model": "fingerprint-6144",
                    "file_count": 2,
                    "filters": {},
                    "iterations": 3,
                    "error": null,
                    "created_at": 1791333870854,
                    "updated_at": 1791333874854,
                    "clusters": [
                      {
                        "cluster_id": 0,
                        "label": "Drums",
                        "file_count": 1,
                        "members": [
                          "audio_3f9c1a7d2b60"
                        ],
                        "representative_files": [
                          {
                            "audio_id": "audio_3f9c1a7d2b60",
                            "name": "demo-mix.wav"
                          }
                        ],
                        "centroid_audio_id": "audio_3f9c1a7d2b60"
                      },
                      {
                        "cluster_id": 1,
                        "label": null,
                        "file_count": 1,
                        "members": [
                          "audio_a81e5c40d7f2"
                        ],
                        "representative_files": [
                          {
                            "audio_id": "audio_a81e5c40d7f2",
                            "name": "demo-mix-2.wav"
                          }
                        ],
                        "centroid_audio_id": "audio_a81e5c40d7f2"
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No grouping job with this id exists in your account (an id that is not a UUID is the same 404).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "cluster_job_not_found",
                    "message": "Sound grouping job not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#cluster_job_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/overview": {
      "get": {
        "operationId": "get_library_overview",
        "tags": [
          "Library"
        ],
        "summary": "Get a library overview",
        "description": "Summarises the whole library in one call: file and track counts, how many files each analysis category covers, your most used tags, your saved views, and when sound groups were last built. Only your own files are ever returned.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "file_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files in the library."
                        },
                        "track_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Tracks in the library; versions of one song count once."
                        },
                        "analyzed_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files with at least one analysis result."
                        },
                        "analyzed_by_category": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "description": "Number of files with a result in each analysis category."
                        },
                        "tags": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "tag": {
                                "type": "string"
                              },
                              "count": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            "required": [
                              "tag",
                              "count"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Your most used tags."
                        },
                        "saved_views": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                                "description": "Saved view id."
                              },
                              "name": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "sound_groups": {
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "count": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "Groups found."
                                },
                                "built_at": {
                                  "type": "number",
                                  "description": "When the grouping finished, in milliseconds since the Unix epoch."
                                }
                              },
                              "required": [
                                "count",
                                "built_at"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The latest sound grouping, or null when you never built one."
                        }
                      },
                      "required": [
                        "file_count",
                        "track_count",
                        "analyzed_count",
                        "analyzed_by_category",
                        "tags",
                        "saved_views",
                        "sound_groups"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "file_count": 42,
                    "track_count": 40,
                    "analyzed_count": 31,
                    "analyzed_by_category": {
                      "rhythm": 22,
                      "spectral": 18
                    },
                    "tags": [
                      {
                        "tag": "demo",
                        "count": 5
                      }
                    ],
                    "saved_views": [
                      {
                        "id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                        "name": "Slow tracks"
                      }
                    ],
                    "sound_groups": null
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/query": {
      "post": {
        "operationId": "query_library",
        "tags": [
          "Library"
        ],
        "summary": "Query the library",
        "description": "Finds files by what the analyses found in them: tempo, key, loudness, tags, names, upload time and more. Send `filters`, optionally `sort` and `limit`, and read the matches from `items`. Only your own files are ever returned.\n\n`limit` is 50 unless you send it, and at most 100. While `has_more` is true, send `next_cursor` back as `cursor` with the same filters and sort to get the next page. `total_matches` counts every match; `coverage` shows how many files have each searchable value, so you can tell \"no match\" from \"not analyzed yet\". Reading does not spend tokens.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "audio_not_found",
          "auth_unavailable",
          "cluster_job_not_found",
          "db_unavailable",
          "embedding_missing",
          "invalid_auth_format",
          "invalid_config",
          "invalid_cursor",
          "invalid_filter",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_limit",
          "invalid_sort",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filters": {
                    "type": "object",
                    "properties": {
                      "bpm": {
                        "description": "Tempo range `{min, max}`, or `{near, tolerance}` (tolerance defaults to 3).",
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "min": {
                                "type": "number"
                              },
                              "max": {
                                "type": "number"
                              }
                            },
                            "additionalProperties": false
                          },
                          {
                            "type": "object",
                            "properties": {
                              "near": {
                                "type": "number"
                              },
                              "tolerance": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "near"
                            ],
                            "additionalProperties": false
                          }
                        ]
                      },
                      "tempo_stability": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "loudness_integrated": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "loudness_range": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "true_peak_dbfs": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "pitch_lowest_midi": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "pitch_highest_midi": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "notes_per_second": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "duration_seconds": {
                        "type": "object",
                        "properties": {
                          "min": {
                            "type": "number"
                          },
                          "max": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": false
                      },
                      "key_label": {
                        "description": "One key name or a list, for example `A minor`.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "key_root": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "key_mode": {
                        "type": "string",
                        "enum": [
                          "major",
                          "minor"
                        ]
                      },
                      "meter": {
                        "description": "One time signature or a list, for example `4/4`.",
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "speech_language": {
                        "anyOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        ]
                      },
                      "format": {
                        "description": "File formats to keep, for example `[\"wav\", \"mp3\"]`.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "transcript_contains": {
                        "description": "Keep files whose transcript contains this text.",
                        "type": "string"
                      },
                      "sound_description": {
                        "type": "string"
                      },
                      "name_contains": {
                        "description": "Keep files whose name contains this text.",
                        "type": "string"
                      },
                      "user_tags": {
                        "description": "Tag rules: keep files with any, with all, or with none of the listed tags.",
                        "type": "object",
                        "properties": {
                          "any": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "all": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "none": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "additionalProperties": false
                      },
                      "auto_tags": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "analyzed": {
                        "description": "Keep files that have results for every listed analysis category.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "analyzed_any": {
                        "description": "Keep files that have results for at least one listed category.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "not_analyzed": {
                        "description": "True keeps only files with no analysis results.",
                        "type": "boolean"
                      },
                      "missing": {
                        "description": "Keep files that lack a value, for example `[\"bpm\"]`.",
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "uploaded_after": {
                        "description": "Milliseconds since the Unix epoch.",
                        "type": "number"
                      },
                      "uploaded_before": {
                        "description": "Milliseconds since the Unix epoch.",
                        "type": "number"
                      },
                      "starred": {
                        "type": "boolean"
                      },
                      "archived": {
                        "description": "Archived files: hidden (default), included, or the only ones shown.",
                        "type": "string",
                        "enum": [
                          "hide",
                          "include",
                          "only"
                        ]
                      },
                      "include_derived": {
                        "description": "True also returns files made from other files, such as stems.",
                        "type": "boolean"
                      },
                      "sounds_like": {
                        "description": "Keep files that sound like the given file.",
                        "type": "object",
                        "properties": {
                          "audio_id": {
                            "type": "string"
                          },
                          "min_score": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "audio_id"
                        ],
                        "additionalProperties": false
                      },
                      "sound_group": {
                        "description": "Keep the files of one sound group from a grouping job.",
                        "type": "object",
                        "properties": {
                          "job_id": {
                            "type": "string"
                          },
                          "group_id": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          }
                        },
                        "required": [
                          "job_id",
                          "group_id"
                        ],
                        "additionalProperties": false
                      },
                      "trash": {
                        "description": "Trashed files: hidden (default), included, or the only ones shown.",
                        "type": "string",
                        "enum": [
                          "hide",
                          "include",
                          "only"
                        ]
                      },
                      "duplicates": {
                        "description": "True keeps only files that have an identical copy.",
                        "type": "boolean"
                      },
                      "artist": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "project": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "album": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "title_contains": {
                        "type": "string"
                      },
                      "credits_contains": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": false,
                    "description": "Which files to keep. Every field you send narrows the result; an empty object keeps every file. An unknown field is refused with 400 `invalid_filter`."
                  },
                  "sort": {
                    "description": "Either one of the short names (`uploaded_at_desc`, `bpm_asc`, ...) or a list of `{ key, dir }`. Defaults to newest first.",
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "uploaded_at_desc",
                          "uploaded_at_asc",
                          "bpm_asc",
                          "bpm_desc",
                          "loudness_asc",
                          "loudness_desc",
                          "name_asc"
                        ]
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "key": {
                              "type": "string",
                              "description": "For example `uploaded`, `name`, `bpm`, `duration`, `size`."
                            },
                            "dir": {
                              "type": "string",
                              "enum": [
                                "asc",
                                "desc"
                              ]
                            }
                          },
                          "required": [
                            "key",
                            "dir"
                          ],
                          "additionalProperties": false
                        }
                      }
                    ]
                  },
                  "limit": {
                    "description": "Matches per page, 1 to 100. Defaults to 50.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "cursor": {
                    "description": "The `next_cursor` of the previous page.",
                    "type": "string"
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "filters": {
                  "bpm": {
                    "min": 90,
                    "max": 130
                  },
                  "analyzed": [
                    "rhythm"
                  ]
                },
                "sort": [
                  {
                    "key": "uploaded",
                    "dir": "desc"
                  }
                ],
                "limit": 25
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "audio_id": {
                                "type": "string"
                              },
                              "original_filename": {
                                "type": "string"
                              },
                              "display_name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "audio_url": {
                                "type": "string",
                                "description": "URL to pass as `audio_url` when running an analysis on this file."
                              },
                              "playback_url": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "duration_seconds": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "format": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "uploaded_at": {
                                "type": "number",
                                "description": "Milliseconds since the Unix epoch."
                              },
                              "starred": {
                                "type": "boolean"
                              },
                              "user_tags": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "analyzed_categories": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "Analysis categories this file has results for."
                              },
                              "bpm": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "tempo_stability": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "key_label": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "key_root": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "key_mode": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "meter": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "loudness_integrated": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "loudness_range": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "true_peak_dbfs": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "pitch_lowest_midi": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "pitch_highest_midi": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "notes_per_second": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "speech_language": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "transcript_text": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "sound_description": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "auto_tags": {
                                "anyOf": [
                                  {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    }
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "bpm_source": {
                                "description": "Where the tempo came from: your own value or the analysis.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "key_source": {
                                "description": "Where the key came from: your own value or the analysis.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "details": {
                                "type": "object",
                                "properties": {
                                  "title": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "artist": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "album": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "project": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "credits": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "has_cover": {
                                    "type": "boolean",
                                    "description": "True when the file has cover art."
                                  },
                                  "content_sha256": {
                                    "description": "Fingerprint of the file content; equal values mean identical files.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "trashed_at": {
                                    "description": "When the file was moved to the trash, in milliseconds since the Unix epoch, or null.",
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "purge_at": {
                                    "description": "When a trashed file is removed for good, or null.",
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  }
                                },
                                "required": [
                                  "title",
                                  "artist",
                                  "album",
                                  "project",
                                  "credits",
                                  "has_cover",
                                  "content_sha256",
                                  "trashed_at",
                                  "purge_at"
                                ],
                                "additionalProperties": false
                              },
                              "similarity": {
                                "description": "Similarity to the `sounds_like` reference. Present only when the query uses `sounds_like`.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "audio_id",
                              "original_filename",
                              "display_name",
                              "audio_url",
                              "playback_url",
                              "duration_seconds",
                              "format",
                              "uploaded_at",
                              "starred",
                              "user_tags",
                              "analyzed_categories",
                              "bpm",
                              "tempo_stability",
                              "key_label",
                              "key_root",
                              "key_mode",
                              "meter",
                              "loudness_integrated",
                              "loudness_range",
                              "true_peak_dbfs",
                              "pitch_lowest_midi",
                              "pitch_highest_midi",
                              "notes_per_second",
                              "speech_language",
                              "transcript_text",
                              "sound_description",
                              "auto_tags",
                              "bpm_source",
                              "key_source",
                              "details"
                            ],
                            "additionalProperties": false
                          },
                          "description": "The matching files."
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Number of items in this page."
                        },
                        "total_matches": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Number of files that match the filters."
                        },
                        "has_more": {
                          "type": "boolean"
                        },
                        "next_cursor": {
                          "description": "Pass this as `cursor` to get the next page.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "coverage": {
                          "type": "object",
                          "properties": {
                            "total_library_size": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files in scope before any value filter."
                            },
                            "indexed": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "description": "For each searchable value (`bpm`, `key_label`, ...), how many files in scope have it."
                            }
                          },
                          "required": [
                            "total_library_size",
                            "indexed"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "items",
                        "count",
                        "total_matches",
                        "has_more",
                        "next_cursor",
                        "coverage"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "items": [
                      {
                        "audio_id": "audio_3f9c1a7d2b60",
                        "original_filename": "demo-mix.wav",
                        "display_name": "Demo mix",
                        "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav",
                        "playback_url": null,
                        "duration_seconds": 184.2,
                        "format": "wav",
                        "uploaded_at": 1791333870854,
                        "starred": false,
                        "user_tags": [
                          "demo"
                        ],
                        "analyzed_categories": [
                          "rhythm"
                        ],
                        "bpm": 118.5,
                        "tempo_stability": null,
                        "key_label": null,
                        "key_root": null,
                        "key_mode": null,
                        "meter": null,
                        "loudness_integrated": null,
                        "loudness_range": null,
                        "true_peak_dbfs": null,
                        "pitch_lowest_midi": null,
                        "pitch_highest_midi": null,
                        "notes_per_second": null,
                        "speech_language": null,
                        "transcript_text": null,
                        "sound_description": null,
                        "auto_tags": null,
                        "bpm_source": "analysis",
                        "key_source": null,
                        "details": {
                          "title": null,
                          "artist": null,
                          "album": null,
                          "project": null,
                          "credits": null,
                          "has_cover": false,
                          "content_sha256": null,
                          "trashed_at": null,
                          "purge_at": null
                        }
                      }
                    ],
                    "count": 1,
                    "total_matches": 1,
                    "has_more": false,
                    "next_cursor": null,
                    "coverage": {
                      "total_library_size": 42,
                      "indexed": {
                        "bpm": 17,
                        "key_label": 9,
                        "meter": 12
                      }
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not a JSON object, has an unknown field, or a filter, sort, `limit` or `cursor` is not valid. `error.details.field` names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_filter",
                    "message": "Unknown filter \"colour\"",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_filter"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "A `sounds_like` reference file does not exist in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "audio_not_found",
                    "message": "Audio file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#audio_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The `sounds_like` reference file has no sound fingerprint yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "embedding_missing",
                    "message": "Run embedding analysis on this file first.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#embedding_missing"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/similar": {
      "post": {
        "operationId": "search_similar_files",
        "tags": [
          "Similar sounds"
        ],
        "summary": "Find files that sound like a file or a link",
        "description": "Same search as the GET route, with the reference given in the body: send exactly one of `audio_id` or `reference_url` (the address of one of your files, as in an `audio_url`). The reference file needs a sound fingerprint (the embedding analysis). A file you own without one is 409 `embedding_missing`; a file that does not exist or is not yours is 404 `audio_not_found`. A `reference_url` that is not one of your files is 404 `audio_not_found`. `limit` is a whole number from 1 to 100 (default 20); `min_score` is a number from -1 to 1 (default -1, which keeps everything). The search compares only your own files and is exact, so on a large library it can take a moment. Any field the route does not know is 400 `invalid_config`; neither or both references is 400 `invalid_reference`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. The embedding analysis that creates a fingerprint is billed when you run it."
        },
        "x-scarleta-error-codes": [
          "audio_not_found",
          "auth_unavailable",
          "db_unavailable",
          "embedding_missing",
          "invalid_auth_format",
          "invalid_config",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_limit",
          "invalid_min_score",
          "invalid_reference",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_id": {
                    "description": "The `audio_id` or file id of the reference file. Send this or `reference_url`.",
                    "type": "string"
                  },
                  "reference_url": {
                    "description": "The address of the reference file in your library. Send this or `audio_id`.",
                    "type": "string"
                  },
                  "limit": {
                    "description": "How many results to return, 1 to 100. Defaults to 20.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "min_score": {
                    "description": "Leave out files scoring below this, -1 to 1. Defaults to -1.",
                    "type": "number",
                    "minimum": -1,
                    "maximum": 1
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "audio_id": "audio_3f9c1a7d2b60",
                "limit": 10,
                "min_score": 0.5
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The closest files, best first.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "reference_audio_id": {
                              "type": "string",
                              "description": "The file the search compared against."
                            },
                            "embedding_model": {
                              "type": "string",
                              "description": "Name of the fingerprint kind that was compared. Only files with a fingerprint of the same kind can match."
                            },
                            "results": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "audio_id": {
                                    "type": "string",
                                    "description": "Registry identifier of the similar file; it starts with `audio_`."
                                  },
                                  "original_filename": {
                                    "type": "string",
                                    "description": "Name the file was uploaded under."
                                  },
                                  "display_name": {
                                    "description": "Name you gave the file, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "similarity_score": {
                                    "type": "number",
                                    "description": "How alike the sound is, from -1 to 1, to four decimals. Higher is closer."
                                  },
                                  "bpm": {
                                    "description": "Tempo of the file, or null when it has none.",
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "key_label": {
                                    "description": "Musical key of the file, for example `A minor`, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "analyzed_categories": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    },
                                    "description": "Analysis categories this file has results for."
                                  }
                                },
                                "required": [
                                  "audio_id",
                                  "original_filename",
                                  "display_name",
                                  "similarity_score",
                                  "bpm",
                                  "key_label",
                                  "analyzed_categories"
                                ],
                                "additionalProperties": false
                              },
                              "description": "Your most similar files, best first. The reference itself is never listed."
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Entries in `results`."
                            },
                            "note": {
                              "type": "string",
                              "description": "A fixed sentence on what similarity means."
                            }
                          },
                          "required": [
                            "reference_audio_id",
                            "embedding_model",
                            "results",
                            "count",
                            "note"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "reference_audio_id": "audio_3f9c1a7d2b60",
                    "embedding_model": "fingerprint-6144",
                    "results": [
                      {
                        "audio_id": "audio_a81e5c40d7f2",
                        "original_filename": "demo-mix-2.wav",
                        "display_name": null,
                        "similarity_score": 0.9312,
                        "bpm": 119.8,
                        "key_label": "A minor",
                        "analyzed_categories": [
                          "rhythm",
                          "embedding"
                        ]
                      }
                    ],
                    "count": 1,
                    "note": "Similarity is acoustic character (timbre/texture), not structural or temporal match."
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON (`invalid_json`), has an unknown field (`invalid_config`), does not name exactly one reference (`invalid_reference`), or `limit` / `min_score` is not allowed (`invalid_limit`, `invalid_min_score`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_reference",
                    "message": "Give exactly one of audio_id or reference_url",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_reference"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The reference file does not exist in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "audio_not_found",
                    "message": "Audio file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#audio_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The reference file has no sound fingerprint yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "embedding_missing",
                    "message": "Run embedding analysis on this file first.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#embedding_missing"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/similar/{audio_id}": {
      "get": {
        "operationId": "find_similar_files",
        "tags": [
          "Similar sounds"
        ],
        "summary": "Find files that sound like one of yours",
        "description": "Returns the files in your library whose sound is closest to the file named in the path (`audio_id` or the file id). The reference file needs a sound fingerprint (the embedding analysis). A file you own without one is 409 `embedding_missing`; a file that does not exist or is not yours is 404 `audio_not_found`. `limit` is a whole number from 1 to 100 (default 20); `min_score` is a number from -1 to 1 (default -1, which keeps everything). The search compares only your own files and is exact, so on a large library it can take a moment. A bad `limit` is 400 `invalid_limit`, a bad `min_score` 400 `invalid_min_score`. If the database is briefly unavailable the route answers 503 `db_unavailable`; retry after a short wait.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. The embedding analysis that creates a fingerprint is billed when you run it."
        },
        "x-scarleta-error-codes": [
          "audio_not_found",
          "auth_unavailable",
          "db_unavailable",
          "embedding_missing",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_limit",
          "invalid_min_score",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "audio_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `audio_id` or file id of the reference file."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "How many results to return, 1 to 100. Defaults to 20.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "min_score",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Leave out files scoring below this, -1 to 1. Defaults to -1.",
              "type": "number",
              "minimum": -1,
              "maximum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The closest files, best first. The list is empty when no other file has a fingerprint of the same kind.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "reference_audio_id": {
                              "type": "string",
                              "description": "The file the search compared against."
                            },
                            "embedding_model": {
                              "type": "string",
                              "description": "Name of the fingerprint kind that was compared. Only files with a fingerprint of the same kind can match."
                            },
                            "results": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "audio_id": {
                                    "type": "string",
                                    "description": "Registry identifier of the similar file; it starts with `audio_`."
                                  },
                                  "original_filename": {
                                    "type": "string",
                                    "description": "Name the file was uploaded under."
                                  },
                                  "display_name": {
                                    "description": "Name you gave the file, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "similarity_score": {
                                    "type": "number",
                                    "description": "How alike the sound is, from -1 to 1, to four decimals. Higher is closer."
                                  },
                                  "bpm": {
                                    "description": "Tempo of the file, or null when it has none.",
                                    "type": [
                                      "number",
                                      "null"
                                    ]
                                  },
                                  "key_label": {
                                    "description": "Musical key of the file, for example `A minor`, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "analyzed_categories": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    },
                                    "description": "Analysis categories this file has results for."
                                  }
                                },
                                "required": [
                                  "audio_id",
                                  "original_filename",
                                  "display_name",
                                  "similarity_score",
                                  "bpm",
                                  "key_label",
                                  "analyzed_categories"
                                ],
                                "additionalProperties": false
                              },
                              "description": "Your most similar files, best first. The reference itself is never listed."
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Entries in `results`."
                            },
                            "note": {
                              "type": "string",
                              "description": "A fixed sentence on what similarity means."
                            }
                          },
                          "required": [
                            "reference_audio_id",
                            "embedding_model",
                            "results",
                            "count",
                            "note"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "reference_audio_id": "audio_3f9c1a7d2b60",
                    "embedding_model": "fingerprint-6144",
                    "results": [
                      {
                        "audio_id": "audio_a81e5c40d7f2",
                        "original_filename": "demo-mix-2.wav",
                        "display_name": null,
                        "similarity_score": 0.9312,
                        "bpm": 119.8,
                        "key_label": "A minor",
                        "analyzed_categories": [
                          "rhythm",
                          "embedding"
                        ]
                      }
                    ],
                    "count": 1,
                    "note": "Similarity is acoustic character (timbre/texture), not structural or temporal match."
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` or `min_score` is not allowed (`invalid_limit`, `invalid_min_score`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_limit",
                    "message": "limit must be an integer from 1 to 100",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_limit"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The reference file does not exist in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "audio_not_found",
                    "message": "Audio file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#audio_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The reference file has no sound fingerprint yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "embedding_missing",
                    "message": "Run embedding analysis on this file first.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#embedding_missing"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/library/view-counts": {
      "get": {
        "operationId": "get_saved_view_counts",
        "tags": [
          "Library"
        ],
        "summary": "Count tracks in each saved view",
        "description": "Returns an object that maps the id of each of your saved views to the number of tracks it currently matches. The object is empty when you have no saved views. Only your own files are ever returned.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string",
                        "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                        "description": "Saved view id."
                      },
                      "additionalProperties": {
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991,
                        "description": "Tracks the view matches."
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52": 12
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/rename": {
      "post": {
        "operationId": "rename_file",
        "tags": [
          "File actions"
        ],
        "summary": "Rename a file",
        "description": "Sets the display name of one of your files (at most 200 characters, surrounding spaces removed). The stored audio is not touched. `audio_id` may be the library identifier or the storage `file_id`; the response returns the `audio_id`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_name",
          "missing_api_key",
          "missing_audio_id",
          "missing_auth",
          "missing_name",
          "name_too_long",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Library identifier (`audio_id`) or storage identifier (`file_id`) of the file."
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The new name, 1 to 200 characters after trimming."
                  }
                },
                "required": [
                  "audio_id",
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_id": "audio_bbb14949dc19",
                "name": "Morning session v2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The file was renamed. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "audio_id",
                        "name"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_id": "audio_bbb14949dc19",
                    "name": "Morning session v2"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, `audio_id` or `name` is missing or blank (`missing_audio_id`), the name is too long (`name_too_long`), or it contains a NUL character (`invalid_name`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_name",
                    "message": "name is required and must be non-empty",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_name"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No file of yours has this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Audio not found or not owned",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The name could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/star": {
      "post": {
        "operationId": "star_files",
        "tags": [
          "File actions"
        ],
        "summary": "Star or unstar files",
        "description": "Sets the star on up to 5000 files at once. Only files whose star actually changes are counted, so starring files that are already starred returns `updated: 0`. Ids that are not your files, and files in the trash, are skipped. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_starred",
          "missing_api_key",
          "missing_audio_ids",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "too_many_audio_ids",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "maxItems": 5000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "The files: library identifiers (`audio_id`) or storage identifiers (`file_id`) of your files, 1 to 5000."
                  },
                  "starred": {
                    "type": "boolean",
                    "description": "`true` to star, `false` to remove the star."
                  }
                },
                "required": [
                  "audio_ids",
                  "starred"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_bbb14949dc19"
                ],
                "starred": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The number of files changed.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "updated": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files whose star changed."
                            }
                          },
                          "required": [
                            "updated"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "updated": 3
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, `starred` is not a boolean, or `audio_ids` is missing, empty or too long (`missing_audio_ids`, `too_many_audio_ids`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_starred",
                    "message": "starred must be true or false",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_starred"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The star could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/storage-usage": {
      "get": {
        "operationId": "get_storage_usage",
        "tags": [
          "Files"
        ],
        "summary": "Get storage usage",
        "description": "Returns how much storage your account uses. Every account includes 1 TiB; `cap_bytes` reports that included amount. Files in the trash still count until they are removed for good. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Usage figures. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "used_bytes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Bytes your files use."
                        },
                        "cap_bytes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Bytes of storage included with the account."
                        },
                        "tier": {
                          "type": "string",
                          "enum": [
                            "free",
                            "paid"
                          ],
                          "description": "The account tier the figures are for."
                        }
                      },
                      "required": [
                        "used_bytes",
                        "cap_bytes",
                        "tier"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "used_bytes": 208773279,
                    "cap_bytes": 1099511627776,
                    "tier": "paid"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/tags": {
      "get": {
        "operationId": "list_tags",
        "tags": [
          "Tags"
        ],
        "summary": "List tags",
        "description": "Returns every tag in your library with the number of files that carry it: the tags you added (`user_tags`, with their color) and the ones Scarleta suggested (`auto_tags`). Files in the trash are not counted. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Your tags.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "user_tags": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "name": {
                                    "type": "string"
                                  },
                                  "count": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "Files that carry the tag."
                                  },
                                  "color": {
                                    "description": "The color set for the tag, or null.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "similar_to": {
                                    "type": "array",
                                    "items": {
                                      "type": "string"
                                    },
                                    "description": "Other tags that differ only by letter case or surrounding spaces."
                                  }
                                },
                                "required": [
                                  "name",
                                  "count",
                                  "color",
                                  "similar_to"
                                ],
                                "additionalProperties": false
                              },
                              "description": "Tags you put on files, most used first."
                            },
                            "auto_tags": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "name": {
                                    "type": "string"
                                  },
                                  "count": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  }
                                },
                                "required": [
                                  "name",
                                  "count"
                                ],
                                "additionalProperties": false
                              },
                              "description": "Tags Scarleta suggested from analysis of your files, most used first."
                            }
                          },
                          "required": [
                            "user_tags",
                            "auto_tags"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "user_tags": [
                      {
                        "name": "morning",
                        "count": 12,
                        "color": "blue",
                        "similar_to": []
                      }
                    ],
                    "auto_tags": [
                      {
                        "name": "speech",
                        "count": 40
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The tags could not be read. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "update_file_tags",
        "tags": [
          "Tags"
        ],
        "summary": "Add or remove tags on files",
        "description": "Adds the tags in `add` to, and removes the tags in `remove` from, every file in `audio_ids`, in one call. At most 50 tags per list, each at most 64 characters. A tag a file already has is not added twice, and a tag it does not have is ignored when removing. The response counts your files the call was applied to, including files that already had every tag to add and none of the tags to remove. Ids that are not your files are skipped without an error. If both lists are empty, or hold only empty strings, nothing is changed and `updated` is 0. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_tag",
          "missing_api_key",
          "missing_audio_ids",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "tag_too_long",
          "too_many_audio_ids",
          "too_many_tags",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Your files: library identifiers (`audio_id`) or storage identifiers (`file_id`). At least one."
                  },
                  "add": {
                    "description": "Tags to add, at most 50 of at most 64 characters each. Empty strings are ignored.",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 64
                    }
                  },
                  "remove": {
                    "description": "Tags to remove, at most 50 of at most 64 characters each. Empty strings are ignored.",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 64
                    }
                  }
                },
                "required": [
                  "audio_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_bbb14949dc19"
                ],
                "add": [
                  "morning",
                  "demo"
                ],
                "remove": [
                  "draft"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The number of your files the call was applied to. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "updated": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Your files the call was applied to, whether or not their tags actually changed."
                        }
                      },
                      "required": [
                        "updated"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "updated": 2
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is empty or invalid JSON, `audio_ids` is missing or empty, a tag is too long, or a list has too many tags (`too_many_tags`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "tag_too_long",
                    "message": "Tags must not exceed 64 characters",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#tag_too_long"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The tags could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/tags/adopt": {
      "post": {
        "operationId": "adopt_auto_tag",
        "tags": [
          "Tags"
        ],
        "summary": "Turn a suggested tag into your own",
        "description": "Adds a tag Scarleta suggested (`auto_tags` in the tag list) to every file it was suggested for, as one of your own tags, optionally under another name (`as`). Files that already have the tag are not changed. A suggested tag that does not exist changes nothing and returns `updated: 0`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_tag",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "tag_too_long",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "auto_tag": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "The suggested tag, 1 to 64 characters."
                  },
                  "as": {
                    "description": "The name to give it, 1 to 64 characters. Defaults to the suggested name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  }
                },
                "required": [
                  "auto_tag"
                ],
                "additionalProperties": false
              },
              "example": {
                "auto_tag": "speech",
                "as": "talk"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The number of files that gained the tag.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "updated": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files whose tags changed."
                            }
                          },
                          "required": [
                            "updated"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "updated": 8
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, or a name is empty or too long (`tag_too_long`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_tag",
                    "message": "auto_tag must be a non-empty tag name",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_tag"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The tag could not be adopted. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/tags/color": {
      "put": {
        "operationId": "set_tag_color",
        "tags": [
          "Tags"
        ],
        "summary": "Set a tag color",
        "description": "Sets the color of a tag, or clears it with `color: null`. The color is kept for the tag name even when no file carries it at the moment. Allowed colors: `red`, `orange`, `amber`, `green`, `teal`, `blue`, `purple`, `pink`, `gray`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_color",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_tag",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "tag_too_long",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "The tag, 1 to 64 characters."
                  },
                  "color": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "red",
                          "orange",
                          "amber",
                          "green",
                          "teal",
                          "blue",
                          "purple",
                          "pink",
                          "gray"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "A color, or `null` to clear it."
                  }
                },
                "required": [
                  "name",
                  "color"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "morning",
                "color": "blue"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The tag and its color after the change.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "name": {
                              "type": "string"
                            },
                            "color": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "name",
                            "color"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "name": "morning",
                    "color": "blue"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, the name is empty or too long, or the color is not an allowed one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_color",
                    "message": "color must be null or one of: red, orange, amber, green, teal, blue, purple, pink, gray",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_color"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The color could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/tags/merge": {
      "post": {
        "operationId": "merge_tags",
        "tags": [
          "Tags"
        ],
        "summary": "Merge tags into one",
        "description": "Replaces up to 20 tags with a single tag, on every file that carries any of them. If the target tag already has a color it keeps it; otherwise it takes the color of the first source that had one. The source tags disappear. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_tag",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "tag_too_long",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "from": {
                    "minItems": 1,
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "description": "A tag to merge away, 1 to 64 characters."
                    },
                    "description": "Tags to merge, 1 to 20."
                  },
                  "into": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "The tag to keep, 1 to 64 characters."
                  }
                },
                "required": [
                  "from",
                  "into"
                ],
                "additionalProperties": false
              },
              "example": {
                "from": [
                  "demo",
                  "draft"
                ],
                "into": "morning"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The number of files changed.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "updated": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files whose tags changed."
                            }
                          },
                          "required": [
                            "updated"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "updated": 5
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, `from` is not 1 to the allowed number of names, or a name is empty or too long (`tag_too_long`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_tag",
                    "message": "from must be an array of 1–20 tag names",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_tag"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The tags could not be merged. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/tags/rename": {
      "post": {
        "operationId": "rename_tag",
        "tags": [
          "Tags"
        ],
        "summary": "Rename a tag",
        "description": "Renames a tag on every file that carries it. If a file already has the new name the two merge. The tag's color moves to the new name. Renaming a tag nothing carries changes nothing and returns `updated: 0`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_tag",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "tag_too_long",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "from": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "The tag to rename, 1 to 64 characters."
                  },
                  "to": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "The new name, 1 to 64 characters."
                  }
                },
                "required": [
                  "from",
                  "to"
                ],
                "additionalProperties": false
              },
              "example": {
                "from": "demo",
                "to": "draft-demo"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The number of files changed.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "updated": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files whose tags changed."
                            }
                          },
                          "required": [
                            "updated"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "updated": 3
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, or a name is empty, or too long (`tag_too_long`). `error.details.field` names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_tag",
                    "message": "to must be a non-empty tag name",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_tag"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The tag could not be renamed. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/tags/selection-state": {
      "post": {
        "operationId": "get_tag_selection_state",
        "tags": [
          "Tags"
        ],
        "summary": "Count tags across a selection of files",
        "description": "For the files you name, returns each tag they carry with how many of those files carry it, so a tag that is on all of them can be told from one that is on some. Files that are not yours, and files in the trash, are left out. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_audio_ids",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "too_many_audio_ids",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "maxItems": 5000,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "The selection: library identifiers (`audio_id`) or storage identifiers (`file_id`) of your files, 1 to 5000."
                  }
                },
                "required": [
                  "audio_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_bbb14949dc19"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag counts for the selection. An empty object when no tag applies.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "description": "Tag name mapped to the number of selected files that carry it."
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "morning": 2,
                    "demo": 1
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The `audio_ids` list is missing, empty, or not a list of strings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_ids",
                    "message": "audio_ids must be a non-empty array of strings",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_ids"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The tags could not be read. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/trash": {
      "get": {
        "operationId": "list_trash",
        "tags": [
          "Trash"
        ],
        "summary": "List the trash",
        "description": "Lists the files you moved to the trash, newest first. A trashed file is kept for 7 days, then removed for good; `purge_after` says when. Only your own files are ever returned.\n\nPage with `limit` and `cursor`: pass `next_cursor` from one response as `cursor` in the next while it is not null. `limit` defaults to 100; larger values are lowered to 200, and a value that is not a positive number counts as the default. On success this route answers `{ data }` without `meta`; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Items per page, 1 to 200. Defaults to 100.",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "description": "The `next_cursor` of the previous page. An unreadable cursor restarts from the first page.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of trashed files. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "audio_id": {
                                "type": "string"
                              },
                              "file_id": {
                                "description": "The file id of the stored file, when it has one.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "size_bytes": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "format": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "trashed_at": {
                                "type": "string",
                                "description": "When the file was moved to the trash, as an ISO 8601 time."
                              },
                              "purge_after": {
                                "type": "string",
                                "description": "When the file is removed for good, as an ISO 8601 time."
                              }
                            },
                            "required": [
                              "audio_id",
                              "file_id",
                              "name",
                              "size_bytes",
                              "format",
                              "trashed_at",
                              "purge_after"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "next_cursor": {
                          "description": "Pass this as `cursor` to get the next page; null on the last page.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "items",
                        "next_cursor"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "items": [
                      {
                        "audio_id": "audio_3f9c1a7d2b60",
                        "file_id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                        "name": "old-take.wav",
                        "size_bytes": 5290044,
                        "format": "wav",
                        "trashed_at": "2026-10-21T05:36:53.621Z",
                        "purge_after": "2026-10-28T05:36:53.621Z"
                      }
                    ],
                    "next_cursor": null
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/trash/delete-forever": {
      "post": {
        "operationId": "delete_from_trash_forever",
        "tags": [
          "Trash"
        ],
        "summary": "Delete trashed files permanently",
        "description": "Removes files from the trash for good: the stored audio and everything attached to it is deleted and cannot be restored. Only files that are already in your trash qualify; any other id comes back with `deleted: false` and nothing happens to it. Send 1 to 100 ids. On success this route answers `{ data }` without `meta`; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_audio_ids",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "too_many_ids",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Ids of files in your trash, 1 to 100. Each is a file's `audio_id` or its file id."
                  }
                },
                "required": [
                  "audio_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_3f9c1a7d2b60"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per id sent, in the order sent. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "audio_id": {
                                "type": "string"
                              },
                              "deleted": {
                                "type": "boolean"
                              },
                              "reason": {
                                "description": "Why a file could not be deleted, when it could not (`error` for a failed delete).",
                                "type": "string"
                              }
                            },
                            "required": [
                              "audio_id",
                              "deleted"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "results"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "results": [
                      {
                        "audio_id": "audio_3f9c1a7d2b60",
                        "deleted": true
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not a JSON object, `audio_ids` is missing, empty or not a list of strings, or it names more ids than allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_ids",
                    "message": "audio_ids must be a non-empty array",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_ids"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/trash/empty": {
      "post": {
        "operationId": "empty_trash",
        "tags": [
          "Trash"
        ],
        "summary": "Empty the trash",
        "description": "Permanently deletes every file in your trash. It takes no body. This cannot be undone, and it acts on the whole trash, so check the trash list first. A file that cannot be removed stays in the trash and is counted in `failed`; the rest are still removed. On success this route answers `{ data }` without `meta`; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "How many files were removed, and how many could not be. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files removed for good."
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Files that could not be removed and are still in the trash."
                        }
                      },
                      "required": [
                        "deleted",
                        "failed"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "deleted": 3,
                    "failed": 0
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/trash/restore": {
      "post": {
        "operationId": "restore_from_trash",
        "tags": [
          "Trash"
        ],
        "summary": "Restore files from the trash",
        "description": "Moves files back out of the trash. Each file returns exactly as it was, with its tags, notes, analyses, versions and shares. Send 1 to 100 ids. The answer lists every id you sent with `restored`: false for an id that is not in your trash. On success this route answers `{ data }` without `meta`; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_audio_ids",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "too_many_ids",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_ids": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "Ids of files in your trash, 1 to 100. Each is a file's `audio_id` or its file id."
                  }
                },
                "required": [
                  "audio_ids"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_ids": [
                  "audio_3f9c1a7d2b60"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per id sent, in the order sent. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "audio_id": {
                                "type": "string"
                              },
                              "restored": {
                                "type": "boolean",
                                "description": "False when the id is not one of your trashed files."
                              }
                            },
                            "required": [
                              "audio_id",
                              "restored"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "results"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "results": [
                      {
                        "audio_id": "audio_3f9c1a7d2b60",
                        "restored": true
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not a JSON object, `audio_ids` is missing, empty or not a list of strings, or it names more ids than allowed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_ids",
                    "message": "audio_ids must be a non-empty array",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_ids"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/ungrouped": {
      "get": {
        "operationId": "search_ungrouped_files",
        "tags": [
          "Versions"
        ],
        "summary": "Find files that are not yet a version of a track",
        "description": "Lists your own top-level files that do not belong to any track group, optionally filtered by a name search. Use it to pick files to add as versions of a track. Only your own files are ever returned. `limit` defaults to 50 and larger values are lowered to 100.\n\nThis route answers with the older body shape: success is `{ data }` with no `meta`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Keep files whose file name or display name contains this text.",
              "type": "string"
            }
          },
          {
            "name": "exclude",
            "in": "query",
            "required": false,
            "schema": {
              "description": "An `audio_id` to leave out of the result.",
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Files to return. Defaults to 50; larger values are lowered to 100.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The matching files. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "audio_id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "uploaded_at": {
                            "type": "string",
                            "description": "Upload time in milliseconds since the Unix epoch, as a string."
                          },
                          "file_size_bytes": {
                            "type": [
                              "number",
                              "string",
                              "null"
                            ]
                          },
                          "format": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "audio_id",
                          "name",
                          "uploaded_at",
                          "file_size_bytes",
                          "format"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "audio_id": "audio_3f9c1a7d2b60",
                      "name": "demo-mix.wav",
                      "uploaded_at": "1791333870854",
                      "file_size_bytes": 5290044,
                      "format": "wav"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/upload-url": {
      "post": {
        "operationId": "create_upload_url",
        "tags": [
          "Files"
        ],
        "summary": "Get a presigned upload URL",
        "description": "Starts an upload that goes straight to storage. Declare the file with `content_length` (and `content_type`), then send the file bytes with a `PUT` to the returned `upload_url` within 15 minutes. The file then appears in your library and the file list. A file can be up to 10 GiB for audio and 1 GiB for MP4 or MOV video.\n\n`upload_url` is opaque: send the request to it exactly as returned, with the same `Content-Type` you declared, and do not parse it or add your API key (the URL itself is the credential). When `direct` is `false` the URL points back at this API instead of storage; the same `PUT` rules apply. Use `media_url` to refer to the stored file afterwards, and `audio_id` to attach it as a version.\n\nDeclaring the size reserves that much of your storage right away, so a file that would not fit is refused here with 413 `storage_quota_exceeded`, before any bytes are sent. An upload you never complete keeps its reservation until it is cleaned up. For files you want to resume, or for many parts in parallel, use an upload session instead. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge; the file counts toward your storage."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "file_too_large",
          "invalid_auth_format",
          "invalid_content_type",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_content_length",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "storage_quota_exceeded",
          "unauthorized",
          "upload_unavailable"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content_length": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 10737418240,
                    "description": "Size of the file in bytes. Required. At most 10 GiB for audio and 1 GiB for video. `size` is accepted as an alias."
                  },
                  "content_type": {
                    "description": "Content type of the file. Defaults to `audio/wav`. One of: `audio/wav`, `audio/wave`, `audio/x-wav`, `audio/mpeg`, `audio/mp3`, `audio/ogg`, `audio/flac`, `audio/aac`, `audio/m4a`, `audio/mp4`, `audio/x-m4a`, `audio/aiff`, `audio/x-aiff`, `audio/webm`, `audio/opus`, `audio/x-opus+ogg`, `video/mp4`, `video/quicktime`.",
                    "type": "string"
                  },
                  "filename": {
                    "description": "Name to show for the file, at most 255 characters. Path separators and control characters are removed.",
                    "type": "string",
                    "maxLength": 255
                  },
                  "duration_seconds": {
                    "description": "Length of the audio in seconds, if you know it. Display only: it is never used for billing. Values outside 0 to 86400 are ignored.",
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 86400
                  }
                },
                "required": [
                  "content_length"
                ],
                "additionalProperties": false
              },
              "example": {
                "content_type": "audio/wav",
                "filename": "morning-session.wav",
                "content_length": 1920044,
                "duration_seconds": 60
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload prepared. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "upload_url": {
                          "type": "string",
                          "description": "Where to `PUT` the file bytes. Opaque; use it as returned."
                        },
                        "file_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the new file."
                        },
                        "key": {
                          "type": "string",
                          "description": "Storage path of the file inside your account."
                        },
                        "expires_in": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Seconds `upload_url` stays valid: 900."
                        },
                        "content_type": {
                          "type": "string",
                          "description": "The content type to send with the `PUT`."
                        },
                        "filename": {
                          "type": "string"
                        },
                        "direct": {
                          "type": "boolean",
                          "description": "`true` when `upload_url` goes straight to storage; `false` when it points back at this API."
                        },
                        "media_url": {
                          "type": "string",
                          "description": "Permanent address of the file once uploaded. Use it to refer to the file in other requests."
                        },
                        "playback_url": {
                          "type": "string",
                          "description": "Signed address for playing the file in a browser; it expires, `media_url` does not."
                        },
                        "audio_id": {
                          "description": "Library identifier of the file, used to attach it as a version of another file. `null` if it could not be computed.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "upload_url",
                        "file_id",
                        "key",
                        "expires_in",
                        "content_type",
                        "filename",
                        "direct",
                        "media_url",
                        "playback_url",
                        "audio_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "upload_url": "https://storage.example.com/uploads/3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav?signature=…",
                    "file_id": "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b",
                    "key": "00000000-0000-4000-8000-000000000001/audio/3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav",
                    "expires_in": 900,
                    "content_type": "audio/wav",
                    "filename": "morning-session.wav",
                    "direct": true,
                    "media_url": "https://api.scarleta.ai/v1/audio/media/3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav",
                    "playback_url": "https://api.scarleta.ai/v1/audio/media/3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav?exp=1792557639&sig=9f2c1d4e8a7b6c5d",
                    "audio_id": "audio_bbb14949dc19"
                  }
                }
              }
            }
          },
          "400": {
            "description": "No positive `content_length`, or a content type that is not one of the accepted ones.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_content_length",
                    "message": "content_length or size is required and must be a positive integer",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_content_length"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The declared size is over the per-file limit, or the file does not fit in your storage (`storage_quota_exceeded`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_too_large",
                    "message": "This file is larger than 10 GB, the most a single file can be.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The upload could not be registered; nothing was reserved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/upload/{fileId}": {
      "put": {
        "operationId": "upload_file_bytes",
        "tags": [
          "Files"
        ],
        "summary": "Upload file bytes through the API",
        "description": "Fallback target of a presigned upload. When the upload URL from the presigned upload route has `direct: false`, it points here: it already carries the one-time `t` token, so call it exactly as returned, with the file bytes as the request body and the `Content-Type` you declared. There is no API key on this route; the token is the credential, it works once, and a URL that is expired, used or wrong gets 403 `invalid_upload_intent`.\n\nThe body is read in one piece, so the limit is 100 MiB for audio. The bytes are checked: a file that is not valid audio is refused with 400 `invalid_file_signature`. Uploads are limited to 30 per hour per source address. Most accounts receive `direct: true` URLs and never call this route.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "file_too_large",
          "invalid_content_type",
          "invalid_file_signature",
          "invalid_upload_intent",
          "missing_body",
          "rate_limit_exceeded",
          "rate_limit_unavailable"
        ],
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `file_id` of one of your files, as returned by the upload routes and the file list. A trailing media extension such as `.wav` is ignored."
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": false,
            "schema": {
              "description": "One-time upload token. Already part of the `upload_url` that points here; leave it as returned.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary",
                "contentEncoding": "binary",
                "description": "The file bytes. Send them as the raw request body."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The file is stored. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "file_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the file."
                        },
                        "key": {
                          "type": "string",
                          "description": "Storage path of the file inside your account."
                        },
                        "status": {
                          "type": "string",
                          "const": "uploaded"
                        },
                        "uploaded_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "file_id",
                        "key",
                        "status",
                        "uploaded_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "file_id": "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b",
                    "key": "00000000-0000-4000-8000-000000000001/audio/3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav",
                    "status": "uploaded",
                    "uploaded_at": "2026-10-20T11:53:45.938Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is empty, the content type is not accepted, or the file is not audio.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_file_signature",
                    "message": "File does not appear to be a valid audio file",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_file_signature"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The URL has expired, was already used, or the token is missing or wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_upload_intent",
                    "message": "Upload URL has expired or is invalid",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_upload_intent"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this route accepts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_too_large",
                    "message": "File size exceeds maximum allowed size",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/uploads": {
      "get": {
        "operationId": "list_upload_sessions",
        "tags": [
          "Upload sessions"
        ],
        "summary": "List unfinished upload sessions",
        "description": "Returns your upload sessions that are still open, newest first (up to 200), so an interrupted upload can be found and resumed. Finished and cancelled sessions are not listed. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_status",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "upload_unavailable"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Only `uploading` is supported, and it is the default.",
              "type": "string",
              "const": "uploading"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Open sessions. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "sessions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "session_id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                                "description": "Identifier of the session."
                              },
                              "file_id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                                "description": "Identifier the file will have once completed."
                              },
                              "audio_id": {
                                "type": "string"
                              },
                              "filename": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "content_type": {
                                "type": "string"
                              },
                              "declared_bytes": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Size declared when the session was created."
                              },
                              "part_size_bytes": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "part_count": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "tags": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "version_of": {
                                "description": "`audio_id` this upload will be attached to, if any.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              },
                              "expires_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              }
                            },
                            "required": [
                              "session_id",
                              "file_id",
                              "audio_id",
                              "filename",
                              "content_type",
                              "declared_bytes",
                              "part_size_bytes",
                              "part_count",
                              "tags",
                              "version_of",
                              "created_at",
                              "expires_at"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "sessions"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "sessions": [
                      {
                        "session_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                        "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
                        "audio_id": "audio_bbb14949dc19",
                        "filename": "morning-session.wav",
                        "content_type": "audio/wav",
                        "declared_bytes": 1920044,
                        "part_size_bytes": 16777216,
                        "part_count": 1,
                        "tags": [
                          "morning"
                        ],
                        "version_of": null,
                        "created_at": "2026-10-20T11:53:45.938Z",
                        "expires_at": "2026-10-27T11:53:45.938Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "A `status` other than `uploading`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_status",
                    "message": "Only status=uploading is supported",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_status"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The database is temporarily unavailable. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_upload_session",
        "tags": [
          "Upload sessions"
        ],
        "summary": "Start an upload session",
        "description": "Starts a resumable upload for a file of any size up to 10 GiB (1 GiB for MP4 or MOV video). The file is sent in parts of `part_size_bytes` (16 MiB; the last part is smaller), at most 10000 parts. The flow is: create the session, ask for part URLs, `PUT` each part to its URL (parts can go in parallel and be retried), then complete the session. A session you do not finish can be resumed by reading its status, and is cleaned up 7 days after it started.\n\nCreating a session reserves the declared size in your storage at once, so a file that would not fit is refused here with 413 `storage_quota_exceeded`. At most 50 sessions started in the last 60 minutes can be unfinished at the same time. If you send `sha256`, repeating the same request (same hash, filename, size and `version_of`) within 5 minutes returns the open session instead of starting a second one, which makes a lost response safe to retry. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge; the file counts toward your storage."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "file_too_large",
          "invalid_auth_format",
          "invalid_content_type",
          "invalid_duration",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_sha256",
          "invalid_tags",
          "invalid_version_of",
          "missing_api_key",
          "missing_auth",
          "missing_filename",
          "missing_size",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "storage_quota_exceeded",
          "tag_too_long",
          "too_many_active_uploads",
          "too_many_tags",
          "unauthorized",
          "upload_unavailable"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "filename": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "Name to show for the file, at most 255 characters. Required."
                  },
                  "content_type": {
                    "type": "string",
                    "description": "Content type of the file. Required. One of: `audio/wav`, `audio/wave`, `audio/x-wav`, `audio/mpeg`, `audio/mp3`, `audio/ogg`, `audio/flac`, `audio/aac`, `audio/m4a`, `audio/mp4`, `audio/x-m4a`, `audio/aiff`, `audio/x-aiff`, `audio/webm`, `audio/opus`, `audio/x-opus+ogg`, `video/mp4`, `video/quicktime`."
                  },
                  "size_bytes": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 10737418240,
                    "description": "Size of the whole file in bytes. Required. At most 10 GiB for audio and 1 GiB for video."
                  },
                  "sha256": {
                    "description": "SHA-256 of the file bytes as 64 hexadecimal characters. Optional; enables safe retry of this call.",
                    "type": "string",
                    "pattern": "^[0-9a-fA-F]{64}$"
                  },
                  "tags": {
                    "description": "Tags to put on the file, at most 50 of at most 64 characters each. Blank tags are dropped and duplicates merged.",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 64
                    }
                  },
                  "version_of": {
                    "description": "`audio_id` of one of your ready files to attach this upload to as a new version, once it completes.",
                    "type": "string",
                    "maxLength": 200
                  },
                  "client_duration_seconds": {
                    "description": "Length of the audio in seconds, if you know it. Display only; never used for billing.",
                    "type": "number",
                    "minimum": 0
                  }
                },
                "required": [
                  "filename",
                  "content_type",
                  "size_bytes"
                ],
                "additionalProperties": false
              },
              "example": {
                "filename": "morning-session.wav",
                "content_type": "audio/wav",
                "size_bytes": 1920044,
                "tags": [
                  "morning"
                ],
                "client_duration_seconds": 60
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session created. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "session_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the session."
                        },
                        "file_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier the file will have once completed."
                        },
                        "audio_id": {
                          "type": "string",
                          "description": "Library identifier of the file."
                        },
                        "part_size_bytes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Size of every part except the last."
                        },
                        "part_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Number of parts to send."
                        },
                        "parts_done": {
                          "type": "array",
                          "items": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "description": "Part numbers already uploaded (empty for a new session)."
                        },
                        "expires_at": {
                          "type": "string",
                          "description": "When an unfinished session is cleaned up, as an ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "session_id",
                        "file_id",
                        "audio_id",
                        "part_size_bytes",
                        "part_count",
                        "parts_done",
                        "expires_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "session_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                    "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
                    "audio_id": "audio_bbb14949dc19",
                    "part_size_bytes": 16777216,
                    "part_count": 1,
                    "parts_done": [],
                    "expires_at": "2026-10-27T11:53:45.938Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A required field is missing or malformed, `tags`, `sha256` or the duration is invalid, or `version_of` is not one of your ready files.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_filename",
                    "message": "filename is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_filename"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The declared size is over the per-file limit, or the file does not fit in your storage (`storage_quota_exceeded`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_too_large",
                    "message": "This file is larger than 10 GB, the most a single file can be.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many unfinished sessions, or over the per-minute cap of these routes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "too_many_active_uploads",
                    "message": "Too many uploads in progress. Finish or cancel some before starting more.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#too_many_active_uploads"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The session could not be registered; nothing was reserved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/uploads/{sessionId}": {
      "get": {
        "operationId": "get_upload_session",
        "tags": [
          "Upload sessions"
        ],
        "summary": "Get an upload session",
        "description": "Returns the state of one session, with the parts storage has actually received, so an interrupted upload resumes by sending only the missing parts. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "upload_session_not_found",
          "upload_unavailable"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `session_id` returned when the session was created."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session state. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "session_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the session."
                        },
                        "file_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier the file has once completed."
                        },
                        "audio_id": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "uploading",
                            "completed",
                            "aborted",
                            "expired"
                          ],
                          "description": "`uploading` until completed or cancelled."
                        },
                        "parts_done": {
                          "type": "array",
                          "items": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991
                          },
                          "description": "Part numbers storage has received."
                        },
                        "bytes_done": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Total size of those parts in bytes."
                        },
                        "declared_bytes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "part_size_bytes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "part_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "filename": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "expires_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "session_id",
                        "file_id",
                        "audio_id",
                        "status",
                        "parts_done",
                        "bytes_done",
                        "declared_bytes",
                        "part_size_bytes",
                        "part_count",
                        "filename",
                        "expires_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "session_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                    "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
                    "audio_id": "audio_bbb14949dc19",
                    "status": "uploading",
                    "parts_done": [
                      1
                    ],
                    "bytes_done": 1920044,
                    "declared_bytes": 1920044,
                    "part_size_bytes": 16777216,
                    "part_count": 1,
                    "filename": "morning-session.wav",
                    "expires_at": "2026-10-27T11:53:45.938Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No upload session with this id in your account. A session that belongs to another account is reported the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_session_not_found",
                    "message": "Upload session not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_session_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Storage or the database is temporarily unavailable. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/uploads/{sessionId}/abort": {
      "post": {
        "operationId": "abort_upload_session",
        "tags": [
          "Upload sessions"
        ],
        "summary": "Cancel an upload session",
        "description": "Cancels an unfinished session: the parts are discarded and the storage reserved for the file is released. Cancelling a session that is already cancelled succeeds again; one that already completed returns 409 `session_not_uploading` (delete the file instead). Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "session_not_uploading",
          "unauthorized",
          "upload_session_not_found",
          "upload_unavailable"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `session_id` returned when the session was created."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The session is cancelled. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "const": "aborted"
                        }
                      },
                      "required": [
                        "status"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "status": "aborted"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No upload session with this id in your account. A session that belongs to another account is reported the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_session_not_found",
                    "message": "Upload session not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_session_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The session already completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "session_not_uploading",
                    "message": "This upload has already finished",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#session_not_uploading"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Storage or the database is temporarily unavailable. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/uploads/{sessionId}/complete": {
      "post": {
        "operationId": "complete_upload_session",
        "tags": [
          "Upload sessions"
        ],
        "summary": "Complete an upload session",
        "description": "Assembles the uploaded parts into the file. Every part must be uploaded with the right size and the total must match the size you declared. The bytes are then checked: a file that is not audio is removed and refused with 415 `not_audio`. On success the file is ready in your library. Completing a session that already completed returns the same result, so the call is safe to retry.\n\nOptionally add `tags` (merged with the ones from the start), change `version_of`, or give `client_duration_seconds`. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "file_too_large",
          "invalid_auth_format",
          "invalid_duration",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_tags",
          "missing_api_key",
          "missing_auth",
          "not_audio",
          "part_size_mismatch",
          "parts_missing",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "session_not_uploading",
          "size_mismatch",
          "tag_too_long",
          "too_many_tags",
          "unauthorized",
          "upload_reservation_missing",
          "upload_session_not_found",
          "upload_unavailable"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `session_id` returned when the session was created."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tags": {
                    "description": "Tags to put on the file, at most 50 of at most 64 characters each. Blank tags are dropped and duplicates merged.",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 64
                    }
                  },
                  "version_of": {
                    "description": "`audio_id` of one of your ready files to attach this upload to. A value that is not one of yours is ignored.",
                    "type": "string",
                    "maxLength": 200
                  },
                  "client_duration_seconds": {
                    "description": "Length of the audio in seconds. Display only.",
                    "type": "number",
                    "minimum": 0
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "tags": [
                  "morning"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The file is ready. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_id": {
                          "type": "string",
                          "description": "Library identifier of the file."
                        },
                        "file_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the file."
                        },
                        "size_bytes": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Final size in bytes."
                        },
                        "format": {
                          "type": "string",
                          "description": "Detected audio format."
                        },
                        "status": {
                          "type": "string",
                          "const": "ready"
                        },
                        "version_link": {
                          "anyOf": [
                            {
                              "type": "string",
                              "enum": [
                                "linked",
                                "failed"
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "`linked` or `failed` when `version_of` was requested, otherwise `null`."
                        }
                      },
                      "required": [
                        "audio_id",
                        "file_id",
                        "size_bytes",
                        "format",
                        "status",
                        "version_link"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_id": "audio_bbb14949dc19",
                    "file_id": "9e8d7c6b-5a49-4382-b170-6f5e4d3c2b1a",
                    "size_bytes": 1920044,
                    "format": "wav",
                    "status": "ready",
                    "version_link": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "`tags` or `client_duration_seconds` is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_tags",
                    "message": "tags must be an array of strings",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_tags"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No upload session with this id in your account. A session that belongs to another account is reported the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_session_not_found",
                    "message": "Upload session not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_session_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "A part is missing or has the wrong size, the parts add up to more than the declared size, or the session was cancelled or already ended another way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "parts_missing",
                    "message": "Some parts of this upload are missing",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#parts_missing"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The uploaded bytes exceed the per-file limit; the upload is cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_too_large",
                    "message": "This file is larger than 10 GB, the most a single file can be.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_too_large"
                  }
                }
              }
            }
          },
          "415": {
            "description": "The assembled file is not a supported audio or video file; it is removed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_audio",
                    "message": "This isn't an audio file we can store.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_audio"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Storage is temporarily unavailable. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/uploads/{sessionId}/part-urls": {
      "post": {
        "operationId": "create_upload_part_urls",
        "tags": [
          "Upload sessions"
        ],
        "summary": "Get upload URLs for parts",
        "description": "Returns one upload URL per requested part, at most 20 per call. Send each part's bytes with a `PUT` to its `url`, exactly as returned and with no API key (the URL is the credential), within 60 minutes. A part is exactly `part_size_bytes` long except the last one. A part can be sent again; the last copy wins. Ask again for fresh URLs if they expire. URLs are opaque: do not parse them. Capped at 60 requests per minute per account across the upload session routes and the duplicate check; these routes do not use up the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_part_numbers",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "session_not_uploading",
          "unauthorized",
          "upload_session_not_found",
          "upload_unavailable"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `session_id` returned when the session was created."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "part_numbers": {
                    "minItems": 1,
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 10000
                    },
                    "description": "Parts to get URLs for, each between 1 and the session's `part_count`, at most 20 numbers."
                  }
                },
                "required": [
                  "part_numbers"
                ],
                "additionalProperties": false
              },
              "example": {
                "part_numbers": [
                  1
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One URL per requested part. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "urls": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "part_number": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "url": {
                                "type": "string",
                                "description": "Where to `PUT` this part. Opaque; use it as returned."
                              },
                              "expires_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              }
                            },
                            "required": [
                              "part_number",
                              "url",
                              "expires_at"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "urls"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "urls": [
                      {
                        "part_number": 1,
                        "url": "https://storage.example.com/uploads/part-1?signature=…",
                        "expires_at": "2026-10-21T04:40:00.000Z"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "`part_numbers` is empty, too long or has a number outside the session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_part_numbers",
                    "message": "part_numbers must be an array of 1–20 part numbers",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_part_numbers"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No upload session with this id in your account. A session that belongs to another account is reported the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_session_not_found",
                    "message": "Upload session not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_session_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The session is already completed or cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "session_not_uploading",
                    "message": "This upload has already finished",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#session_not_uploading"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Part URLs could not be created. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/uploads/{sessionId}/parts/{n}": {
      "put": {
        "operationId": "upload_session_part",
        "tags": [
          "Upload sessions"
        ],
        "summary": "Upload a part through the API",
        "description": "Fallback target of a part URL. When a URL from the part-urls route points at this API instead of at storage, send the part bytes to it exactly as returned: it already carries the one-time `t` token, which is the credential, so there is no API key. The request needs a `Content-Length` header (without one it is refused with HTTP 411 `missing_content_length`) and a body no larger than `part_size_bytes`. Most accounts receive storage URLs and never call this route.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "invalid_part_number",
          "invalid_upload_token",
          "missing_body",
          "missing_content_length",
          "part_too_large",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "session_not_uploading",
          "upload_unavailable"
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `session_id` of the session."
            }
          },
          {
            "name": "n",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d+$",
              "description": "Part number, from 1 to the session's `part_count`."
            }
          },
          {
            "name": "t",
            "in": "query",
            "required": false,
            "schema": {
              "description": "One-time token. Already part of the URL that points here; leave it as returned.",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary",
                "contentEncoding": "binary",
                "description": "The part bytes, as the raw request body."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The part is stored. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "part_number": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "etag": {
                          "type": "string",
                          "description": "Opaque checksum of the stored part."
                        }
                      },
                      "required": [
                        "part_number",
                        "etag"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "part_number": 1,
                    "etag": "a54357aff0632cce46d942af68356b38"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The part number is not within the session, or the body is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_part_number",
                    "message": "part number must be between 1 and 3",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_part_number"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The URL has expired, or the token is missing or wrong.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_upload_token",
                    "message": "Upload URL has expired or is invalid",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_upload_token"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The session already completed or was cancelled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "session_not_uploading",
                    "message": "This upload has already finished",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#session_not_uploading"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than `part_size_bytes`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "part_too_large",
                    "message": "This part is larger than the upload part size",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#part_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Storage or the database is temporarily unavailable. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "upload_unavailable",
                    "message": "Upload couldn't start. Try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#upload_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/versions/{versionId}/audio-url": {
      "get": {
        "operationId": "get_version_audio_url",
        "tags": [
          "Versions"
        ],
        "summary": "Get the audio URL of one version",
        "description": "Returns the URL to pass as `audio_url` when running an analysis on one version of a track. `versionId` is the version's `id` or `audio_id` from the library list. `audio_url` is null when the original file is not stored. Only your own files are ever returned. On success this route answers `{ data }` without `meta`; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "file_not_found",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_version_id",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "versionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `id` or `audio_id` of a version in your library."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The URL of that version. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_url": {
                          "description": "URL of the stored file, or null when only a link was stored.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "audio_url"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No version with this id exists in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_not_found",
                    "message": "Audio version not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/versions/add": {
      "post": {
        "operationId": "add_version",
        "tags": [
          "Versions"
        ],
        "summary": "Make a file a version of a track",
        "description": "Groups `source_audio_id` as another version of the track that `target_audio_id` belongs to. If the target is not in a group yet, a group is created. Both files must be your own top-level files; a file that is already in a group, or the same file twice, is refused with 400 `invalid_grouping`. On success this route answers `{ data }` without `meta`; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "file_not_found",
          "invalid_auth_format",
          "invalid_body",
          "invalid_grouping",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "target_audio_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "A file of the track to add to."
                  },
                  "source_audio_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The file that becomes a version of that track."
                  }
                },
                "required": [
                  "target_audio_id",
                  "source_audio_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "target_audio_id": "audio_3f9c1a7d2b60",
                "source_audio_id": "audio_a81e5c40d7f2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The two files are now versions of one track. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "track_group_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the track group."
                        },
                        "status": {
                          "type": "string",
                          "const": "grouped"
                        }
                      },
                      "required": [
                        "track_group_id",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "track_group_id": "7d2c9e1a-4b3f-4c68-9a5d-1e0f8b7c6a52",
                    "status": "grouped"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A required field is missing or not a string (`invalid_body`), or the files cannot be grouped: the same file twice, a file already in a group, or a derived file (`invalid_grouping`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_grouping",
                    "message": "Files cannot be grouped as requested",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_grouping"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "A file does not exist in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_not_found",
                    "message": "Audio file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/versions/remove": {
      "post": {
        "operationId": "remove_version",
        "tags": [
          "Versions"
        ],
        "summary": "Remove a file from its track",
        "description": "Takes a file out of its track group so it becomes a track of its own again. Calling it on a file that is not in a group succeeds and changes nothing. On success this route answers `{ data }` without `meta`; errors use the standard error body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "file_not_found",
          "invalid_auth_format",
          "invalid_body",
          "invalid_grouping",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The file to take out of its track."
                  }
                },
                "required": [
                  "audio_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_id": "audio_a81e5c40d7f2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The file is a track of its own. This response has no `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "audio_id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "const": "ungrouped"
                        }
                      },
                      "required": [
                        "audio_id",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  }
                },
                "example": {
                  "data": {
                    "audio_id": "audio_a81e5c40d7f2",
                    "status": "ungrouped"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`audio_id` is missing or not a string, or the file cannot be ungrouped (`invalid_grouping`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_body",
                    "message": "audio_id is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_body"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The file does not exist in your library.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_not_found",
                    "message": "Audio file not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/views": {
      "get": {
        "operationId": "list_views",
        "tags": [
          "Saved views"
        ],
        "summary": "List saved views",
        "description": "Returns all your saved views, newest first. `data` is the list itself. A stored definition that can no longer be read is returned as the default definition instead of failing the list. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Your views. The body is `{ data }` where `data` is an array, without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                            "description": "Identifier of the view."
                          },
                          "name": {
                            "type": "string"
                          },
                          "origin": {
                            "type": "string",
                            "enum": [
                              "user",
                              "chat"
                            ],
                            "description": "`user` for views you saved, `chat` for views the assistant built in a conversation until you keep them."
                          },
                          "source_conversation_id": {
                            "description": "For a `chat` view, the conversation it was built in.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "source_tool_call_id": {
                            "description": "For a `chat` view, the step of that conversation that built it.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "definition": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {},
                            "description": "The definition in the current (version 2) form, as stored."
                          },
                          "dropped": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Parts of an older stored definition that the current form no longer supports and that were left out."
                          },
                          "config": {
                            "type": "object",
                            "propertyNames": {
                              "type": "string"
                            },
                            "additionalProperties": {},
                            "description": "The same definition in the older (version 1) form, kept for existing clients."
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "updated_at": {
                            "type": "string"
                          },
                          "last_opened_at": {
                            "description": "When the view was last read with the get route.",
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "origin",
                          "source_conversation_id",
                          "source_tool_call_id",
                          "definition",
                          "dropped",
                          "config",
                          "created_at",
                          "updated_at",
                          "last_opened_at"
                        ],
                        "additionalProperties": false
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                      "name": "Fast tracks",
                      "origin": "user",
                      "source_conversation_id": null,
                      "source_tool_call_id": null,
                      "definition": {
                        "version": 2,
                        "filters": {},
                        "sort": [],
                        "columns": []
                      },
                      "dropped": [],
                      "config": {},
                      "created_at": "2026-10-20T11:53:45.938Z",
                      "updated_at": "2026-10-20T11:53:45.938Z",
                      "last_opened_at": null
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_view",
        "tags": [
          "Saved views"
        ],
        "summary": "Create a saved view",
        "description": "Saves a named view of your library. Send `definition` (the current form) or `config` (the older form), not both; with neither, the view covers the whole library. The response is the stored view with `201`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_columns",
          "invalid_config",
          "invalid_filter",
          "invalid_group",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_name",
          "invalid_sort",
          "missing_api_key",
          "missing_auth",
          "missing_name",
          "name_too_long",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The view name, 1 to 200 characters after trimming."
                  },
                  "definition": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {},
                    "description": "The view definition: `{\"version\":2,\"filters\":{...},\"sort\":[...],\"group\":...,\"columns\":[...]}`. Every part is optional; `{\"version\":2}` is the whole library. The same definition is accepted by the library read route (`q`)."
                  },
                  "config": {
                    "description": "The older (version 1) form of the definition. Send this or `definition`, not both.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Fast tracks",
                "definition": {
                  "version": 2
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The view was saved. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the view."
                        },
                        "name": {
                          "type": "string"
                        },
                        "origin": {
                          "type": "string",
                          "enum": [
                            "user",
                            "chat"
                          ],
                          "description": "`user` for views you saved, `chat` for views the assistant built in a conversation until you keep them."
                        },
                        "source_conversation_id": {
                          "description": "For a `chat` view, the conversation it was built in.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "source_tool_call_id": {
                          "description": "For a `chat` view, the step of that conversation that built it.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "definition": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {},
                          "description": "The definition in the current (version 2) form, as stored."
                        },
                        "dropped": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Parts of an older stored definition that the current form no longer supports and that were left out."
                        },
                        "config": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {},
                          "description": "The same definition in the older (version 1) form, kept for existing clients."
                        },
                        "created_at": {
                          "type": "string"
                        },
                        "updated_at": {
                          "type": "string"
                        },
                        "last_opened_at": {
                          "description": "When the view was last read with the get route.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "origin",
                        "source_conversation_id",
                        "source_tool_call_id",
                        "definition",
                        "dropped",
                        "config",
                        "created_at",
                        "updated_at",
                        "last_opened_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                    "name": "Fast tracks",
                    "origin": "user",
                    "source_conversation_id": null,
                    "source_tool_call_id": null,
                    "definition": {
                      "version": 2,
                      "filters": {},
                      "sort": [],
                      "columns": []
                    },
                    "dropped": [],
                    "config": {},
                    "created_at": "2026-10-20T11:53:45.938Z",
                    "updated_at": "2026-10-20T11:53:45.938Z",
                    "last_opened_at": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, a name is missing (`missing_name`) or too long (`name_too_long`), or the definition is not valid (`invalid_config`, `invalid_filter`, `invalid_sort`, `invalid_group`, `invalid_columns`; `error.details.field` names the part).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_config",
                    "message": "Send definition or config, not both",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_config"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The view could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/views/{viewId}": {
      "delete": {
        "operationId": "delete_view",
        "tags": [
          "Saved views"
        ],
        "summary": "Delete a saved view",
        "description": "Deletes one of your saved views for good (views are not kept in a trash). Your files are not affected. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_view_id",
          "missing_api_key",
          "missing_auth",
          "missing_view_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "viewId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `id` of one of your saved views."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The view is deleted. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "The deleted view."
                        },
                        "deleted": {
                          "type": "boolean",
                          "const": true
                        }
                      },
                      "required": [
                        "id",
                        "deleted"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                    "deleted": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "The id is not a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_view_id",
                    "message": "viewId must be a valid UUID",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_view_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No view with this id in your account (or it is already deleted).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "View not found or not owned",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The view could not be deleted. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_view",
        "tags": [
          "Saved views"
        ],
        "summary": "Get a saved view",
        "description": "Returns one view and records that it was opened (`last_opened_at` in the response is the new time). Only your own views can be read; any other id returns 404 `view_not_found`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "view_not_found"
        ],
        "parameters": [
          {
            "name": "viewId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `id` of one of your saved views."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The view.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                              "description": "Identifier of the view."
                            },
                            "name": {
                              "type": "string"
                            },
                            "origin": {
                              "type": "string",
                              "enum": [
                                "user",
                                "chat"
                              ],
                              "description": "`user` for views you saved, `chat` for views the assistant built in a conversation until you keep them."
                            },
                            "source_conversation_id": {
                              "description": "For a `chat` view, the conversation it was built in.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "source_tool_call_id": {
                              "description": "For a `chat` view, the step of that conversation that built it.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "definition": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The definition in the current (version 2) form, as stored."
                            },
                            "dropped": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Parts of an older stored definition that the current form no longer supports and that were left out."
                            },
                            "config": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The same definition in the older (version 1) form, kept for existing clients."
                            },
                            "created_at": {
                              "type": "string"
                            },
                            "updated_at": {
                              "type": "string"
                            },
                            "last_opened_at": {
                              "description": "When the view was last read with the get route.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "origin",
                            "source_conversation_id",
                            "source_tool_call_id",
                            "definition",
                            "dropped",
                            "config",
                            "created_at",
                            "updated_at",
                            "last_opened_at"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                    "name": "Fast tracks",
                    "origin": "user",
                    "source_conversation_id": null,
                    "source_tool_call_id": null,
                    "definition": {
                      "version": 2,
                      "filters": {},
                      "sort": [],
                      "columns": []
                    },
                    "dropped": [],
                    "config": {},
                    "created_at": "2026-10-20T11:53:45.938Z",
                    "updated_at": "2026-10-20T11:53:45.938Z",
                    "last_opened_at": "2026-10-20T11:53:45.938Z"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No view with this id in your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "view_not_found",
                    "message": "View not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#view_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The view could not be read. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "update_view",
        "tags": [
          "Saved views"
        ],
        "summary": "Update a saved view",
        "description": "Changes the name and/or the definition of one of your views. Send at least one of `name`, `definition`, `config` (`definition` and `config` not together); a request that changes nothing returns 400 `nothing_to_update`. Parts you leave out stay as they are. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_columns",
          "invalid_config",
          "invalid_filter",
          "invalid_group",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_name",
          "invalid_sort",
          "invalid_view_id",
          "missing_api_key",
          "missing_auth",
          "missing_view_id",
          "name_too_long",
          "not_found",
          "nothing_to_update",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "viewId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `id` of one of your saved views."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The view name, 1 to 200 characters after trimming."
                  },
                  "definition": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {},
                    "description": "The view definition: `{\"version\":2,\"filters\":{...},\"sort\":[...],\"group\":...,\"columns\":[...]}`. Every part is optional; `{\"version\":2}` is the whole library. The same definition is accepted by the library read route (`q`)."
                  },
                  "config": {
                    "description": "The older (version 1) form of the definition. Send this or `definition`, not both.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "name": "Fast tracks v2",
                "definition": {
                  "version": 2
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated view. The body is `{ data }` without `meta`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the view."
                        },
                        "name": {
                          "type": "string"
                        },
                        "origin": {
                          "type": "string",
                          "enum": [
                            "user",
                            "chat"
                          ],
                          "description": "`user` for views you saved, `chat` for views the assistant built in a conversation until you keep them."
                        },
                        "source_conversation_id": {
                          "description": "For a `chat` view, the conversation it was built in.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "source_tool_call_id": {
                          "description": "For a `chat` view, the step of that conversation that built it.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "definition": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {},
                          "description": "The definition in the current (version 2) form, as stored."
                        },
                        "dropped": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Parts of an older stored definition that the current form no longer supports and that were left out."
                        },
                        "config": {
                          "type": "object",
                          "propertyNames": {
                            "type": "string"
                          },
                          "additionalProperties": {},
                          "description": "The same definition in the older (version 1) form, kept for existing clients."
                        },
                        "created_at": {
                          "type": "string"
                        },
                        "updated_at": {
                          "type": "string"
                        },
                        "last_opened_at": {
                          "description": "When the view was last read with the get route.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "origin",
                        "source_conversation_id",
                        "source_tool_call_id",
                        "definition",
                        "dropped",
                        "config",
                        "created_at",
                        "updated_at",
                        "last_opened_at"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                    "name": "Fast tracks",
                    "origin": "user",
                    "source_conversation_id": null,
                    "source_tool_call_id": null,
                    "definition": {
                      "version": 2,
                      "filters": {},
                      "sort": [],
                      "columns": []
                    },
                    "dropped": [],
                    "config": {},
                    "created_at": "2026-10-20T11:53:45.938Z",
                    "updated_at": "2026-10-20T11:53:45.938Z",
                    "last_opened_at": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "The id is not a UUID (`invalid_view_id`), the body is invalid JSON, nothing is being changed, the name is blank (`missing_name`) or too long, or the definition is not valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "nothing_to_update",
                    "message": "No fields to update",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#nothing_to_update"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No view with this id in your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "View not found or not owned",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The view could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/views/{viewId}/save": {
      "post": {
        "operationId": "save_view",
        "tags": [
          "Saved views"
        ],
        "summary": "Keep a view under a name",
        "description": "Keeps a view the assistant built in a conversation: its `origin` becomes `user` and it gets the name you send. On a view you already saved this just renames it. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_name",
          "name_too_long",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "view_not_found"
        ],
        "parameters": [
          {
            "name": "viewId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `id` of one of your saved views."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The view name, 1 to 200 characters after trimming."
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              },
              "example": {
                "name": "Fast tracks"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The kept view.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                              "description": "Identifier of the view."
                            },
                            "name": {
                              "type": "string"
                            },
                            "origin": {
                              "type": "string",
                              "enum": [
                                "user",
                                "chat"
                              ],
                              "description": "`user` for views you saved, `chat` for views the assistant built in a conversation until you keep them."
                            },
                            "source_conversation_id": {
                              "description": "For a `chat` view, the conversation it was built in.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "source_tool_call_id": {
                              "description": "For a `chat` view, the step of that conversation that built it.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "definition": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The definition in the current (version 2) form, as stored."
                            },
                            "dropped": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Parts of an older stored definition that the current form no longer supports and that were left out."
                            },
                            "config": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The same definition in the older (version 1) form, kept for existing clients."
                            },
                            "created_at": {
                              "type": "string"
                            },
                            "updated_at": {
                              "type": "string"
                            },
                            "last_opened_at": {
                              "description": "When the view was last read with the get route.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "origin",
                            "source_conversation_id",
                            "source_tool_call_id",
                            "definition",
                            "dropped",
                            "config",
                            "created_at",
                            "updated_at",
                            "last_opened_at"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                    "name": "Fast tracks",
                    "origin": "user",
                    "source_conversation_id": null,
                    "source_tool_call_id": null,
                    "definition": {
                      "version": 2,
                      "filters": {},
                      "sort": [],
                      "columns": []
                    },
                    "dropped": [],
                    "config": {},
                    "created_at": "2026-10-20T11:53:45.938Z",
                    "updated_at": "2026-10-20T11:53:45.938Z",
                    "last_opened_at": null
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is invalid JSON, or the name is missing (`missing_name`) or too long (`name_too_long`). `error.details.field` names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_name",
                    "message": "name is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_name"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No view with this id in your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "view_not_found",
                    "message": "View not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#view_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The view could not be saved. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/views/{viewId}/summary": {
      "get": {
        "operationId": "get_view_summary",
        "tags": [
          "Saved views"
        ],
        "summary": "Summarize a saved view",
        "description": "Counts what a view matches and describes it: the number of tracks and files, how many files have each searchable value (`coverage`), a profile of the matched files (tempo and loudness range, most common keys and tags) and the first five matches. Reading does not spend tokens. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "view_not_found"
        ],
        "parameters": [
          {
            "name": "viewId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "description": "The `id` of one of your saved views."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The summary.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "view_id": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "name": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "track_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Tracks the view matches."
                            },
                            "file_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Files the view matches."
                            },
                            "coverage": {
                              "type": "object",
                              "properties": {
                                "total_library_size": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "Files in the scope of the view before its filters."
                                },
                                "indexed": {
                                  "type": "object",
                                  "propertyNames": {
                                    "type": "string"
                                  },
                                  "additionalProperties": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  "description": "Per searchable value, the number of files that have it."
                                }
                              },
                              "required": [
                                "total_library_size",
                                "indexed"
                              ],
                              "additionalProperties": false
                            },
                            "profile": {
                              "type": "object",
                              "properties": {
                                "bpm": {
                                  "anyOf": [
                                    {
                                      "type": "object",
                                      "properties": {
                                        "min": {
                                          "type": "number"
                                        },
                                        "max": {
                                          "type": "number"
                                        }
                                      },
                                      "required": [
                                        "min",
                                        "max"
                                      ],
                                      "additionalProperties": false
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "top_keys": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "key": {
                                        "type": "string"
                                      },
                                      "pct": {
                                        "type": "number"
                                      }
                                    },
                                    "required": [
                                      "key",
                                      "pct"
                                    ],
                                    "additionalProperties": false
                                  },
                                  "description": "The most common keys; `pct` is the whole-number share of matched files that have a key."
                                },
                                "loudness": {
                                  "anyOf": [
                                    {
                                      "type": "object",
                                      "properties": {
                                        "min": {
                                          "type": "number"
                                        },
                                        "max": {
                                          "type": "number"
                                        }
                                      },
                                      "required": [
                                        "min",
                                        "max"
                                      ],
                                      "additionalProperties": false
                                    },
                                    {
                                      "type": "null"
                                    }
                                  ]
                                },
                                "top_tags": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "tag": {
                                        "type": "string"
                                      },
                                      "count": {
                                        "type": "integer",
                                        "minimum": -9007199254740991,
                                        "maximum": 9007199254740991
                                      }
                                    },
                                    "required": [
                                      "tag",
                                      "count"
                                    ],
                                    "additionalProperties": false
                                  }
                                }
                              },
                              "required": [
                                "bpm",
                                "top_keys",
                                "loudness",
                                "top_tags"
                              ],
                              "additionalProperties": false
                            },
                            "top": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "audio_id": {
                                    "type": "string"
                                  },
                                  "name": {
                                    "type": "string"
                                  },
                                  "facts": {
                                    "type": "object",
                                    "propertyNames": {
                                      "type": "string"
                                    },
                                    "additionalProperties": {},
                                    "description": "The values the view sorts or filters by, for this file."
                                  }
                                },
                                "required": [
                                  "audio_id",
                                  "name",
                                  "facts"
                                ],
                                "additionalProperties": false
                              },
                              "description": "The first five matches."
                            }
                          },
                          "required": [
                            "view_id",
                            "name",
                            "track_count",
                            "file_count",
                            "coverage",
                            "profile",
                            "top"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "view_id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                    "name": "Fast tracks",
                    "track_count": 12,
                    "file_count": 15,
                    "coverage": {
                      "total_library_size": 42,
                      "indexed": {
                        "bpm": 17,
                        "key_label": 9
                      }
                    },
                    "profile": {
                      "bpm": {
                        "min": 90,
                        "max": 174
                      },
                      "top_keys": [
                        {
                          "key": "A minor",
                          "pct": 40
                        }
                      ],
                      "loudness": {
                        "min": -18,
                        "max": -6
                      },
                      "top_tags": [
                        {
                          "tag": "morning",
                          "count": 5
                        }
                      ]
                    },
                    "top": [
                      {
                        "audio_id": "audio_bbb14949dc19",
                        "name": "morning-session.wav",
                        "facts": {
                          "bpm": 128
                        }
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No view with this id in your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "view_not_found",
                    "message": "View not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#view_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The summary could not be computed. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/audio/views/by-tool-call/{toolCallId}": {
      "get": {
        "operationId": "get_view_by_tool_call",
        "tags": [
          "Saved views"
        ],
        "summary": "Find the view a conversation step built",
        "description": "Returns the view the assistant built in a given step of a conversation, so a client can show it again. Both `toolCallId` (the step) and the `conversation_id` query parameter are needed. A step that built no view of yours returns 404 `view_not_found`. Counts against the hourly account request budget. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "view_not_found"
        ],
        "parameters": [
          {
            "name": "toolCallId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Identifier of the conversation step."
            }
          },
          {
            "name": "conversation_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation the step belongs to."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The view.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                              "description": "Identifier of the view."
                            },
                            "name": {
                              "type": "string"
                            },
                            "origin": {
                              "type": "string",
                              "enum": [
                                "user",
                                "chat"
                              ],
                              "description": "`user` for views you saved, `chat` for views the assistant built in a conversation until you keep them."
                            },
                            "source_conversation_id": {
                              "description": "For a `chat` view, the conversation it was built in.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "source_tool_call_id": {
                              "description": "For a `chat` view, the step of that conversation that built it.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "definition": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The definition in the current (version 2) form, as stored."
                            },
                            "dropped": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              },
                              "description": "Parts of an older stored definition that the current form no longer supports and that were left out."
                            },
                            "config": {
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {},
                              "description": "The same definition in the older (version 1) form, kept for existing clients."
                            },
                            "created_at": {
                              "type": "string"
                            },
                            "updated_at": {
                              "type": "string"
                            },
                            "last_opened_at": {
                              "description": "When the view was last read with the get route.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "origin",
                            "source_conversation_id",
                            "source_tool_call_id",
                            "definition",
                            "dropped",
                            "config",
                            "created_at",
                            "updated_at",
                            "last_opened_at"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "id": "8a1c3e5f-7b9d-4f20-a4c6-e8f0123456ab",
                    "name": "Fast tracks",
                    "origin": "chat",
                    "source_conversation_id": "c0e1d2f3-0000-4000-8000-000000000000",
                    "source_tool_call_id": "call_1",
                    "definition": {
                      "version": 2,
                      "filters": {},
                      "sort": [],
                      "columns": []
                    },
                    "dropped": [],
                    "config": {},
                    "created_at": "2026-10-20T11:53:45.938Z",
                    "updated_at": "2026-10-20T11:53:45.938Z",
                    "last_opened_at": null
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The `conversation_id` query parameter is missing or blank.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_conversation_id",
                    "message": "conversation_id is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_conversation_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No view of yours was built by this step.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "view_not_found",
                    "message": "View not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#view_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "The view could not be read. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "db_unavailable",
                    "message": "Database not available",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#db_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/batch": {
      "post": {
        "operationId": "submit_batch",
        "tags": [
          "Batch"
        ],
        "summary": "Submit a batch",
        "description": "Runs one recipe over up to 500 audio files in the background. The call returns `202` at once with a `batch_id`; follow progress with the status route or receive a `batch_completed` webhook when the batch ends. Batches are available on paid accounts only; a free-account key receives 403 `batch_paid_only`.\n\nEach file is charged like a single run of the recipe: 1 token per second of audio at the base rate ($0.10 per minute), and recipes can carry their own per-step rates. Use the estimate route first to see the cost. The account needs a token balance, or auto-recharge turned on, otherwise the call returns 402 `insufficient_balance`.\n\nSend an `Idempotency-Key` header to make retries safe: the same key with the same request returns the original `batch_id` (with `meta.idempotent: true`) and starts nothing new; the same key with a different request returns 409 `idempotency_key_reused`.\n\nCapped at 10 requests per minute per account on top of the hourly account budget.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "tokens",
          "rule": "Charged per file when its run finishes: 1 token per second of audio at the base rate of $0.10 per minute. Recipes can use per-step rates, so check the estimate route first."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "batch_paid_only",
          "batch_too_large",
          "idempotency_key_reused",
          "insufficient_balance",
          "invalid_audio_url",
          "invalid_auth_format",
          "invalid_idempotency_key",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_message",
          "invalid_metadata",
          "invalid_name",
          "invalid_recipe_id",
          "invalid_webhook_url",
          "media_not_owned",
          "message_too_long",
          "metadata_too_large",
          "missing_api_key",
          "missing_audio_urls",
          "missing_auth",
          "missing_recipe_id",
          "name_too_long",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "webhook_url_too_large",
          "webhook_validation_unavailable",
          "workflow_create_failed"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "description": "1 to 255 visible ASCII characters. Makes the submit safe to retry.",
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The recipe to run on every file, for example `rec_1005_cat_spectral`."
                  },
                  "audio_urls": {
                    "minItems": 1,
                    "maxItems": 500,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "HTTPS URLs of the audio files to process, 1 to 500 entries."
                  },
                  "name": {
                    "description": "A label for the batch, up to 32000 characters. Returned as `name` by the list route.",
                    "type": "string",
                    "maxLength": 32000
                  },
                  "message": {
                    "description": "Older alias of `name`. When both are sent, `name` wins.",
                    "type": "string",
                    "maxLength": 32000
                  },
                  "webhook_url": {
                    "description": "Where to POST the `batch_completed` event. Must be an https URL that resolves to a public address, at most 4096 bytes.",
                    "type": "string"
                  },
                  "metadata": {
                    "description": "Free-form JSON object kept with the batch, at most 8192 bytes when serialized. Keys are limited to 64 characters and string values to 2048.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "recipe_id",
                  "audio_urls"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe_id": "rec_1005_cat_spectral",
                "audio_urls": [
                  "https://example.com/track-1.wav",
                  "https://example.com/track-2.wav"
                ],
                "name": "Morning session",
                "webhook_url": "https://example.com/hooks/scarleta"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. The batch is queued. `meta` has no `request_id`; the `X-Request-ID` header carries the request id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "batch_id": {
                          "type": "string",
                          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                          "description": "Identifier of the new batch."
                        },
                        "status": {
                          "type": "string",
                          "const": "IN_QUEUE"
                        }
                      },
                      "required": [
                        "batch_id",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": "string",
                          "description": "Informational: which engine accepted the batch. Do not branch on it."
                        },
                        "idempotent": {
                          "description": "Present and true when this response replays an earlier submit with the same `Idempotency-Key`.",
                          "type": "boolean"
                        },
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "source"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                    "status": "IN_QUEUE"
                  },
                  "meta": {
                    "source": "workflow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON, a missing or empty `audio_urls` or `recipe_id`, an unacceptable audio or webhook URL, a label or metadata that breaks its limits, or a malformed `Idempotency-Key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_urls",
                    "message": "audio_urls must be a non-empty array",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_urls"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "402": {
            "description": "No token balance and no auto-recharge.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "insufficient_balance",
                    "message": "Your team has no token balance and auto-recharge is not active. Top up to submit batches.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#insufficient_balance"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key belongs to a free account, or a file is not owned by your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_paid_only",
                    "message": "Batch processing is available on paid plans only.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_paid_only"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The recipe does not exist or is not visible to your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe 'rec_9999_unknown' not found.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The `Idempotency-Key` was used before with a different request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "idempotency_key_reused",
                    "message": "This Idempotency-Key was already used with a different batch request.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#idempotency_key_reused"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The metadata is over 16384 bytes, or the `webhook_url` is over 4096 bytes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "metadata_too_large",
                    "message": "metadata serialized JSON exceeds 16384 bytes",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#metadata_too_large"
                  }
                }
              }
            }
          },
          "422": {
            "description": "More than 500 files.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_too_large",
                    "message": "audio_urls must contain at most 500 entries (got 501)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The batch could not be started. Retry with the same `Idempotency-Key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "workflow_create_failed",
                    "message": "Batch could not be started; please retry.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#workflow_create_failed"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/batch/{batch_id}": {
      "delete": {
        "operationId": "cancel_batch",
        "tags": [
          "Batch"
        ],
        "summary": "Cancel a batch",
        "description": "Stops a batch that is still running: items that have not finished are cancelled and their work is stopped. Items that already finished keep their results and their charges. A batch that has already reached a final state returns 409 `batch_already_final`. Capped at 10 requests per minute per account on top of the hourly account budget.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. Items that already finished stay charged."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "batch_already_final",
          "batch_not_found",
          "invalid_auth_format",
          "invalid_batch_id",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
              "description": "The `batch_id` returned when the batch was submitted. Batches submitted today get a UUID; an older batch can carry an id of the form `batch_<digits>_<hex>`, which is accepted too."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "batch_id": {
                          "type": "string",
                          "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
                          "description": "Identifier of the batch."
                        },
                        "cancelled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items this call cancelled."
                        }
                      },
                      "required": [
                        "message",
                        "batch_id",
                        "cancelled"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "message": "Batch b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7 cancellation requested. 2 items cancelled.",
                    "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                    "cancelled": 2
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`batch_id` is neither a UUID nor a legacy `batch_<digits>_<hex>` id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_batch_id",
                    "message": "batch_id must be a valid batch id",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_batch_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No batch with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_not_found",
                    "message": "Batch b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The batch had already reached a final state. `error.details.status` holds that state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_already_final",
                    "message": "Batch b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7 already completed",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_already_final"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_batch",
        "tags": [
          "Batch"
        ],
        "summary": "Get a batch",
        "description": "Returns the live state of one batch: its status, per-state item counters and progress. A batch is final when `status` is `completed`, `failed`, `partial` or `cancelled`. Only batches created by your own account can be read; any other id returns 404. Capped at 600 requests per minute per account on top of the hourly account budget.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "batch_not_found",
          "invalid_auth_format",
          "invalid_batch_id",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
              "description": "The `batch_id` returned when the batch was submitted. Batches submitted today get a UUID; an older batch can carry an id of the form `batch_<digits>_<hex>`, which is accepted too."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string",
                          "description": "Human-readable progress line."
                        },
                        "batch_id": {
                          "type": "string",
                          "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
                          "description": "Identifier of the batch."
                        },
                        "status": {
                          "anyOf": [
                            {
                              "type": "string",
                              "enum": [
                                "processing",
                                "completed",
                                "failed",
                                "partial",
                                "cancelled"
                              ]
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Current state. `processing` until every item is final."
                        },
                        "error": {
                          "description": "Summary of why the batch failed, when it did.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "total": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items in the batch."
                        },
                        "completed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items that finished successfully."
                        },
                        "failed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items that failed."
                        },
                        "cancelled": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items cancelled before they finished."
                        },
                        "pending": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items waiting to start."
                        },
                        "processing": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items running now."
                        },
                        "percent_complete": {
                          "type": "number",
                          "description": "`completed` divided by `total`, as a percentage with one decimal."
                        },
                        "actual_cost": {
                          "type": "number",
                          "description": "Tokens charged so far for the batch."
                        },
                        "estimated_cost": {
                          "description": "Estimate recorded at submit, when there was one.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "created_at": {
                          "description": "Milliseconds since the Unix epoch.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "completed_at": {
                          "description": "Milliseconds since the Unix epoch.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "webhook_delivery_status": {
                          "description": "State of the `batch_completed` delivery: `in_progress`, `delivered`, `failed`, `skipped` (no `webhook_url`, or the batch was cancelled, which sends no webhook) or `unconfirmed`; null before the batch ends. It describes only the per-request `webhook_url`: addresses registered with `POST /v1/webhooks` are retried the same way, but their outcome is not shown in this field.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "webhook_last_attempt_at": {
                          "description": "Milliseconds since the Unix epoch.",
                          "type": [
                            "number",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "message",
                        "batch_id",
                        "status",
                        "error",
                        "total",
                        "completed",
                        "failed",
                        "cancelled",
                        "pending",
                        "processing",
                        "percent_complete",
                        "actual_cost",
                        "estimated_cost",
                        "created_at",
                        "completed_at",
                        "webhook_delivery_status",
                        "webhook_last_attempt_at"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "message": "Batch b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7: 100.0% complete (2/2)",
                    "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                    "status": "completed",
                    "error": null,
                    "total": 2,
                    "completed": 2,
                    "failed": 0,
                    "cancelled": 0,
                    "pending": 0,
                    "processing": 0,
                    "percent_complete": 100,
                    "actual_cost": 40,
                    "estimated_cost": null,
                    "created_at": 1791333870854,
                    "completed_at": 1791333895009,
                    "webhook_delivery_status": "delivered",
                    "webhook_last_attempt_at": 1791333895229
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`batch_id` is neither a UUID nor a legacy `batch_<digits>_<hex>` id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_batch_id",
                    "message": "batch_id must be a valid batch id",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_batch_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No batch with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_not_found",
                    "message": "Batch b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/batch/{batch_id}/results": {
      "get": {
        "operationId": "get_batch_results",
        "tags": [
          "Batch"
        ],
        "summary": "Get batch results",
        "description": "Returns the per-file results of a batch, 50 items per page by default. Page with `offset` and `limit` while `has_more` is true. The keys inside each `raw_results` depend on the recipe that ran. Capped at 600 requests per minute per account on top of the hourly account budget.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "batch_not_found",
          "invalid_auth_format",
          "invalid_batch_id",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
              "description": "The `batch_id` returned when the batch was submitted. Batches submitted today get a UUID; an older batch can carry an id of the form `batch_<digits>_<hex>`, which is accepted too."
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Items to skip. Defaults to 0.",
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Items per page. Defaults to 50; values above 100 are clamped to 100.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "batch_id": {
                          "type": "string",
                          "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
                          "description": "Identifier of the batch."
                        },
                        "items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "item_id": {
                                "type": "string",
                                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                                "description": "Identifier of this item attempt."
                              },
                              "item_index": {
                                "anyOf": [
                                  {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Position of the file in `audio_urls`, starting at 0."
                              },
                              "audio_url": {
                                "type": "string",
                                "description": "The file this item processed."
                              },
                              "display_name": {
                                "description": "The file's library name, when it is in your library; null otherwise.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "reference_url": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "pending",
                                  "processing",
                                  "completed",
                                  "failed",
                                  "cancelled"
                                ]
                              },
                              "raw_results": {
                                "anyOf": [
                                  {
                                    "type": "object",
                                    "propertyNames": {
                                      "type": "string"
                                    },
                                    "additionalProperties": {}
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Output of the recipe for this file. The keys depend on the recipe that ran."
                              },
                              "error": {
                                "description": "Why the item failed, when it did.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "cost": {
                                "description": "Tokens charged for this item.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "duration_ms": {
                                "description": "How long the item took, in milliseconds.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "retry_count": {
                                "anyOf": [
                                  {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "How many times this item has been retried."
                              }
                            },
                            "required": [
                              "item_id",
                              "item_index",
                              "audio_url",
                              "reference_url",
                              "status",
                              "raw_results",
                              "error",
                              "cost",
                              "duration_ms",
                              "retry_count"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "total": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items in the batch."
                        },
                        "offset": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "limit": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "has_more": {
                          "type": "boolean",
                          "description": "True when another page follows."
                        },
                        "filters_applied": {
                          "type": "object",
                          "properties": {
                            "status_filter": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "status_filter"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "message",
                        "batch_id",
                        "items",
                        "total",
                        "offset",
                        "limit",
                        "has_more",
                        "filters_applied"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "message": "Returning 1 items (offset 0)",
                    "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                    "items": [
                      {
                        "item_id": "3f2a9c1e-7b64-4c0d-8e21-5a6b7c8d9e0f",
                        "item_index": 0,
                        "audio_url": "https://example.com/track-1.wav",
                        "reference_url": null,
                        "status": "completed",
                        "raw_results": {
                          "recipe_id": "rec_1005_cat_spectral",
                          "status": "COMPLETED"
                        },
                        "error": null,
                        "cost": 20,
                        "duration_ms": 8120,
                        "retry_count": 0
                      }
                    ],
                    "total": 2,
                    "offset": 0,
                    "limit": 50,
                    "has_more": true,
                    "filters_applied": {
                      "status_filter": "all"
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`batch_id` is neither a UUID nor a legacy `batch_<digits>_<hex>` id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_batch_id",
                    "message": "batch_id must be a valid batch id",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_batch_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No batch with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_not_found",
                    "message": "Batch b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/batch/{batch_id}/retry": {
      "post": {
        "operationId": "retry_batch",
        "tags": [
          "Batch"
        ],
        "summary": "Retry failed items of a batch",
        "description": "Re-queues the items of a finished batch that failed, as new attempts, and reopens the batch. Only a batch whose status is `failed`, `partial` or `cancelled` can be retried; any other status returns 409 `batch_not_retryable`. An item that has already been retried `max_retries` times is left as failed and counted in `permanently_failed`. The body is optional. Capped at 10 requests per minute per account on top of the hourly account budget.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "tokens",
          "rule": "Re-queued items are charged again when they finish, at the same per-file rate as the original run."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "batch_not_found",
          "batch_not_retryable",
          "batch_recipe_missing",
          "batch_tenant_missing",
          "invalid_auth_format",
          "invalid_batch_id",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_max_retries",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "workflow_create_failed"
        ],
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
              "description": "The `batch_id` returned when the batch was submitted. Batches submitted today get a UUID; an older batch can carry an id of the form `batch_<digits>_<hex>`, which is accepted too."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "max_retries": {
                    "description": "Highest number of times one item may be retried, 1 to 10. Defaults to 2.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "max_retries": 2
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "batch_id": {
                          "type": "string",
                          "pattern": "(?:^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$)|(?:^batch_\\d{10,16}_[0-9a-f]{8}$)",
                          "description": "Identifier of the batch."
                        },
                        "requeued": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Items put back in the queue."
                        },
                        "permanently_failed": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Failed items that were not re-queued because they reached `max_retries`."
                        },
                        "superseded": {
                          "description": "True when a cancel or another retry changed the batch while this call ran, so nothing was started.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "message",
                        "batch_id",
                        "requeued",
                        "permanently_failed"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "message": "Retry results: 1 items requeued, 0 permanently failed (already at 2 retries)",
                    "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                    "requeued": 1,
                    "permanently_failed": 0
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not a JSON object, `max_retries` is not an integer in range, or `batch_id` is neither a UUID nor a legacy `batch_<digits>_<hex>` id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_max_retries",
                    "message": "max_retries must be an integer between 1 and 10",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_max_retries"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No batch with this id exists for your account. If the batch exists but its recipe was deleted, the code is `not_found` instead (past results are kept).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_not_found",
                    "message": "Batch b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The batch is still running or already completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_not_retryable",
                    "message": "Batch is not in a retryable terminal state (current: completed)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_not_retryable"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The retry could not be started.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "workflow_create_failed",
                    "message": "Retry could not be started; please retry.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#workflow_create_failed"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/batch/estimate": {
      "post": {
        "operationId": "estimate_batch",
        "tags": [
          "Batch"
        ],
        "summary": "Estimate the cost of a batch",
        "description": "Returns the token cost of running a recipe over a list of files, per file and in total, without starting anything and without charging. Batches are available on paid accounts only; a free-account key receives 403 `batch_paid_only`. Accepts the same `recipe_id` and `audio_urls` as submit, at most 500 files. A file whose length cannot be read contributes 0 and reports `duration_seconds: null`. Capped at 600 requests per minute per account on top of the hourly account budget.",
        "x-scarleta-tier": "paid",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge: estimating never spends tokens."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "batch_paid_only",
          "batch_too_large",
          "invalid_audio_url",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_audio_urls",
          "missing_auth",
          "missing_recipe_id",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_not_found",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The recipe to run on every file, for example `rec_1005_cat_spectral`."
                  },
                  "audio_urls": {
                    "minItems": 1,
                    "maxItems": 500,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "description": "HTTPS URLs of the audio files to process, 1 to 500 entries."
                  }
                },
                "required": [
                  "recipe_id",
                  "audio_urls"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe_id": "rec_1005_cat_spectral",
                "audio_urls": [
                  "https://example.com/track-1.wav",
                  "https://example.com/track-2.wav"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "recipe_id": {
                          "type": "string"
                        },
                        "total_cost": {
                          "type": "number",
                          "description": "Tokens the whole batch would cost."
                        },
                        "file_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "per_file": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "audio_url": {
                                "type": "string"
                              },
                              "duration_seconds": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "cost": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "audio_url",
                              "duration_seconds",
                              "cost"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "message",
                        "recipe_id",
                        "total_cost",
                        "file_count",
                        "per_file"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "message": "Estimated cost for 2 file(s) with recipe rec_1005_cat_spectral",
                    "recipe_id": "rec_1005_cat_spectral",
                    "total_cost": 40,
                    "file_count": 2,
                    "per_file": [
                      {
                        "audio_url": "https://example.com/track-1.wav",
                        "duration_seconds": 4,
                        "cost": 20
                      },
                      {
                        "audio_url": "https://example.com/track-2.wav",
                        "duration_seconds": 3.2,
                        "cost": 20
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON, `recipe_id` or `audio_urls` is missing, or a URL is not an acceptable public audio URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_urls",
                    "message": "audio_urls must be a non-empty array",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_urls"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The key belongs to a free account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_paid_only",
                    "message": "Batch processing is available on paid plans only.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_paid_only"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The recipe does not exist or is not visible to your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "recipe_not_found",
                    "message": "Recipe rec_9999_unknown not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#recipe_not_found"
                  }
                }
              }
            }
          },
          "422": {
            "description": "More than 500 files.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "batch_too_large",
                    "message": "audio_urls must contain at most 500 entries (got 501)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#batch_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/batches": {
      "get": {
        "operationId": "list_batches",
        "tags": [
          "Batch"
        ],
        "summary": "List batches",
        "description": "Returns your most recent batches, newest first, each with its item counters and the tokens charged so far. Page past the first `limit` batches with `offset`; `total` is how many batches you have in all. Returns an empty list for a free account, which cannot create batches. Capped at 600 requests per minute per account on top of the hourly account budget.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Rows to return. Defaults to 50; values above 100 are clamped to 100.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Batches to skip, newest first. Defaults to 0; a negative or non-numeric value is read as 0.",
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "batches": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "batch_id": {
                                "type": "string",
                                "description": "Identifier of the batch. Batches submitted today get a UUID. An older batch can carry an id of the form `batch_<digits>_<hex>`: it is listed here and every batch route accepts it."
                              },
                              "status": {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "enum": [
                                      "processing",
                                      "completed",
                                      "failed",
                                      "partial",
                                      "cancelled"
                                    ]
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Current state of the batch."
                              },
                              "recipe_id": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "name": {
                                "description": "The label sent as `name` (or `message`) at submit, if any.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "total_items": {
                                "anyOf": [
                                  {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  {
                                    "type": "null"
                                  }
                                ]
                              },
                              "completed_items": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Items that finished successfully."
                              },
                              "failed_items": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Items that failed."
                              },
                              "cancelled_items": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Items cancelled before they finished."
                              },
                              "created_at": {
                                "description": "When the batch was submitted, in milliseconds since the Unix epoch.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "completed_at": {
                                "description": "When the batch reached a final state, in milliseconds since the Unix epoch.",
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "actual_cost": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991,
                                "description": "Tokens charged so far for this batch's items; 0 when nothing was charged."
                              }
                            },
                            "required": [
                              "batch_id",
                              "status",
                              "recipe_id",
                              "name",
                              "total_items",
                              "completed_items",
                              "failed_items",
                              "cancelled_items",
                              "created_at",
                              "completed_at",
                              "actual_cost"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "total": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "How many batches you have in all, which can be more than the page returned. On a page past the end it is the offset you asked for."
                        },
                        "offset": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "The offset this page starts at."
                        }
                      },
                      "required": [
                        "message",
                        "batches",
                        "count",
                        "total",
                        "offset"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "message": "Returning 1 batches",
                    "batches": [
                      {
                        "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                        "status": "completed",
                        "recipe_id": "rec_1005_cat_spectral",
                        "name": "Morning session",
                        "total_items": 2,
                        "completed_items": 2,
                        "failed_items": 0,
                        "cancelled_items": 0,
                        "created_at": 1791333870854,
                        "completed_at": 1791333895009,
                        "actual_cost": 120
                      }
                    ],
                    "count": 1,
                    "total": 1,
                    "offset": 0
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/chat": {
      "post": {
        "operationId": "send_chat_message",
        "tags": [
          "Chat"
        ],
        "summary": "Send a chat message",
        "description": "Sends one message to the Scarleta assistant and starts a turn in the background. The call returns `202` at once; it does not contain the reply. Follow the turn with `GET /v1/conversations/{conversation_id}/status` until `active_turn_workflow_id` is null, then read the reply with `GET /v1/conversations/{conversation_id}`. `POST /v1/conversations/{conversation_id}/cancel` stops a turn that is running.\n\nLeave out `conversation_id` to start a new conversation, or send the id of one of your conversations to continue it; the assistant remembers the earlier turns. Attach audio with `audio_url` or with `media`; the assistant decides which analyses to run, and those analyses are charged like any other. Only one turn can run in a conversation at a time: a second message sent while a turn is active returns 409 `turn_in_progress`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "tokens",
          "rule": "Free for a message that needs no analysis. When the assistant runs an analysis on your audio, that analysis is charged per second of audio like the equivalent single call."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "chat_failed",
          "conversation_do_error",
          "conversation_not_found",
          "conversation_ownership_unavailable",
          "invalid_audio_url",
          "invalid_auth_format",
          "invalid_conversation_id",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "media_not_owned",
          "missing_api_key",
          "missing_auth",
          "missing_prompt",
          "payload_too_large",
          "prompt_too_long",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "service_misconfigured",
          "too_many_media",
          "turn_in_progress",
          "turn_workflow_create_failed",
          "turn_workflow_precondition_missing",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "prompt": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32768,
                    "description": "Your message, at most 32768 characters."
                  },
                  "audio_url": {
                    "description": "A file to discuss. Shorthand for a single `media` item.",
                    "type": "string",
                    "maxLength": 4096
                  },
                  "media": {
                    "description": "Files to attach, at most 2. Takes precedence over `audio_url`.",
                    "maxItems": 2,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "minLength": 1,
                          "description": "Where to fetch the file: a public `http` or `https` URL, or a file in your own library."
                        },
                        "type": {
                          "description": "Kind of file. Detected from the URL when absent.",
                          "type": "string",
                          "enum": [
                            "audio",
                            "video"
                          ]
                        },
                        "name": {
                          "description": "Display name shown with the file in the conversation.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "region": {
                          "description": "Seconds to analyze, `{ start, end }` with `end` greater than `start`. The whole file when absent.",
                          "anyOf": [
                            {
                              "type": "object",
                              "properties": {
                                "start": {
                                  "type": "number",
                                  "minimum": 0
                                },
                                "end": {
                                  "type": "number"
                                }
                              },
                              "required": [
                                "start",
                                "end"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "null"
                            }
                          ]
                        },
                        "mediaType": {
                          "description": "MIME type of the file, for example `audio/wav`.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "durationS": {
                          "description": "Length in seconds, shown in the conversation. Display only: billing always uses the measured length.",
                          "anyOf": [
                            {
                              "type": "number",
                              "minimum": 0
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "url"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "conversation_id": {
                    "description": "UUID of one of your conversations to continue. A new conversation is created when absent.",
                    "type": "string"
                  }
                },
                "required": [
                  "prompt"
                ],
                "additionalProperties": false
              },
              "example": {
                "prompt": "What key is this track in, and does it drift?",
                "audio_url": "https://example.com/track-1.wav"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted. The turn is running. Carries `X-Conversation-ID` and `X-Turn-Workflow-ID` headers with the same values as the body,.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "status": {
                              "type": "string",
                              "const": "IN_PROGRESS"
                            },
                            "workflow": {
                              "type": "string",
                              "const": "turn-workflow"
                            },
                            "conversation_id": {
                              "type": "string",
                              "description": "The conversation the message belongs to. Use it for follow-up messages and to read the reply."
                            },
                            "turn_workflow_id": {
                              "type": "string",
                              "description": "Identifier of this turn."
                            },
                            "workflow_instance_id": {
                              "type": "string",
                              "description": "Same value as `turn_workflow_id`."
                            },
                            "prompt": {
                              "type": "string",
                              "description": "Your message, echoed."
                            },
                            "audio_url": {
                              "description": "The file the turn works on: the one you attached, or the file already in the conversation.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "tenant_id": {
                              "description": "Your account identifier. Absent for free accounts.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "created_at": {
                              "type": "string",
                              "description": "ISO 8601 timestamp."
                            },
                            "response_time_ms": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "How long accepting the message took, in milliseconds."
                            },
                            "message": {
                              "type": "string",
                              "description": "Where to poll and how to cancel."
                            }
                          },
                          "required": [
                            "status",
                            "workflow",
                            "conversation_id",
                            "turn_workflow_id",
                            "workflow_instance_id",
                            "prompt",
                            "audio_url",
                            "created_at",
                            "response_time_ms",
                            "message"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "status": "IN_PROGRESS",
                    "workflow": "turn-workflow",
                    "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "turn_workflow_id": "turn_6e0ed523-72f5-464e-974c-9ae95fdc2a99",
                    "workflow_instance_id": "turn_6e0ed523-72f5-464e-974c-9ae95fdc2a99",
                    "prompt": "What key is this track in, and does it drift?",
                    "audio_url": "https://example.com/track-1.wav",
                    "tenant_id": "8c1d0b52-3f6a-4e0d-9d7b-2a41c5e90f13",
                    "created_at": "2026-10-21T03:41:37.272Z",
                    "response_time_ms": 2736,
                    "message": "Turn dispatched. Poll GET /v1/conversations/3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01/status for active-turn state. POST /v1/conversations/3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01/cancel to abort."
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON, a missing `prompt`, too many `media` items, an unacceptable URL, or a `conversation_id` that is not a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_prompt",
                    "message": "prompt is required in request body",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_prompt"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "A library file in `audio_url` or `media` is owned by another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "media_not_owned",
                    "message": "That file belongs to a different account.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#media_not_owned"
                  }
                }
              }
            }
          },
          "404": {
            "description": "`conversation_id` belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "conversation_not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#conversation_not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "A turn is already running in this conversation. `error.details.existing_workflow_id` names it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "turn_in_progress",
                    "message": "A turn is already active for conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "details": {
                      "existing_workflow_id": "turn_6e0ed523-72f5-464e-974c-9ae95fdc2a99"
                    },
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#turn_in_progress"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The prompt is over 32768 characters, or the whole request body is over 1048576 bytes (`payload_too_large`: send a shorter message and attach audio by URL).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "prompt_too_long",
                    "message": "prompt must not exceed 32768 characters",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#prompt_too_long"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The message could not be processed. Retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "chat_failed",
                    "message": "Failed to process chat request",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#chat_failed"
                  }
                }
              }
            }
          },
          "502": {
            "description": "The turn could not be started. Retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "turn_workflow_create_failed",
                    "message": "Failed to start chat turn. Please retry.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#turn_workflow_create_failed"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "conversation_ownership_unavailable",
                    "message": "Unable to verify conversation ownership, please retry",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#conversation_ownership_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/chat/{job_id}": {
      "get": {
        "operationId": "get_chat_job",
        "tags": [
          "Chat"
        ],
        "summary": "Get an assistant job",
        "description": "Reads a background job run by the assistant service by its `job_id`: a recipe run (see `POST /v1/recipe/execute`) or a job started by an older chat. Chat messages sent with `POST /v1/chat` answer with a conversation, not a job id; read their replies through the conversation routes. For a recipe run prefer `GET /v1/recipe/jobs/{job_id}`, which also reports the steps. `status` is `IN_QUEUE`, `IN_PROGRESS`, `COMPLETED`, `FAILED` or `TIMEOUT`; `response` holds the raw outcome once the job has ended. `prompt` and `model` appear only on jobs that stored them. Only your own jobs are returned.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_job_id",
          "invalid_key",
          "invalid_key_format",
          "job_not_found",
          "missing_api_key",
          "missing_auth",
          "missing_job_id",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "retrieval_failed",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The id of the job, for example `recipe_9f3a1c7e52b4`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "job_id": {
                          "type": "string",
                          "description": "Identifier of the job."
                        },
                        "status": {
                          "type": "string",
                          "description": "`IN_QUEUE`, `IN_PROGRESS`, `COMPLETED`, `FAILED` or `TIMEOUT`."
                        },
                        "workflow": {
                          "type": "string",
                          "const": "ai-agent",
                          "description": "Always `ai-agent`: only jobs of the assistant service are returned here."
                        },
                        "audio_url": {
                          "description": "The audio the job used.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "prompt": {
                          "description": "The message the job was started with, when it stored one.",
                          "type": "string"
                        },
                        "model": {
                          "description": "A model setting stored with the job, when it had one.",
                          "type": "string"
                        },
                        "response": {
                          "description": "The raw outcome of the job once it has ended (an object for a recipe run); null before."
                        },
                        "interpretation": {
                          "description": "A written interpretation of the outcome, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "conversation_id": {
                          "description": "The conversation the job is tied to, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "error": {
                          "description": "Why the job failed, or null."
                        },
                        "created_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        },
                        "completed_at": {
                          "description": "ISO 8601 timestamp of the end, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "job_id",
                        "status",
                        "workflow",
                        "audio_url",
                        "response",
                        "interpretation",
                        "conversation_id",
                        "error",
                        "created_at",
                        "completed_at"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "job_id": "recipe_9f3a1c7e52b4",
                    "status": "COMPLETED",
                    "workflow": "ai-agent",
                    "audio_url": "https://example.com/track-1.wav",
                    "response": {
                      "status": "success",
                      "step_count": 1
                    },
                    "interpretation": null,
                    "conversation_id": null,
                    "error": null,
                    "created_at": "2026-10-21T03:41:37.272Z",
                    "completed_at": "2026-10-21T03:41:56.630Z"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`job_id` has characters outside letters, digits and `_ . : -`, or is too long.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_job_id",
                    "message": "job_id must match ^[A-Za-z0-9_.:-]{1,128}$",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_job_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No assistant job with this id belongs to your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "job_not_found",
                    "message": "AI Agent job recipe_9f3a1c7e52b4 not found or access denied",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#job_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations": {
      "get": {
        "operationId": "list_conversations",
        "tags": [
          "Conversations"
        ],
        "summary": "List conversations",
        "description": "Returns your most recent conversations, newest activity first. Archived (deleted) conversations are not listed. `meta.count` is the number of conversations returned.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "list_failed",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Conversations to return. Defaults to 20; values above 100 are clamped to 100, and a value that is not a positive number falls back to the default.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Identifier of the conversation."
                          },
                          "audio_url": {
                            "type": "string",
                            "description": "The audio file the conversation is about; an empty string when none was attached."
                          },
                          "playback_url": {
                            "description": "A playable link for the audio; empty (or null) when no audio was attached.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "title": {
                            "description": "The conversation title.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "message_count": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "Messages in the conversation."
                          },
                          "status": {
                            "type": "string",
                            "description": "The conversation state; `active` for a conversation in use."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "ISO 8601 timestamp."
                          },
                          "updated_at": {
                            "type": "string",
                            "description": "ISO 8601 timestamp."
                          },
                          "last_message_at": {
                            "description": "ISO 8601 timestamp of the newest message, or null when there is none.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "is_unread": {
                            "type": "boolean",
                            "description": "True when the conversation has an assistant reply you have not marked read."
                          }
                        },
                        "required": [
                          "id",
                          "audio_url",
                          "playback_url",
                          "title",
                          "message_count",
                          "status",
                          "created_at",
                          "updated_at",
                          "last_message_at",
                          "is_unread"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Conversations in `data`."
                        }
                      },
                      "required": [
                        "request_id",
                        "count"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                      "audio_url": "",
                      "playback_url": "",
                      "title": "Mix review",
                      "message_count": 2,
                      "status": "active",
                      "created_at": "2026-10-21T03:41:37.272Z",
                      "updated_at": "2026-10-21T03:41:56.630Z",
                      "last_message_at": "2026-10-21T03:41:56.630Z",
                      "is_unread": false
                    }
                  ],
                  "meta": {
                    "request_id": "0cf07e8d-6f86-47b3-8a35-35499a651571",
                    "count": 1
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_conversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Create a conversation",
        "description": "Creates an empty conversation about one audio file and returns it with `201`. You do not need this call to chat: `POST /v1/chat` creates a conversation by itself when you leave out `conversation_id`. Use this route to prepare a conversation before the first message. `audio_url` must be a public `http` or `https` URL, or a file in your own library.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "create_failed",
          "invalid_audio_url",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_title",
          "media_not_owned",
          "missing_api_key",
          "missing_audio_url",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "title_too_long",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096,
                    "description": "The audio file the conversation is about, at most 4096 characters."
                  },
                  "title": {
                    "description": "A title, at most 200 characters. Derived from the first message when absent.",
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "required": [
                  "audio_url"
                ],
                "additionalProperties": false
              },
              "example": {
                "audio_url": "https://example.com/track-1.wav",
                "title": "Mix review"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created. `meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifier of the conversation."
                        },
                        "audio_url": {
                          "type": "string",
                          "description": "The audio file the conversation is about; an empty string when none was attached."
                        },
                        "playback_url": {
                          "description": "A playable link for the audio; empty (or null) when no audio was attached.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "title": {
                          "description": "The conversation title.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "message_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Messages in the conversation."
                        },
                        "status": {
                          "type": "string",
                          "description": "The conversation state; `active` for a conversation in use."
                        },
                        "created_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        }
                      },
                      "required": [
                        "id",
                        "audio_url",
                        "playback_url",
                        "title",
                        "message_count",
                        "status",
                        "created_at"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "audio_url": "https://example.com/track-1.wav",
                    "playback_url": "https://example.com/track-1.wav",
                    "title": "Mix review",
                    "message_count": 0,
                    "status": "active",
                    "created_at": "2026-10-21T03:41:37.272Z"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON, a missing `audio_url`, an unacceptable URL, or a title over the limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_audio_url",
                    "message": "audio_url is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_audio_url"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "`audio_url` points at a library file owned by another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "media_not_owned",
                    "message": "You don't have access to this audio.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#media_not_owned"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversation_id}": {
      "delete": {
        "operationId": "delete_conversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Delete a conversation",
        "description": "Deletes a conversation: it no longer appears in `GET /v1/conversations`, and if a chat turn is running in it, the turn is asked to stop. The response reports `status: \"archived\"`. The call is safe to repeat: deleting a conversation that is already deleted answers `200` again. Only a conversation that is not yours, or that does not exist, answers `404 not_found`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. Work a running turn already finished stays charged."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "delete_failed",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted. `meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "The conversation id."
                        },
                        "status": {
                          "type": "string",
                          "const": "archived",
                          "description": "Always `archived`: the conversation is gone from your lists."
                        }
                      },
                      "required": [
                        "id",
                        "status"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "status": "archived"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No conversation with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_conversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Get a conversation",
        "description": "Returns one conversation with its messages, oldest first. A customer key sees the newest 50 messages: when the conversation holds more, `truncated` is true and `total_available` says how many exist. Each message carries its text and role only. Internal reasoning, tool calls, tool results and model details are never returned. To read the assistant's reply to a chat message, poll `GET /v1/conversations/{conversation_id}/status` until no turn is active, then call this route.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "get_failed",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "truncated": {
                          "type": "boolean",
                          "description": "True when older messages were left out."
                        },
                        "returned_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Messages in `messages`."
                        },
                        "total_available": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Messages the conversation holds."
                        },
                        "running_recipe_jobs": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "job_id": {
                                "type": "string",
                                "description": "The running recipe job."
                              },
                              "recipe_id": {
                                "type": "string",
                                "description": "The recipe the job runs."
                              }
                            },
                            "required": [
                              "job_id",
                              "recipe_id"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Recipe runs of this conversation that are still queued or in progress. Empty when none."
                        },
                        "id": {
                          "type": "string",
                          "description": "Identifier of the conversation."
                        },
                        "audio_url": {
                          "type": "string",
                          "description": "The audio file the conversation is about; an empty string when none was attached."
                        },
                        "playback_url": {
                          "description": "A playable link for the audio; empty (or null) when no audio was attached.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "title": {
                          "description": "The conversation title.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "message_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Messages in the conversation."
                        },
                        "status": {
                          "type": "string",
                          "description": "The conversation state; `active` for a conversation in use."
                        },
                        "created_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        },
                        "updated_at": {
                          "type": "string",
                          "description": "ISO 8601 timestamp."
                        },
                        "last_message_at": {
                          "description": "ISO 8601 timestamp of the newest message, or null when there is none.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "messages": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "role": {
                                "type": "string",
                                "enum": [
                                  "user",
                                  "assistant"
                                ],
                                "description": "Who wrote the message."
                              },
                              "content": {
                                "type": "string",
                                "description": "The message text."
                              },
                              "job_id": {
                                "description": "The analysis job the message belongs to, when there is one.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "created_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp."
                              },
                              "turn_index": {
                                "anyOf": [
                                  {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Which exchange of the conversation the message belongs to, from 1."
                              },
                              "message_index": {
                                "anyOf": [
                                  {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "Position of the message inside its exchange, from 0."
                              }
                            },
                            "required": [
                              "id",
                              "role",
                              "content",
                              "job_id",
                              "created_at",
                              "turn_index",
                              "message_index"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "truncated",
                        "returned_count",
                        "total_available",
                        "running_recipe_jobs",
                        "id",
                        "audio_url",
                        "playback_url",
                        "title",
                        "message_count",
                        "status",
                        "created_at",
                        "updated_at",
                        "last_message_at",
                        "messages"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "running_recipe_jobs": [],
                    "truncated": false,
                    "returned_count": 2,
                    "total_available": 2,
                    "id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "audio_url": "",
                    "playback_url": "",
                    "title": "Mix review",
                    "message_count": 2,
                    "status": "active",
                    "created_at": "2026-10-21T03:41:37.272Z",
                    "updated_at": "2026-10-21T03:41:56.630Z",
                    "last_message_at": "2026-10-21T03:41:56.630Z",
                    "messages": [
                      {
                        "id": "45190c94-a86b-4d7e-90da-281f0442864e",
                        "role": "user",
                        "content": "What key is this track in?",
                        "job_id": null,
                        "created_at": "2026-10-21T03:41:37.272Z",
                        "turn_index": 1,
                        "message_index": 0
                      },
                      {
                        "id": "425a18c9-5206-44a0-9d7b-e43941726f76",
                        "role": "assistant",
                        "content": "It sits in A minor.",
                        "job_id": null,
                        "created_at": "2026-10-21T03:41:56.630Z",
                        "turn_index": 1,
                        "message_index": 1
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No conversation with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversation_id}/cancel": {
      "post": {
        "operationId": "cancel_conversation_turn",
        "tags": [
          "Conversations"
        ],
        "summary": "Cancel the running turn",
        "description": "Asks the running chat turn of a conversation to stop. The call is safe to repeat: when no turn is running it answers `200` with `signaled: false` and `delivery: \"no_active_turn\"`. `delivery` says whether the stop signal reached the turn: `sent`, `send_failed` (your intent is recorded but the signal did not arrive), `binding_missing`, or `stale` (the turn you saw ended and a new one started before the signal could be sent, so nothing was cancelled; call again to cancel the new turn).",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. Work the turn already finished stays charged."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "conversation_do_error",
          "conversation_do_unbound",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The body is `{ data }` with no `meta` member; the request id is in the `X-Request-ID` header.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "conversation_id": {
                          "type": "string"
                        },
                        "signaled": {
                          "type": "boolean",
                          "description": "True when a stop signal was recorded for a running turn."
                        },
                        "target_workflow_id": {
                          "description": "The turn the signal was aimed at, or null when none was running.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "delivery": {
                          "type": "string",
                          "enum": [
                            "sent",
                            "send_failed",
                            "binding_missing",
                            "no_active_turn",
                            "stale"
                          ],
                          "description": "Outcome of delivering the signal."
                        }
                      },
                      "required": [
                        "conversation_id",
                        "signaled",
                        "target_workflow_id",
                        "delivery"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "signaled": true,
                    "target_workflow_id": "turn_6e0ed523-72f5-464e-974c-9ae95fdc2a99",
                    "delivery": "sent"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No conversation with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "502": {
            "description": "The conversation could not be reached right now. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "conversation_do_error",
                    "message": "Durable Object requestCancel failed: 500",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#conversation_do_error"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversation_id}/live-status": {
      "get": {
        "operationId": "get_conversation_live_status",
        "tags": [
          "Conversations"
        ],
        "summary": "Get the progress of a conversation",
        "description": "Reports how far a conversation has got: the newest exchange, whether an assistant reply arrived since `since_turn_index`, and, when you pass `job_id`, whether that job's result has been delivered into the conversation and the progress of its steps. Use it to show progress while a long job runs.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_job_id",
          "invalid_key",
          "invalid_key_format",
          "live_status_failed",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          },
          {
            "name": "job_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "A job started in this conversation, to get its step progress and delivery state.",
              "type": "string"
            }
          },
          {
            "name": "since_turn_index",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Only count assistant replies after this exchange number. A value that is not an integer is ignored.",
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "last_turn_index": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "Number of the newest exchange; null when the conversation has no messages."
                        },
                        "last_message_at": {
                          "description": "ISO 8601 timestamp of the newest message, or null.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "has_new_assistant_result": {
                          "type": "boolean",
                          "description": "True when an assistant reply exists after `since_turn_index`."
                        },
                        "job_delivered": {
                          "type": "boolean",
                          "description": "True when the result of `job_id` has been delivered into the conversation. False when `job_id` is absent."
                        },
                        "job_delivered_turn_index": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "The exchange the job result was delivered in, or null."
                        },
                        "progress": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "step_index": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              "label": {
                                "type": "string",
                                "description": "Plain-language name of the step."
                              },
                              "status": {
                                "type": "string",
                                "description": "State of the step."
                              }
                            },
                            "required": [
                              "step_index",
                              "label",
                              "status"
                            ],
                            "additionalProperties": false
                          },
                          "description": "Steps of `job_id`; empty when `job_id` is absent."
                        }
                      },
                      "required": [
                        "last_turn_index",
                        "last_message_at",
                        "has_new_assistant_result",
                        "job_delivered",
                        "job_delivered_turn_index",
                        "progress"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "last_turn_index": 1,
                    "last_message_at": "2026-10-21T03:41:56.630Z",
                    "has_new_assistant_result": true,
                    "job_delivered": false,
                    "job_delivered_turn_index": null,
                    "progress": []
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`job_id` has characters outside letters, digits and `_ . : -`, or is too long.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_job_id",
                    "message": "job_id must match ^[A-Za-z0-9_.:-]{1,128}$",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_job_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No conversation with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversation_id}/mark-read": {
      "put": {
        "operationId": "mark_conversation_read",
        "tags": [
          "Conversations"
        ],
        "summary": "Mark a conversation as read",
        "description": "Clears the unread marker: `is_unread` in `GET /v1/conversations` becomes false for this conversation. The call has no request body and is safe to repeat.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "mark_read_failed",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Marked read. `meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "const": true,
                          "description": "Always true."
                        }
                      },
                      "required": [
                        "ok"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "ok": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No conversation with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversation_id}/rewind": {
      "post": {
        "operationId": "rewind_conversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Rewind a conversation to an earlier message",
        "description": "Use this to edit a message you already sent. It deletes the message you name, together with its reply and every later exchange, so you can send the edited message again with `POST /v1/chat`. **The deleted messages cannot be recovered.** `user_message_ordinal` is the position of the message among the messages you sent, counted from 0. The optional guards make the call delete nothing when your copy of the thread differs from the stored one: `message_id` (the id of a message read from `GET /v1/conversations/{conversation_id}`) picks the target directly, `user_messages_after` must equal the number of your messages that come after the target, and `expected_text` must equal the target's stored text. When no message matches, the call answers `409 rewind_target_mismatch` and deletes nothing. While a turn is running in the conversation, or an analysis recipe is running for it, the call answers `409 turn_in_progress` and deletes nothing.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "conversation_do_error",
          "conversation_do_unbound",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "rewind_failed",
          "rewind_target_mismatch",
          "turn_in_progress",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user_message_ordinal": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991,
                    "description": "Position of the message to edit among the messages you sent, counted from 0."
                  },
                  "expected_text": {
                    "description": "The text the target message had when you read it. Nothing is deleted if the stored text differs.",
                    "type": "string"
                  },
                  "message_id": {
                    "description": "The id of the target message, at most 200 characters. When it names one of your messages it picks the target.",
                    "type": "string",
                    "maxLength": 200
                  },
                  "user_messages_after": {
                    "description": "How many of your messages come after the target. Nothing is deleted if it does not match.",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": [
                  "user_message_ordinal"
                ],
                "additionalProperties": false
              },
              "example": {
                "user_message_ordinal": 0
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rewound. `meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Messages deleted: the target, its reply and everything after."
                        }
                      },
                      "required": [
                        "deleted"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "deleted": 2
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A missing or malformed body, or a field of the wrong type (the message names the field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "user_message_ordinal must be a non-negative integer",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No conversation with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "No message matches `user_message_ordinal` and the guards (`turn_in_progress` when a turn is running). Nothing was deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rewind_target_mismatch",
                    "message": "The edited message does not match this conversation. Reload and try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rewind_target_mismatch"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "502": {
            "description": "The conversation could not be reached right now. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "conversation_do_error",
                    "message": "Durable Object tryAcquireTurn failed: 500",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#conversation_do_error"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversation_id}/status": {
      "get": {
        "operationId": "get_conversation_status",
        "tags": [
          "Conversations"
        ],
        "summary": "Get the active turn of a conversation",
        "description": "Tells you whether a chat turn is running in the conversation. After `POST /v1/chat`, poll this route every few seconds: `active_turn_workflow_id` is the id of the running turn and becomes null when the turn is over. Then read the reply with `GET /v1/conversations/{conversation_id}`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "conversation_do_error",
          "conversation_do_unbound",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The body is `{ data }` with no `meta` member; the request id is in the `X-Request-ID` header.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "conversation_id": {
                          "type": "string"
                        },
                        "active_turn_workflow_id": {
                          "description": "The running turn, or null when none is running.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "started_at": {
                          "description": "When the running turn started, in milliseconds since the Unix epoch; null when none is running.",
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "tenant_id": {
                          "description": "Your account identifier; null for free accounts.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "conversation_id",
                        "active_turn_workflow_id",
                        "started_at",
                        "tenant_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "active_turn_workflow_id": "turn_6e0ed523-72f5-464e-974c-9ae95fdc2a99",
                    "started_at": 1792554134633,
                    "tenant_id": "8c1d0b52-3f6a-4e0d-9d7b-2a41c5e90f13"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No conversation with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "502": {
            "description": "The conversation could not be read right now. Retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "conversation_do_error",
                    "message": "Durable Object getActiveTurn failed: 500",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#conversation_do_error"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/shares": {
      "get": {
        "operationId": "list_conversation_shares",
        "tags": [
          "Conversation shares"
        ],
        "summary": "List the share links of a conversation",
        "description": "Returns every share link you created for one conversation, newest first, including revoked and expired ones (check `active`). `meta.count` is the number of shares returned and `meta.active_count` how many of them currently work. A conversation that is not yours, or does not exist, answers `200` with an empty list.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "list_failed",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Identifier of the share. Use it to revoke the share."
                          },
                          "token": {
                            "type": "string",
                            "description": "The secret in the link. Anyone who has it can read the conversation until the share is revoked or expires."
                          },
                          "public_url": {
                            "type": "string",
                            "description": "Path of the public page, to append to `https://www.scarleta.ai`."
                          },
                          "conversation_id": {
                            "type": "string",
                            "description": "The shared conversation."
                          },
                          "expires_at": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When the link stops working, in milliseconds since the Unix epoch; null when it never expires."
                          },
                          "revoked_at": {
                            "anyOf": [
                              {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              },
                              {
                                "type": "null"
                              }
                            ],
                            "description": "When the share was revoked, in milliseconds since the Unix epoch; null while it is not revoked."
                          },
                          "created_at": {
                            "type": "integer",
                            "minimum": -9007199254740991,
                            "maximum": 9007199254740991,
                            "description": "When the share was created, in milliseconds since the Unix epoch."
                          },
                          "active": {
                            "type": "boolean",
                            "description": "True when the link currently works: not revoked and not expired."
                          }
                        },
                        "required": [
                          "id",
                          "token",
                          "public_url",
                          "conversation_id",
                          "expires_at",
                          "revoked_at",
                          "created_at",
                          "active"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Shares in `data`."
                        },
                        "active_count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Shares in `data` that currently work."
                        }
                      },
                      "required": [
                        "request_id",
                        "count",
                        "active_count"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "9b1e5c7a-2d3f-4a68-b0c4-7e8f9a0b1c2d",
                      "token": "example-share-token",
                      "public_url": "/share/chat/example-share-token",
                      "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                      "expires_at": null,
                      "revoked_at": null,
                      "created_at": 1792554097272,
                      "active": true
                    }
                  ],
                  "meta": {
                    "request_id": "0cf07e8d-6f86-47b3-8a35-35499a651571",
                    "count": 1,
                    "active_count": 1
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create_conversation_share",
        "tags": [
          "Conversation shares"
        ],
        "summary": "Create a share link for a conversation",
        "description": "Creates a public link to one of your conversations and returns it with `201`. Anyone who has the link can read the conversation without an API key, so treat `token` like a password and revoke the share when it is no longer needed. Open the link at `https://www.scarleta.ai` followed by `public_url`. The link never expires unless you send `expires_in_seconds`. The request body is optional; send none to create a link that does not expire. Each call creates a new link; list them with `GET /v1/conversations/{conversationId}/shares`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_expiry",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "mint_failed",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expires_in_seconds": {
                    "description": "How long the link works, in seconds, from now. Send a JSON number of at least 1, at most 315360000; fractions are rounded down, so a value below 1 gives a link that is already expired. Leave it out for a link that does not expire.",
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 315360000
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "expires_in_seconds": 3600
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created. `meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifier of the share. Use it to revoke the share."
                        },
                        "token": {
                          "type": "string",
                          "description": "The secret in the link. Anyone who has it can read the conversation until the share is revoked or expires."
                        },
                        "public_url": {
                          "type": "string",
                          "description": "Path of the public page, to append to `https://www.scarleta.ai`."
                        },
                        "conversation_id": {
                          "type": "string",
                          "description": "The shared conversation."
                        },
                        "expires_at": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "When the link stops working, in milliseconds since the Unix epoch; null when it never expires."
                        },
                        "revoked_at": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "When the share was revoked, in milliseconds since the Unix epoch; null while it is not revoked."
                        },
                        "created_at": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "When the share was created, in milliseconds since the Unix epoch."
                        },
                        "active": {
                          "type": "boolean",
                          "description": "True when the link currently works: not revoked and not expired."
                        }
                      },
                      "required": [
                        "id",
                        "token",
                        "public_url",
                        "conversation_id",
                        "expires_at",
                        "revoked_at",
                        "created_at",
                        "active"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "9b1e5c7a-2d3f-4a68-b0c4-7e8f9a0b1c2d",
                    "token": "example-share-token",
                    "public_url": "/share/chat/example-share-token",
                    "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "expires_at": null,
                    "revoked_at": null,
                    "created_at": 1792554097272,
                    "active": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON (`invalid_json`), or `expires_in_seconds` is not a positive number within the limit (`invalid_expiry`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_expiry",
                    "message": "expires_in_seconds must be a positive number of seconds",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_expiry"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "You do not own this conversation, or it does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/conversations/{conversationId}/shares/{shareId}": {
      "delete": {
        "operationId": "revoke_conversation_share",
        "tags": [
          "Conversation shares"
        ],
        "summary": "Revoke a share link",
        "description": "Turns a share link off right away: the public page stops working and `revoked_at` is set. The share stays in `GET /v1/conversations/{conversationId}/shares` with `active: false`. A revoked link cannot be turned back on; create a new one instead. Revoking a share that is already revoked answers `404 not_found`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_conversation_id",
          "missing_share_id",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "revoke_failed",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The conversation id, for example `3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01`."
            }
          },
          {
            "name": "shareId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The share id (the `id` of a share, not its `token`), for example `9b1e5c7a-2d3f-4a68-b0c4-7e8f9a0b1c2d`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked. `meta.request_id` is present.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifier of the share. Use it to revoke the share."
                        },
                        "token": {
                          "type": "string",
                          "description": "The secret in the link. Anyone who has it can read the conversation until the share is revoked or expires."
                        },
                        "public_url": {
                          "type": "string",
                          "description": "Path of the public page, to append to `https://www.scarleta.ai`."
                        },
                        "conversation_id": {
                          "type": "string",
                          "description": "The shared conversation."
                        },
                        "expires_at": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "When the link stops working, in milliseconds since the Unix epoch; null when it never expires."
                        },
                        "revoked_at": {
                          "anyOf": [
                            {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            {
                              "type": "null"
                            }
                          ],
                          "description": "When the share was revoked, in milliseconds since the Unix epoch; null while it is not revoked."
                        },
                        "created_at": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "When the share was created, in milliseconds since the Unix epoch."
                        },
                        "active": {
                          "type": "boolean",
                          "description": "True when the link currently works: not revoked and not expired."
                        }
                      },
                      "required": [
                        "id",
                        "token",
                        "public_url",
                        "conversation_id",
                        "expires_at",
                        "revoked_at",
                        "created_at",
                        "active"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "9b1e5c7a-2d3f-4a68-b0c4-7e8f9a0b1c2d",
                    "token": "example-share-token",
                    "public_url": "/share/chat/example-share-token",
                    "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "expires_at": null,
                    "revoked_at": 1792554157272,
                    "created_at": 1792554097272,
                    "active": false
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The share does not exist, is not yours, or is already revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Share 9b1e5c7a-2d3f-4a68-b0c4-7e8f9a0b1c2d not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/documents": {
      "get": {
        "operationId": "list_documents",
        "tags": [
          "Documents"
        ],
        "summary": "List documents",
        "description": "Returns the latest version of each of your documents, newest first, with the full content. `meta.count` is the number of documents returned.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_limit",
          "list_failed",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Documents to return, from 1 to 100. Defaults to 50. A value outside the range, or one that is not a whole number, is refused with `invalid_limit`.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "Identifier of the document. Every version of one document has the same id."
                          },
                          "created_at": {
                            "type": "string",
                            "description": "ISO 8601 timestamp of this version."
                          },
                          "title": {
                            "type": "string",
                            "description": "The document title."
                          },
                          "content": {
                            "description": "The document content; null when the version has none.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "kind": {
                            "type": "string",
                            "enum": [
                              "text",
                              "code",
                              "sheet",
                              "image",
                              "chart"
                            ],
                            "description": "What the content is: `text`, `code`, `sheet`, `image` or `chart`."
                          }
                        },
                        "required": [
                          "id",
                          "created_at",
                          "title",
                          "content",
                          "kind"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        },
                        "count": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "Documents in `data`."
                        }
                      },
                      "required": [
                        "request_id",
                        "count"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38",
                      "created_at": "2026-10-21T03:41:56.630Z",
                      "title": "Mix notes",
                      "content": "Kick is masking the bass below 80 Hz.",
                      "kind": "text"
                    }
                  ],
                  "meta": {
                    "request_id": "4d18043e-5317-4d76-9c7f-b01c34db04b4",
                    "count": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "`limit` is not a whole number in the allowed range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_limit",
                    "message": "limit must be an integer between 1 and 100",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_limit"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "save_document",
        "tags": [
          "Documents"
        ],
        "summary": "Create a document or save a new version",
        "description": "Without `id`, creates a new document and returns its first version with `201`. With the `id` of one of your documents, appends a new version to it (the history is kept) and returns that version, also with `201`. A body that is not valid JSON is answered like a body with no title: `400 missing_title`. A chart whose content is an invented, flat heatmap is refused with `400 degenerate_heatmap`; fix the content to save it.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "content_too_large",
          "create_failed",
          "degenerate_heatmap",
          "invalid_auth_format",
          "invalid_id",
          "invalid_key",
          "invalid_key_format",
          "invalid_kind",
          "missing_api_key",
          "missing_auth",
          "missing_title",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "title_too_long",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "description": "Id of an existing document to add a version to. Leave it out to create a new document. Must be a UUID.",
                    "type": "string"
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "The title, at most 200 characters after leading and trailing spaces are removed. Required, and not blank."
                  },
                  "content": {
                    "description": "The content, at most 1048576 characters. Leave it out or send null for none.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1048576
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "kind": {
                    "description": "What the content is. Defaults to `text`.",
                    "type": "string",
                    "enum": [
                      "text",
                      "code",
                      "sheet",
                      "image",
                      "chart"
                    ]
                  }
                },
                "required": [
                  "title"
                ],
                "additionalProperties": false
              },
              "example": {
                "title": "Mix notes",
                "content": "Kick is masking the bass below 80 Hz.",
                "kind": "text"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The version just saved.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "Identifier of the document. Every version of one document has the same id."
                            },
                            "created_at": {
                              "type": "string",
                              "description": "ISO 8601 timestamp of this version."
                            },
                            "title": {
                              "type": "string",
                              "description": "The document title."
                            },
                            "content": {
                              "description": "The document content; null when the version has none.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "text",
                                "code",
                                "sheet",
                                "image",
                                "chart"
                              ],
                              "description": "What the content is: `text`, `code`, `sheet`, `image` or `chart`."
                            }
                          },
                          "required": [
                            "id",
                            "created_at",
                            "title",
                            "content",
                            "kind"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "id": "5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38",
                    "created_at": "2026-10-21T03:41:56.630Z",
                    "title": "Mix notes",
                    "content": "Kick is masking the bass below 80 Hz.",
                    "kind": "text"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The title is missing or blank, or the body is not valid JSON (`missing_title`); the title is too long (`title_too_long`); `id` is not a UUID (`invalid_id`); `kind` is not one of the five kinds (`invalid_kind`); or a chart is a degenerate heatmap (`degenerate_heatmap`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_title",
                    "message": "title is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_title"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "`id` names a document that is not yours or does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Document 5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The content is over the size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "content_too_large",
                    "message": "document content must not exceed 1048576 characters",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#content_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/documents/{id}": {
      "delete": {
        "operationId": "delete_document_versions",
        "tags": [
          "Documents"
        ],
        "summary": "Delete the versions of a document saved after a time",
        "description": "Removes every version of the document saved after the time in `after`, which restores the document to the version that was current at that time. This cannot be undone. `after` is required so a call can never wipe a whole history by accident; send `after=0` to remove every version, which deletes the document. The call answers `200` with `removed: 0` when nothing is newer, when the document is already gone, or when it is not yours.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "delete_failed",
          "invalid_after",
          "invalid_auth_format",
          "invalid_id",
          "invalid_key",
          "invalid_key_format",
          "missing_after",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The document id, for example `5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38`."
            }
          },
          {
            "name": "after",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "description": "A time in milliseconds since the Unix epoch. Versions saved after it are removed; the version saved at exactly this time stays. Use `Date.parse(created_at)` of the version you want to keep. Send a whole number of milliseconds (digits only): a blank, fractional, signed or exponent value is refused with `invalid_after`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "The document id."
                            },
                            "removed": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Versions removed."
                            }
                          },
                          "required": [
                            "id",
                            "removed"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "id": "5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38",
                    "removed": 1
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`after` is missing (`missing_after`) or is not a whole number of milliseconds (`invalid_after`), or the id is not a UUID (`invalid_id`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "missing_after",
                    "message": "after (epoch ms) query param is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#missing_after"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_document",
        "tags": [
          "Documents"
        ],
        "summary": "Get a document",
        "description": "Returns the latest version of one document. With `versions=true`, returns every version instead, oldest first, and `meta.count` is the number of versions.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "get_failed",
          "invalid_auth_format",
          "invalid_id",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The document id, for example `5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38`."
            }
          },
          {
            "name": "versions",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Send `true` to get every version of the document, oldest first. Any other value returns only the latest version.",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The latest version as an object, or with `versions=true` an array of versions (see the response fields: `data` is an object or an array).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "Identifier of the document. Every version of one document has the same id."
                            },
                            "created_at": {
                              "type": "string",
                              "description": "ISO 8601 timestamp of this version."
                            },
                            "title": {
                              "type": "string",
                              "description": "The document title."
                            },
                            "content": {
                              "description": "The document content; null when the version has none.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "text",
                                "code",
                                "sheet",
                                "image",
                                "chart"
                              ],
                              "description": "What the content is: `text`, `code`, `sheet`, `image` or `chart`."
                            }
                          },
                          "required": [
                            "id",
                            "created_at",
                            "title",
                            "content",
                            "kind"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifier of the document. Every version of one document has the same id."
                              },
                              "created_at": {
                                "type": "string",
                                "description": "ISO 8601 timestamp of this version."
                              },
                              "title": {
                                "type": "string",
                                "description": "The document title."
                              },
                              "content": {
                                "description": "The document content; null when the version has none.",
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "kind": {
                                "type": "string",
                                "enum": [
                                  "text",
                                  "code",
                                  "sheet",
                                  "image",
                                  "chart"
                                ],
                                "description": "What the content is: `text`, `code`, `sheet`, `image` or `chart`."
                              }
                            },
                            "required": [
                              "id",
                              "created_at",
                              "title",
                              "content",
                              "kind"
                            ],
                            "additionalProperties": false
                          }
                        }
                      ]
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        },
                        "count": {
                          "description": "Versions in `data`; present only with `versions=true`.",
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38",
                    "created_at": "2026-10-21T03:41:56.630Z",
                    "title": "Mix notes",
                    "content": "Kick is masking the bass below 80 Hz.",
                    "kind": "text"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The id in the path is not a UUID.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_id",
                    "message": "id must be a valid UUID",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_id"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No document with this id exists in your account (a document of another account is reported the same way).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Document 5c2f8a14-9d3b-4e07-a1c6-0b7d4e9f2a38 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/feedback": {
      "post": {
        "operationId": "send_feedback",
        "tags": [
          "Feedback"
        ],
        "summary": "Send a thumbs up or thumbs down",
        "description": "Records whether a result was good. `request_id` is the id of the request you are rating, as a UUID (the part of an `X-Request-ID` header after `req_`); `feedback` is `thumbs_up` or `thumbs_down`; `feedback_text` is an optional comment of at most 4096 characters. You can rate only a request your own account made: an id that was never issued, or that belongs to another account, is 404 `not_found` (the record of a request is written just after its answer is sent, so rate it a moment later, not in the same instant). Sending the same rating twice stores it twice.\n\nEvery problem with the body, including text that is not valid JSON, is 400 `invalid_request`; the message names the field. Only an over-long comment has its own code, `feedback_text_too_long`. If the rating could not be stored the reply is 503 `db_unavailable`; send it again.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "db_unavailable",
          "feedback_text_too_long",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "request_id": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                    "description": "The id of the request you are rating, as a UUID."
                  },
                  "feedback": {
                    "type": "string",
                    "enum": [
                      "thumbs_up",
                      "thumbs_down"
                    ],
                    "description": "Your verdict."
                  },
                  "feedback_text": {
                    "description": "An optional comment, at most 4096 characters.",
                    "type": "string",
                    "maxLength": 4096
                  }
                },
                "required": [
                  "request_id",
                  "feedback"
                ],
                "additionalProperties": false
              },
              "example": {
                "request_id": "4e1b7c9a-2d58-4f03-8a6b-5c0d9e1f2a37",
                "feedback": "thumbs_up",
                "feedback_text": "Great result"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The rating is stored.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true: the rating was stored."
                            },
                            "request_id": {
                              "type": "string",
                              "description": "The id you sent."
                            },
                            "feedback": {
                              "type": "string",
                              "enum": [
                                "thumbs_up",
                                "thumbs_down"
                              ],
                              "description": "The verdict you sent."
                            },
                            "message": {
                              "type": "string",
                              "description": "A short confirmation sentence that repeats the verdict and the comment."
                            }
                          },
                          "required": [
                            "success",
                            "request_id",
                            "feedback",
                            "message"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "request_id": "4e1b7c9a-2d58-4f03-8a6b-5c0d9e1f2a37",
                    "feedback": "thumbs_up",
                    "message": "✓ Feedback recorded: thumbs_up - Great result"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON, `request_id` is missing or not a UUID, `feedback` is not one of the two verdicts, or `feedback_text` is not a string (`invalid_request`); `feedback_text` is too long (`feedback_text_too_long`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Error: request_id must be a valid UUID",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The id was not issued to your account (it never existed, or another account made it).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Error: request not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/mcp/rpc": {
      "get": {
        "operationId": "open_mcp_event_stream",
        "tags": [
          "MCP"
        ],
        "summary": "Open the MCP event stream",
        "description": "Opens the Server-Sent Events channel of the MCP transport. Send `Accept: text/event-stream` and your API key. The answer is `200` with `Content-Type: text/event-stream` and stays open; the server does not send events on it today, because every request is answered on its own. Most clients do not need it: use `POST /v1/mcp/rpc`. Without `text/event-stream` in `Accept` the answer is `406`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "rate_limit_exceeded",
          "rate_limit_unavailable"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Must list `text/event-stream`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The stream is open (`Content-Type: text/event-stream`). The response has no body to read; it ends when you close it."
          },
          "401": {
            "description": "The Authorization header is missing, not a Bearer key, or the key is unknown or revoked. A challenge header `WWW-Authenticate: Bearer` is sent. No tool runs and nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "error": {
                    "message": "Authorization header required"
                  }
                }
              }
            }
          },
          "406": {
            "description": "The `Accept` header does not list `text/event-stream`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "description": "The `id` of the request this answers; null when the request could not be read.",
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "result": {
                      "description": "The result of the method, present when the call succeeded.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "error": {
                      "description": "Present when the call failed at the protocol level.",
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "A JSON-RPC error code, for example `-32601` for an unknown method."
                        },
                        "message": {
                          "type": "string"
                        },
                        "data": {}
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "jsonrpc": "2.0",
                  "error": {
                    "code": -32000,
                    "message": "Not Acceptable: Client must accept text/event-stream"
                  },
                  "id": null
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from your IP address in the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded. You can make 300 requests per hour. Please try again later.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "mcp_rpc_request",
        "tags": [
          "MCP"
        ],
        "summary": "Send an MCP request",
        "description": "The Model Context Protocol endpoint for AI clients. Send one JSON-RPC 2.0 message per request: `initialize`, then `tools/list` to see the tools and `tools/call` to run one. It is stateless: there are no sessions, so every request stands alone and answers with plain JSON. The request must send `Accept: application/json, text/event-stream`. Authenticate with your API key as `Authorization: Bearer <key>` like every other route. This endpoint is switched on in production. The tools are listed on the [MCP tools page](/docs/reference/mcp-tools); a long-running tool answers with a `job_id` that you read with the `get_analysis_result` tool. Protocol failures are JSON-RPC errors, often with HTTP `200`. Failures before the protocol (sign-in, bad `Content-Type`, bad `Accept`, unreadable JSON) are HTTP errors whose body is documented below; they do not use the standard error body. Requests are also limited per IP address: at most 300 per hour, then `429 rate_limit_exceeded`. A notification (a message with no `id`) is answered `202` with no body.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "tokens",
          "rule": "Initializing, listing tools and reading a result are free. Calling an audio tool uses tokens at the same rate as the matching analysis: 1 token is 1 second of audio."
        },
        "x-scarleta-error-codes": [
          "rate_limit_exceeded",
          "rate_limit_unavailable"
        ],
        "parameters": [
          {
            "name": "Accept",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Must list both `application/json` and `text/event-stream`, for example `application/json, text/event-stream`."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "id": {
                    "description": "Request id echoed in the answer. Leave it out to send a notification, which gets no answer body.",
                    "type": [
                      "string",
                      "number"
                    ]
                  },
                  "method": {
                    "type": "string",
                    "description": "The method: `initialize`, `tools/list`, `tools/call`, `resources/list` or `notifications/initialized`."
                  },
                  "params": {
                    "description": "Method parameters. `tools/call` takes `{ name, arguments }`.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "additionalProperties": false
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "initialize",
                "params": {
                  "protocolVersion": "2025-03-26",
                  "capabilities": {},
                  "clientInfo": {
                    "name": "example-client",
                    "version": "1.0.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC answer: `result` on success, `error` for a protocol failure such as an unknown method. A `tools/call` that fails inside the tool answers a `result` with `isError: true`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "description": "The `id` of the request this answers; null when the request could not be read.",
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "result": {
                      "description": "The result of the method, present when the call succeeded.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "error": {
                      "description": "Present when the call failed at the protocol level.",
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "A JSON-RPC error code, for example `-32601` for an unknown method."
                        },
                        "message": {
                          "type": "string"
                        },
                        "data": {}
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "result": {
                    "protocolVersion": "2025-03-26",
                    "capabilities": {
                      "tools": {},
                      "resources": {}
                    },
                    "serverInfo": {
                      "name": "Scarleta Audio MCP",
                      "version": "1.0.0"
                    }
                  },
                  "jsonrpc": "2.0",
                  "id": 1
                }
              }
            }
          },
          "202": {
            "description": "A notification was accepted. The body is empty."
          },
          "400": {
            "description": "The body is not valid JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "description": "The `id` of the request this answers; null when the request could not be read.",
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "result": {
                      "description": "The result of the method, present when the call succeeded.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "error": {
                      "description": "Present when the call failed at the protocol level.",
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "A JSON-RPC error code, for example `-32601` for an unknown method."
                        },
                        "message": {
                          "type": "string"
                        },
                        "data": {}
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "jsonrpc": "2.0",
                  "error": {
                    "code": -32700,
                    "message": "Parse error: Invalid JSON"
                  },
                  "id": null
                }
              }
            }
          },
          "401": {
            "description": "The Authorization header is missing, not a Bearer key, or the key is unknown or revoked. A challenge header `WWW-Authenticate: Bearer` is sent. No tool runs and nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "error"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "error": {
                    "message": "Authorization header required"
                  }
                }
              }
            }
          },
          "406": {
            "description": "The `Accept` header does not list both `application/json` and `text/event-stream`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "description": "The `id` of the request this answers; null when the request could not be read.",
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "result": {
                      "description": "The result of the method, present when the call succeeded.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "error": {
                      "description": "Present when the call failed at the protocol level.",
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "A JSON-RPC error code, for example `-32601` for an unknown method."
                        },
                        "message": {
                          "type": "string"
                        },
                        "data": {}
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "jsonrpc": "2.0",
                  "error": {
                    "code": -32000,
                    "message": "Not Acceptable: Client must accept both application/json and text/event-stream"
                  },
                  "id": null
                }
              }
            }
          },
          "415": {
            "description": "The `Content-Type` is not `application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "description": "The `id` of the request this answers; null when the request could not be read.",
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    },
                    "result": {
                      "description": "The result of the method, present when the call succeeded.",
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {}
                    },
                    "error": {
                      "description": "Present when the call failed at the protocol level.",
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991,
                          "description": "A JSON-RPC error code, for example `-32601` for an unknown method."
                        },
                        "message": {
                          "type": "string"
                        },
                        "data": {}
                      },
                      "required": [
                        "code",
                        "message"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "jsonrpc",
                    "id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "jsonrpc": "2.0",
                  "error": {
                    "code": -32000,
                    "message": "Unsupported Media Type: Content-Type must be application/json"
                  },
                  "id": null
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from your IP address in the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded. You can make 300 requests per hour. Please try again later.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/media/refresh-url": {
      "post": {
        "operationId": "refresh_media_url",
        "tags": [
          "Media links"
        ],
        "summary": "Get a fresh link for a media file",
        "description": "Media links that Scarleta returns can carry a signature that expires. Send a link you hold (`url`, an absolute address of at most 2048 characters, expired or not) and the route returns a freshly signed link for the same file, so a player can carry on. Only a file of your own account on Scarleta is signed. For anything else the answer is still 200 with `url` set to null: another account's file, an address on another site, or a link that cannot be signed right now. A null `url` means \"no fresh link\"; the link you already hold is not echoed back.\n\nA missing, empty, over-long or relative `url`, and a body that is not valid JSON, are all 400 `invalid_url`. On success this route answers `{ data }` without `meta`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_url",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2048,
                    "description": "The link to refresh, an absolute address of at most 2048 characters."
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A fresh link, or `url: null`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "description": "The freshly signed link, or null when the link is not a file of yours that can be signed.",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "url"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "url": "https://api.scarleta.ai/v1/audio/media/9b2c7d1e-5a40-4f83-b6c9-0d1e2f3a4b5c.wav?exp=1791337470&sig=example-signature"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is not valid JSON, or `url` is missing, empty, too long or not an absolute address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_url",
                    "message": "url must be a non-empty string",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_url"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/{recipe_id}": {
      "delete": {
        "operationId": "delete_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Delete a recipe",
        "description": "Permanently deletes a recipe saved by your account or team, together with its comments. This cannot be undone. A catalog recipe, another account's recipe, or one already deleted answers `404 not_found`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "recipe_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "recipe_id": {
                              "type": "string"
                            },
                            "deleted": {
                              "type": "boolean",
                              "const": true
                            }
                          },
                          "required": [
                            "recipe_id",
                            "deleted"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "recipe_id": "rec_4821_mix_check",
                    "deleted": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe of yours has this id (a catalog recipe, another account's recipe or one already deleted is answered the same way).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get_recipe",
        "tags": [
          "Recipe catalog"
        ],
        "summary": "Get a recipe",
        "description": "Returns one recipe with its steps. You can read catalog recipes and your own account's recipes. Step feature names are the neutral capability names.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "recipe_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "recipe": {
                              "type": "object",
                              "properties": {
                                "recipe_id": {
                                  "type": "string",
                                  "description": "Identifier of the recipe."
                                },
                                "recipe_name": {
                                  "description": "The recipe name.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "user_intent": {
                                  "description": "What the recipe was made to do, in the words it was created with.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "ai_description": {
                                  "description": "A short description of what the recipe does; null when none was set.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "domain": {
                                  "description": "The subject area of the recipe; null when none was set.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "scope": {
                                  "type": "string",
                                  "description": "Who can see the recipe: `universal` (the public catalog), `org-private` (your team) or `user-custom` (you)."
                                },
                                "catalog_status": {
                                  "description": "`draft`, `published` or null for a recipe that was saved without a status.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "author_id": {
                                  "description": "Identifier of the author, for catalog recipes; null otherwise.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "author_kind": {
                                  "description": "What kind of author made it, for catalog recipes; null otherwise.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "forked_from": {
                                  "description": "The recipe this one was forked from, or null.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "is_template": {
                                  "type": "boolean",
                                  "description": "True for a catalog template recipe."
                                },
                                "usage_count": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "How many times the recipe has been run."
                                },
                                "steps": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "propertyNames": {
                                      "type": "string"
                                    },
                                    "additionalProperties": {}
                                  },
                                  "description": "The ordered steps. Each has a `step` number, a `tool` name and its `parameters`, and may list `features` and `depends_on`."
                                },
                                "budget": {
                                  "description": "The recipe's budget settings, or null."
                                },
                                "execution": {
                                  "description": "The recipe's execution settings, or null."
                                },
                                "is_owner": {
                                  "type": "boolean",
                                  "description": "True when your account can delete this recipe."
                                }
                              },
                              "required": [
                                "recipe_id",
                                "recipe_name",
                                "user_intent",
                                "ai_description",
                                "domain",
                                "scope",
                                "catalog_status",
                                "author_id",
                                "author_kind",
                                "forked_from",
                                "is_template",
                                "usage_count",
                                "steps",
                                "budget",
                                "execution",
                                "is_owner"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "success",
                            "recipe"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "recipe": {
                      "recipe_id": "rec_1005_cat_spectral",
                      "recipe_name": "Analyze the spectral characteristics of an audio recording",
                      "user_intent": "analyze the spectral content of this audio",
                      "ai_description": "Analyze brightness, spectral centroid, rolloff and energy for mixing and sound-design decisions.",
                      "domain": "audio analysis",
                      "scope": "universal",
                      "catalog_status": "published",
                      "author_id": "example-author",
                      "author_kind": "scarleta",
                      "forked_from": null,
                      "is_template": true,
                      "usage_count": 8,
                      "steps": [
                        {
                          "step": 1,
                          "tool": "spectral_analysis",
                          "features": [
                            "spectral.centroid",
                            "spectral.rolloff"
                          ],
                          "parameters": {
                            "analysis_level": "basic"
                          }
                        }
                      ],
                      "budget": null,
                      "execution": null,
                      "is_owner": false
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe with this id is visible to you: it does not exist, or it is a private recipe of another account. Both are answered the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/{recipe_id}/comments": {
      "get": {
        "operationId": "list_recipe_comments",
        "tags": [
          "Recipe catalog"
        ],
        "summary": "List the comments on a recipe",
        "description": "Returns the discussion on a recipe you can see, oldest first. Page with `limit` and `offset`; `has_more` is true when another page exists.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "recipe_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case."
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Comments to return. Defaults to 100; a value above 200 is clamped to 200, a value below 1 is read as 1, and a value that is not a number falls back to the default.",
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Comments to skip. Defaults to 0; a negative or non-numeric value is read as 0.",
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "comments": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "comment_id": {
                                    "type": "string",
                                    "description": "Identifier of the comment."
                                  },
                                  "recipe_id": {
                                    "type": "string",
                                    "description": "The recipe the comment belongs to."
                                  },
                                  "author_label": {
                                    "type": "string",
                                    "description": "A stable display name for the author, such as `Member 11e594`. It cannot be turned back into an account id."
                                  },
                                  "body": {
                                    "type": "string",
                                    "description": "The comment text."
                                  },
                                  "created_at": {
                                    "type": "integer",
                                    "minimum": -9007199254740991,
                                    "maximum": 9007199254740991,
                                    "description": "When the comment was posted, in milliseconds since the Unix epoch."
                                  }
                                },
                                "required": [
                                  "comment_id",
                                  "recipe_id",
                                  "author_label",
                                  "body",
                                  "created_at"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Comments in `comments`."
                            },
                            "has_more": {
                              "type": "boolean",
                              "description": "True when more comments exist after this page."
                            }
                          },
                          "required": [
                            "success",
                            "comments",
                            "count",
                            "has_more"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "comments": [
                      {
                        "comment_id": "cmt_0b2d9f4e-6a31-4c58-9e07-3d1a5b7c9e02",
                        "recipe_id": "rec_4821_mix_check",
                        "author_label": "Member 11e594",
                        "body": "The tempo step works well on this track.",
                        "created_at": 1792554097272
                      }
                    ],
                    "count": 1,
                    "has_more": false
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe with this id is visible to you: it does not exist, or it is a private recipe of another account. Both are answered the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post_recipe_comment",
        "tags": [
          "Recipe catalog"
        ],
        "summary": "Post a comment on a recipe",
        "description": "Adds a comment to a recipe you can see and returns it with `201`. The comment is shown under a display name derived from your account, never the account id. There is no route to edit or delete a comment; comments on a recipe are removed when the recipe is deleted. A body that is not valid JSON is answered like an empty comment: `400 invalid_request`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "recipe_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000,
                    "description": "The comment text, at most 4000 characters after leading and trailing spaces are removed. Required, and not blank."
                  }
                },
                "required": [
                  "body"
                ],
                "additionalProperties": false
              },
              "example": {
                "body": "The tempo step works well on this track."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The comment just posted.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "comment": {
                              "type": "object",
                              "properties": {
                                "comment_id": {
                                  "type": "string",
                                  "description": "Identifier of the comment."
                                },
                                "recipe_id": {
                                  "type": "string",
                                  "description": "The recipe the comment belongs to."
                                },
                                "author_label": {
                                  "type": "string",
                                  "description": "A stable display name for the author, such as `Member 11e594`. It cannot be turned back into an account id."
                                },
                                "body": {
                                  "type": "string",
                                  "description": "The comment text."
                                },
                                "created_at": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "When the comment was posted, in milliseconds since the Unix epoch."
                                }
                              },
                              "required": [
                                "comment_id",
                                "recipe_id",
                                "author_label",
                                "body",
                                "created_at"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "success",
                            "comment"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "comment": {
                      "comment_id": "cmt_0b2d9f4e-6a31-4c58-9e07-3d1a5b7c9e02",
                      "recipe_id": "rec_4821_mix_check",
                      "author_label": "Member 11e594",
                      "body": "The tempo step works well on this track.",
                      "created_at": 1792554097272
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The comment is missing or blank, is over the length limit, or the body is not valid JSON.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Comment body is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe with this id is visible to you: it does not exist, or it is a private recipe of another account. Both are answered the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/{recipe_id}/compare": {
      "get": {
        "operationId": "compare_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Compare a fork with its source",
        "description": "Shows which top-level fields of a fork differ from the recipe it was forked from, and how many steps each has. The recipe in the path must be a fork you can see, and its source must still be visible to you.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_a_fork",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "source_not_found",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "recipe_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "fork_id": {
                              "type": "string",
                              "description": "The fork you asked about."
                            },
                            "source_id": {
                              "type": "string",
                              "description": "The recipe it was forked from."
                            },
                            "diff": {
                              "type": "object",
                              "properties": {
                                "changed": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "field": {
                                        "type": "string",
                                        "description": "A recipe field: `recipe_name`, `user_intent`, `domain`, `ai_description`, `steps`, `budget` or `execution`."
                                      },
                                      "status": {
                                        "type": "string",
                                        "enum": [
                                          "added",
                                          "removed",
                                          "changed"
                                        ],
                                        "description": "Whether the fork added the field, removed it or changed it."
                                      },
                                      "source": {
                                        "description": "The value in the source."
                                      },
                                      "fork": {
                                        "description": "The value in the fork."
                                      }
                                    },
                                    "required": [
                                      "field",
                                      "status",
                                      "source",
                                      "fork"
                                    ],
                                    "additionalProperties": false
                                  },
                                  "description": "Fields that differ. Empty when the fork is identical."
                                },
                                "step_count": {
                                  "type": "object",
                                  "properties": {
                                    "source": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991
                                    },
                                    "fork": {
                                      "type": "integer",
                                      "minimum": -9007199254740991,
                                      "maximum": 9007199254740991
                                    }
                                  },
                                  "required": [
                                    "source",
                                    "fork"
                                  ],
                                  "additionalProperties": false,
                                  "description": "Steps in each recipe."
                                }
                              },
                              "required": [
                                "changed",
                                "step_count"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "success",
                            "fork_id",
                            "source_id",
                            "diff"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "fork_id": "rec_3791_17925845289883",
                    "source_id": "rec_4821_mix_check",
                    "diff": {
                      "changed": [
                        {
                          "field": "recipe_name",
                          "status": "changed",
                          "source": "Tempo check",
                          "fork": "Tempo check (fork)"
                        }
                      ],
                      "step_count": {
                        "source": 1,
                        "fork": 1
                      }
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The recipe in the path was not made by forking another.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_a_fork",
                    "message": "This recipe is not a fork (no forked_from source to compare against)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_a_fork"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe with this id is visible to you: it does not exist, or it belongs to another account. Both are answered the same way. When the fork is visible but its source is not, the code is `source_not_found` instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/{recipe_id}/fork": {
      "post": {
        "operationId": "fork_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Fork a recipe",
        "description": "Copies a recipe you can see (a catalog recipe or one of yours) into a new draft that belongs to you, and returns it with `201`. The copy keeps a pointer to the source in `forked_from`; use `GET /v1/recipe/{recipe_id}/compare` to see how a fork has drifted. Without `recipe_name` the copy is named after the source with \" (fork)\" added. The response also carries internal bookkeeping fields; do not rely on them.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "name_too_long",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_json_too_large",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "recipe_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case."
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe_name": {
                    "description": "A name for the copy, at most 200 characters.",
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "additionalProperties": false
              },
              "example": {
                "recipe_name": "Tempo check (fork)"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new draft.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "recipe_id": {
                              "type": "string",
                              "description": "The id of the new copy."
                            },
                            "forked_from": {
                              "type": "string",
                              "description": "The id of the source."
                            },
                            "forked_recipe": {
                              "type": "object",
                              "properties": {
                                "recipe_id": {
                                  "type": "string",
                                  "description": "Identifier of the recipe."
                                },
                                "recipe_name": {
                                  "description": "The recipe name.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "user_intent": {
                                  "type": "string",
                                  "description": "What the recipe is for."
                                },
                                "steps": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "propertyNames": {
                                      "type": "string"
                                    },
                                    "additionalProperties": {}
                                  },
                                  "description": "The ordered steps as stored."
                                },
                                "budget": {
                                  "description": "Budget settings, or null."
                                },
                                "execution": {
                                  "description": "Execution settings, or null."
                                },
                                "tags": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "description": "Tags on the recipe."
                                },
                                "is_template": {
                                  "type": "boolean",
                                  "description": "True for a catalog template recipe."
                                },
                                "usage_count": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "How many times the recipe has been run."
                                },
                                "scope": {
                                  "type": "string",
                                  "description": "Who can see the recipe: `org-private` (your team) or `user-custom` (you)."
                                },
                                "catalog_status": {
                                  "description": "`draft`, `published`, or null for a recipe saved without a status.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "forked_from": {
                                  "description": "The recipe this one was forked from, or null.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "ai_description": {
                                  "description": "A short description, or null.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "domain": {
                                  "description": "The subject area, or null.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "author_id": {
                                  "description": "Author id for catalog recipes; null for yours.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "author_kind": {
                                  "description": "Author kind for catalog recipes; null for yours.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "created_at": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "When the recipe was saved, in milliseconds since the Unix epoch."
                                },
                                "updated_at": {
                                  "description": "When it was last updated, or null.",
                                  "type": [
                                    "number",
                                    "null"
                                  ]
                                },
                                "last_used_at": {
                                  "description": "When it was last run, or null.",
                                  "type": [
                                    "number",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "recipe_id",
                                "recipe_name",
                                "user_intent",
                                "steps",
                                "budget",
                                "execution",
                                "tags",
                                "is_template",
                                "usage_count",
                                "scope",
                                "catalog_status",
                                "forked_from",
                                "ai_description",
                                "domain",
                                "author_id",
                                "author_kind",
                                "created_at",
                                "updated_at",
                                "last_used_at"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "success",
                            "recipe_id",
                            "forked_from",
                            "forked_recipe"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "recipe_id": "rec_3791_17925845289883",
                    "forked_from": "rec_4821_mix_check",
                    "forked_recipe": {
                      "recipe_id": "rec_3791_17925845289883",
                      "recipe_name": "Tempo check (fork)",
                      "user_intent": "Estimate the tempo of a track",
                      "steps": [
                        {
                          "step": 1,
                          "tool": "tempo_analysis",
                          "parameters": {}
                        }
                      ],
                      "budget": null,
                      "execution": null,
                      "tags": [],
                      "is_template": false,
                      "usage_count": 0,
                      "scope": "user-custom",
                      "catalog_status": "draft",
                      "forked_from": "rec_4821_mix_check",
                      "ai_description": null,
                      "domain": null,
                      "author_id": null,
                      "author_kind": null,
                      "created_at": 1792586336723,
                      "updated_at": null,
                      "last_used_at": null
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`recipe_name` is too long.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "name_too_long",
                    "message": "Name must not exceed 200 characters",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#name_too_long"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe with this id is visible to you: it does not exist, or it belongs to another account. Both are answered the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The source recipe is over the size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "recipe_json_too_large",
                    "message": "recipe exceeds 102400 bytes (got 102401)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#recipe_json_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/{recipe_id}/unpublish": {
      "post": {
        "operationId": "unpublish_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Unpublish a recipe",
        "description": "Moves one of your recipes back to a draft. Only the status changes. You can unpublish recipes saved by your account or team; a catalog recipe or another account's recipe answers `404 not_found`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "recipe_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The recipe id, for example `rec_4821_mix_check`. Ids are case-insensitive and are read in lower case."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "recipe_id": {
                              "type": "string"
                            },
                            "catalog_status": {
                              "type": "string",
                              "const": "draft"
                            }
                          },
                          "required": [
                            "recipe_id",
                            "catalog_status"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "recipe_id": "rec_4821_mix_check",
                    "catalog_status": "draft"
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe of yours has this id (a catalog recipe or another account's recipe is answered the same way).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/approve": {
      "post": {
        "operationId": "approve_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Record an approval or a rejection of a recipe",
        "description": "Records that you approved or rejected a saved recipe. It changes nothing on the recipe itself and does not run it; it leaves a record that your own tools can use. With `approved: true` you may list `modifications` (fields you changed); their names are echoed in `modifications_applied`. With `approved: false` you may give a `rejection_reason`. `modifications` may be at most 102400 bytes once serialized.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_json_too_large",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe_id": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The id of a recipe in your account, for example `rec_4821_mix_check`."
                  },
                  "approved": {
                    "type": "boolean",
                    "description": "True to approve, false to reject. Must be a JSON boolean."
                  },
                  "modifications": {
                    "description": "Fields you changed before approving. Only used when `approved` is true.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "rejection_reason": {
                    "description": "Why you rejected it. Only kept when `approved` is false.",
                    "type": "string"
                  }
                },
                "required": [
                  "recipe_id",
                  "approved"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe_id": "rec_4821_mix_check",
                "approved": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "recipe_id": {
                              "type": "string",
                              "description": "The recipe the decision is about."
                            },
                            "request_id": {
                              "type": "string",
                              "description": "Identifier of this decision record."
                            },
                            "approved": {
                              "type": "boolean",
                              "description": "The decision."
                            },
                            "modifications_applied": {
                              "description": "Names of the fields in `modifications`. Present when approved.",
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "rejection_reason": {
                              "description": "The reason given, or null. Present when rejected.",
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "success",
                            "recipe_id",
                            "request_id",
                            "approved"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "recipe_id": "rec_4821_mix_check",
                    "request_id": "0cf07e8d-6f86-47b3-8a35-35499a651571",
                    "approved": true,
                    "modifications_applied": []
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`recipe_id` is missing, or `approved` is not a JSON boolean, or the body is not valid JSON (`invalid_json`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Error: approved (boolean) is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe with this id is visible to you.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Error: Recipe 'rec_4821_mix_check' not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "`modifications` is over the size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "recipe_json_too_large",
                    "message": "modifications exceeds 102400 bytes (got 102401)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#recipe_json_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/author/{author_id}": {
      "get": {
        "operationId": "get_recipe_author",
        "tags": [
          "Recipe catalog"
        ],
        "summary": "Get an author's published recipes",
        "description": "Returns the public profile of a catalog author: the kind of author, their total number of published catalog recipes, and up to 100 of those recipes, newest first. Page past the first 100 with `offset`. Drafts and private recipes are never listed. The `author_id` of a catalog recipe is on `GET /v1/recipe/{recipe_id}`.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "author_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The author id, for example `example-author`."
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Recipes to skip, newest first, to reach the ones after the first 100. Defaults to 0; a negative or non-numeric value is read as 0. A page past the end returns an empty `recipes` list with the real `total`.",
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "author": {
                              "type": "object",
                              "properties": {
                                "author_id": {
                                  "type": "string",
                                  "description": "The author id you asked for."
                                },
                                "author_kind": {
                                  "description": "What kind of author this is.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "recipes": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "recipe_id": {
                                        "type": "string",
                                        "description": "Identifier of the recipe."
                                      },
                                      "recipe_name": {
                                        "description": "The recipe name.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "ai_description": {
                                        "description": "A short description of what the recipe does; null for a recipe that has none.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      },
                                      "domain": {
                                        "description": "The subject area of the recipe, for example `transcription`; null when none was set.",
                                        "type": [
                                          "string",
                                          "null"
                                        ]
                                      }
                                    },
                                    "required": [
                                      "recipe_id",
                                      "recipe_name",
                                      "ai_description",
                                      "domain"
                                    ],
                                    "additionalProperties": false
                                  },
                                  "description": "Their newest published catalog recipes (at most 100)."
                                },
                                "total": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "How many published catalog recipes the author has in all, which can be more than the 100 listed."
                                }
                              },
                              "required": [
                                "author_id",
                                "author_kind",
                                "recipes",
                                "total"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "success",
                            "author"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "author": {
                      "author_id": "example-author",
                      "author_kind": "scarleta",
                      "recipes": [
                        {
                          "recipe_id": "rec_1005_cat_spectral",
                          "recipe_name": "Analyze the spectral characteristics of an audio recording",
                          "ai_description": "Analyze brightness, spectral centroid, rolloff and energy for mixing and sound-design decisions.",
                          "domain": "audio analysis"
                        }
                      ],
                      "total": 1
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No author with this id has a published catalog recipe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Author not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/browse": {
      "get": {
        "operationId": "browse_recipes",
        "tags": [
          "Recipe catalog"
        ],
        "summary": "Browse recipes",
        "description": "Returns recipes you can see, newest first within a tab. `scope=universal` (the default) lists the public catalog; `scope=own` lists recipes saved by your account; `scope=draft` lists your unpublished recipes. Any other `scope` value is read as `universal`, and your own tabs never show another account's recipes. This is a summary list: use `GET /v1/recipe/{recipe_id}` for the steps. `is_owner` is true for recipes your account can delete. When the catalog is switched off for an environment the answer is an empty list, not an error.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Which list to return. Defaults to `universal`. `tab` is accepted as another name for this parameter.",
              "type": "string",
              "enum": [
                "universal",
                "own",
                "draft"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Recipes to return. Defaults to 50; a value above 100 is clamped to 100, and a value that is not a positive number falls back to the default.",
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Recipes to skip, for paging. Defaults to 0; a value that is not a positive number is read as 0.",
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The recipes of the chosen tab.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "recipes": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "recipe_id": {
                                    "type": "string",
                                    "description": "Identifier of the recipe."
                                  },
                                  "recipe_name": {
                                    "description": "The recipe name.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "ai_description": {
                                    "description": "A short description of what the recipe does; null for a recipe that has none.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "domain": {
                                    "description": "The subject area of the recipe, for example `transcription`; null when none was set.",
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "is_owner": {
                                    "type": "boolean",
                                    "description": "True when your account can delete this recipe."
                                  }
                                },
                                "required": [
                                  "recipe_id",
                                  "recipe_name",
                                  "ai_description",
                                  "domain",
                                  "is_owner"
                                ],
                                "additionalProperties": false
                              }
                            },
                            "count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Recipes in `recipes`."
                            }
                          },
                          "required": [
                            "success",
                            "recipes",
                            "count"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "recipes": [
                      {
                        "recipe_id": "rec_1005_cat_spectral",
                        "recipe_name": "Analyze the spectral characteristics of an audio recording",
                        "ai_description": "Analyze brightness, spectral centroid, rolloff and energy for mixing and sound-design decisions.",
                        "domain": "audio analysis",
                        "is_owner": false
                      }
                    ],
                    "count": 1
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/cancel": {
      "post": {
        "operationId": "cancel_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Set a proposed recipe aside in a conversation",
        "description": "Declines a recipe that the assistant proposed in one of your conversations; a recipe that was never proposed in the conversation answers `404` `recipe_not_found`. The decline is saved durably in the conversation, and a run of that recipe that is still queued or in progress is stopped. Cancel is silent: it sends no reply and costs nothing. Calling it again for the same conversation and recipe answers `200` too and records nothing new. `reason` is optional. Leading and trailing spaces are removed, a reason that is only spaces counts as none, and only the first 500 characters of the rest are kept.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge. Cancel sends no reply and analyzes no audio."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "decline_record_failed",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_not_found",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[A-Za-z0-9_.:@-]+$",
                    "description": "The id of the proposed recipe to set aside, at most 200 characters. Only letters, digits, `_`, `.`, `:`, `@` and `-` are allowed; other characters are rejected with 400 `invalid_request`."
                  },
                  "conversation_id": {
                    "type": "string",
                    "description": "The conversation the recipe was proposed in. Must be a UUID of a conversation of yours."
                  },
                  "reason": {
                    "description": "Why you set it aside, in your own words. Only the first 500 characters are kept.",
                    "type": "string"
                  }
                },
                "required": [
                  "recipe_id",
                  "conversation_id"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe_id": "rec_4821_mix_check",
                "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                "reason": "Too slow."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "recipe_id": {
                              "type": "string",
                              "description": "The recipe set aside."
                            },
                            "conversation_id": {
                              "type": "string",
                              "description": "The conversation."
                            },
                            "declined": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            }
                          },
                          "required": [
                            "success",
                            "recipe_id",
                            "conversation_id",
                            "declined"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "recipe_id": "rec_4821_mix_check",
                    "conversation_id": "3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01",
                    "declined": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`recipe_id` is missing, empty, longer than 200 characters or contains characters outside letters, digits, `_`, `.`, `:`, `@` and `-`, `conversation_id` is missing or not a UUID, or the body is not valid JSON (`invalid_json`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Error: a valid conversation_id is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The conversation is not yours or does not exist (`not_found`), or the recipe was never proposed in this conversation (`recipe_not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "502": {
            "description": "The decline could not be saved. Nothing was cancelled; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "decline_record_failed",
                    "message": "Failed to record the cancel. Please try again.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#decline_record_failed"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/execute": {
      "post": {
        "operationId": "execute_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Run a recipe on an audio file",
        "description": "Starts a recipe on one audio file and answers `200` at once with a `job_id`; read progress with `GET /v1/recipe/jobs/{job_id}` or receive a `recipe_completed` webhook. Name the recipe with `recipe_id` (a saved recipe of yours or a catalog recipe) or send the whole recipe in `recipe`, never both. The cost is estimated before anything starts (a rough run time is shown in `estimated_seconds`, summed from typical timings of each step's tool; a tool with no measured timing counts as 45 seconds); an account whose balance cannot cover it gets `402 insufficient_balance` with the estimate, the balance and the shortfall. `audio_url` must be a public `http` or `https` URL or a file in your own library; audio longer than 60 minutes is refused with 400 `audio_too_long`. Send `conversation_id` of one of your conversations to tie the run to it; repeating the same run for that conversation returns the existing job with `idempotent: true`, and a recipe you set aside with `POST /v1/recipe/cancel` answers `status: declined` with no job. Refusals use the standard error body; `insufficient_balance` (402) carries `estimated_cost`, `balance`, `shortfall` and `audio_duration` in `error.details`, and `audio_too_long` (400) carries `audio_duration` and `max_duration`. The top-level field `budget` is refused; set budgets in the recipe.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "tokens",
          "rule": "Each step is billed like the matching analysis of the audio: 1 token is 1 second of audio, at the rate of its capability. The estimate is checked against your balance before the run starts."
        },
        "x-scarleta-error-codes": [
          "audio_not_found",
          "audio_processing_failed",
          "audio_too_long",
          "auth_unavailable",
          "insufficient_balance",
          "invalid_audio_url",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_recipe",
          "invalid_recipe_parameters",
          "invalid_request",
          "invalid_webhook_url",
          "media_not_owned",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_json_too_large",
          "unauthorized",
          "unsupported_format",
          "webhook_url_too_large",
          "webhook_validation_unavailable",
          "workflow_binding_missing",
          "workflow_start_failed"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audio_url": {
                    "type": "string",
                    "minLength": 1,
                    "description": "The audio file to run the recipe on."
                  },
                  "recipe_id": {
                    "description": "The id of a saved recipe, for example `rec_4821_mix_check`. Send this or `recipe`.",
                    "type": "string"
                  },
                  "recipe": {
                    "description": "The whole recipe, as accepted by `POST /v1/recipe/validate`, at most 102400 bytes once serialized. Send this or `recipe_id`.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "conversation_id": {
                    "description": "A conversation of yours to tie the run to. Must be a UUID; a value that is not one is ignored.",
                    "type": "string"
                  },
                  "webhook_url": {
                    "description": "Where to POST the `recipe_completed` event. An https URL that resolves to a public address, at most 4096 bytes.",
                    "type": "string"
                  }
                },
                "required": [
                  "audio_url"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe_id": "rec_4821_mix_check",
                "audio_url": "https://example.com/track-1.wav"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The run was accepted (or an identical earlier run was found).",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "description": "Identifier of the run. Absent only when `status` is `declined`.",
                              "type": "string"
                            },
                            "status": {
                              "type": "string",
                              "description": "`IN_QUEUE` for a new run; the current status for an existing one; `declined` for a recipe you set aside."
                            },
                            "mode": {
                              "type": "string",
                              "const": "recipe",
                              "description": "Always `recipe`."
                            },
                            "recipe_id": {
                              "type": "string",
                              "description": "The recipe that runs."
                            },
                            "audio_url": {
                              "description": "The audio the run uses.",
                              "type": "string"
                            },
                            "num_steps": {
                              "description": "Steps in the recipe.",
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "estimated_seconds": {
                              "description": "A rough run time in seconds.",
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991
                            },
                            "idempotent": {
                              "description": "True when this answer repeats an earlier identical run for the same conversation.",
                              "type": "boolean"
                            },
                            "conversation_id": {
                              "description": "Present when `status` is `declined`.",
                              "type": "string"
                            },
                            "declined": {
                              "description": "True when the recipe was set aside in the conversation; nothing ran.",
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "status",
                            "mode",
                            "recipe_id"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "recipe_9f3a1c7e52b4",
                    "status": "IN_QUEUE",
                    "mode": "recipe",
                    "recipe_id": "rec_4821_mix_check",
                    "audio_url": "https://example.com/track-1.wav",
                    "num_steps": 1,
                    "estimated_seconds": 45
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The body is malformed or incomplete (`invalid_request`, `invalid_json`), the recipe fails validation (`invalid_recipe`, `invalid_recipe_parameters`), a URL is not acceptable (`invalid_audio_url`, `invalid_webhook_url`), or the audio cannot be used (`audio_too_long`, `unsupported_format`, `audio_processing_failed`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Provide either recipe_id or recipe.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "402": {
            "description": "The balance cannot cover the estimate. `error.details` carries `estimated_cost`, `balance`, `shortfall` and `audio_duration`. Nothing was charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "insufficient_balance",
                    "message": "Running this plan costs about 8 tokens, but your balance is 5. Top up and I will run it.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#insufficient_balance"
                  }
                }
              }
            }
          },
          "403": {
            "description": "The audio file belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "media_not_owned",
                    "message": "A file named in the request belongs to a different account.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#media_not_owned"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe with this id is visible to you, or `conversation_id` names a conversation that is not yours. A file at `audio_url` that cannot be downloaded is 404 `audio_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe 'rec_4821_mix_check' not found.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "`recipe` (`recipe_json_too_large`) or `webhook_url` (`webhook_url_too_large`) is over its size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "recipe_json_too_large",
                    "message": "recipe exceeds 102400 bytes (got 102401)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#recipe_json_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "500": {
            "description": "The recipe runner is not configured in this environment. This is a deployment fault, not something to retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "workflow_binding_missing",
                    "message": "RECIPE_EXECUTE_WORKFLOW binding is not configured.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#workflow_binding_missing"
                  }
                }
              }
            }
          },
          "502": {
            "description": "The run could not be started. Nothing was charged; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "workflow_start_failed",
                    "message": "Failed to start recipe execution. Please retry.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#workflow_start_failed"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/generate": {
      "post": {
        "operationId": "generate_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Generate a recipe from a request",
        "description": "Describes in words what you want to find out and returns a recipe the planner built for it. Nothing is saved or run: review the recipe, change it if you like, then save it with `POST /v1/recipe/save` and run it. The `recipe_id` in the answer is only a suggestion and is not unique, so save the recipe under your own `rec_` id. The call needs a token balance of at least 1 and does not debit tokens. It calls the planner, so it takes several seconds and can answer `503 planner_unavailable` when the planner times out (the same status as `auth_unavailable`; read the `code`); retry later.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "No tokens are debited, but the account needs a balance of at least 1 token."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "insufficient_balance",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "planner_unavailable",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user_intent": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "What you want to find out, in words, at most 2000 characters."
                  },
                  "budget_mode": {
                    "description": "How much work the plan may use: `fast` for the fewest, cheapest steps, `quality` for the most thorough.",
                    "type": "string",
                    "enum": [
                      "fast",
                      "balanced",
                      "quality"
                    ]
                  },
                  "audio_type": {
                    "description": "What kind of audio the recipe is for.",
                    "type": "string",
                    "enum": [
                      "music",
                      "speech",
                      "mixed",
                      "unknown"
                    ]
                  },
                  "max_cost": {
                    "description": "A cost ceiling in tokens that the planner aims to stay under.",
                    "type": "number"
                  },
                  "conversation_id": {
                    "description": "A conversation of yours to attribute the planning to. Must be a UUID.",
                    "type": "string"
                  }
                },
                "required": [
                  "user_intent"
                ],
                "additionalProperties": false
              },
              "example": {
                "user_intent": "Estimate the tempo of my track",
                "budget_mode": "fast"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "recipe": {
                              "type": "object",
                              "properties": {
                                "recipe_id": {
                                  "type": "string",
                                  "description": "A suggested id. Not unique."
                                },
                                "user_intent": {
                                  "type": "string",
                                  "description": "Your request."
                                },
                                "steps": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "propertyNames": {
                                      "type": "string"
                                    },
                                    "additionalProperties": {}
                                  },
                                  "description": "The planned steps. Each has a `step` number, a `tool` name and its `parameters`, and may carry `features`, `label` and `reason`."
                                },
                                "estimated_cost": {
                                  "description": "The planner's estimate of the cost in tokens.",
                                  "type": "number"
                                },
                                "budget": {
                                  "description": "The budget the plan was made under.",
                                  "type": "object",
                                  "propertyNames": {
                                    "type": "string"
                                  },
                                  "additionalProperties": {}
                                },
                                "rationale": {
                                  "description": "A short plain explanation of the plan.",
                                  "type": "string"
                                }
                              },
                              "required": [
                                "recipe_id",
                                "user_intent",
                                "steps"
                              ],
                              "additionalProperties": {},
                              "description": "The recipe. The planner may add fields beyond the ones listed."
                            },
                            "steps_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Steps in the recipe."
                            },
                            "estimated_cost": {
                              "type": "number",
                              "description": "The estimated cost in tokens; 0 when the planner gave none."
                            }
                          },
                          "required": [
                            "success",
                            "recipe",
                            "steps_count",
                            "estimated_cost"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "recipe": {
                      "recipe_id": "auto_generated_1712700000",
                      "user_intent": "Estimate the tempo of my track",
                      "steps": [
                        {
                          "step": 1,
                          "tool": "tempo_analysis",
                          "parameters": {
                            "include_tempo": true
                          },
                          "features": [
                            "tempo.bpm",
                            "tempo.beat_count"
                          ],
                          "label": "Find the tempo"
                        }
                      ],
                      "estimated_cost": 1,
                      "budget": {
                        "mode": "fast",
                        "audio_type": "music",
                        "max_cost": 5
                      },
                      "rationale": "One quick pass to hear the beat and give you the tempo."
                    },
                    "steps_count": 1,
                    "estimated_cost": 1
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`user_intent` is missing, empty or too long, `conversation_id` is not a UUID, the planner could not produce a valid recipe (the message says why), or the body is not valid JSON (`invalid_json`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Error: user_intent is required",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "402": {
            "description": "The account has no token balance, or its tenant is frozen. Nothing was charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "insufficient_balance",
                    "message": "Your balance is empty. Top up to generate recipes.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#insufficient_balance"
                  }
                }
              }
            }
          },
          "404": {
            "description": "`conversation_id` names a conversation that is not yours or does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Conversation 3f9c1d2e-7b44-4c1a-8e0f-5a6b7c8d9e01 not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/jobs/{job_id}": {
      "get": {
        "operationId": "get_recipe_job",
        "tags": [
          "Recipes"
        ],
        "summary": "Get a recipe run",
        "description": "Returns the state of a run started with `POST /v1/recipe/execute`. Poll it until `status` is `COMPLETED`, `FAILED`, `CANCELLED` or `TIMEOUT`; `results` is filled in only once the run has ended. Only recipe runs (ids that start with `recipe_`) are read here; use `GET /v1/analyze/{job_id}` for analyses. `completed_steps` and `num_steps` count the steps that finished and the steps in the recipe (`num_steps` is 0 until the run has ended). When you gave a `webhook_url`, `webhook_delivery_status` shows how the `recipe_completed` delivery went: `in_progress`, `delivered`, `failed`, or `unconfirmed`; it is null when there is no webhook or the run has not ended. It describes only that per-request `webhook_url`: addresses registered with `POST /v1/webhooks` are retried the same way, but their outcome is not shown in this field.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "The `job_id` from the execute answer, for example `recipe_9f3a1c7e52b4`."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "job_id": {
                              "type": "string",
                              "description": "Identifier of the run."
                            },
                            "status": {
                              "anyOf": [
                                {
                                  "type": "string",
                                  "description": "`IN_QUEUE`, `IN_PROGRESS`, `COMPLETED`, `FAILED`, `CANCELLED` or `TIMEOUT`."
                                },
                                {
                                  "type": "null"
                                }
                              ]
                            },
                            "mode": {
                              "type": "string",
                              "const": "recipe",
                              "description": "Always `recipe`."
                            },
                            "recipe_id": {
                              "description": "The recipe that ran; null until the run has ended.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "audio_url": {
                              "description": "The audio the run used.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "num_steps": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Steps in the recipe; 0 until the run has ended."
                            },
                            "completed_steps": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Steps that finished."
                            },
                            "results": {
                              "anyOf": [
                                {
                                  "type": "object",
                                  "propertyNames": {
                                    "type": "string"
                                  },
                                  "additionalProperties": {}
                                },
                                {
                                  "type": "null"
                                }
                              ],
                              "description": "The outcome of the run, once it has ended: the recipe, its steps and their results. Null while the run is queued or in progress, and for `TIMEOUT`."
                            },
                            "error": {
                              "description": "Why the run failed, or null.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "error_code": {
                              "description": "A short code for the failure, or null.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "started_at": {
                              "description": "When the run started, in milliseconds since the Unix epoch, or null.",
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "completed_at": {
                              "description": "When the run ended, in milliseconds since the Unix epoch, or null.",
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "webhook_delivery_status": {
                              "description": "State of the `recipe_completed` delivery to the per-request `webhook_url` only (registered addresses are not reflected here), or null.",
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "webhook_last_attempt_at": {
                              "description": "When the last delivery attempt started, in milliseconds since the Unix epoch, or null.",
                              "type": [
                                "number",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "job_id",
                            "status",
                            "mode",
                            "recipe_id",
                            "audio_url",
                            "num_steps",
                            "completed_steps",
                            "results",
                            "error",
                            "error_code",
                            "started_at",
                            "completed_at",
                            "webhook_delivery_status",
                            "webhook_last_attempt_at"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "job_id": "recipe_9f3a1c7e52b4",
                    "status": "COMPLETED",
                    "mode": "recipe",
                    "recipe_id": "rec_4821_mix_check",
                    "audio_url": "https://example.com/track-1.wav",
                    "num_steps": 1,
                    "completed_steps": 1,
                    "results": {
                      "status": "success",
                      "recipe_id": "rec_4821_mix_check",
                      "step_count": 1,
                      "response": null,
                      "conversation_id": null
                    },
                    "error": null,
                    "error_code": null,
                    "started_at": 1792586336723,
                    "completed_at": 1792586348723,
                    "webhook_delivery_status": null,
                    "webhook_last_attempt_at": null
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No recipe run with this id belongs to your account, or the id does not start with `recipe_`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe job 'recipe_9f3a1c7e52b4' not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/save": {
      "post": {
        "operationId": "save_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Save a recipe",
        "description": "Saves a recipe to your account and returns it. A recipe saved with `recipe_id` of an existing recipe of yours replaces it; one saved under another account's id answers `404 not_found`. Without `catalog_status` or with `published`, the recipe must pass validation and `recipe.recipe_id` is required. With `catalog_status: draft` validation is skipped so you can save work in progress, and a recipe with no `recipe_id` gets one made for you. `catalog_status` can only be `draft` or `published`, and cannot be set on a template recipe (`403 forbidden`). The response also carries internal bookkeeping fields; do not rely on them.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "forbidden",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_recipe_id",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "name_too_long",
          "not_found",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_json_too_large",
          "save_failed",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe": {
                    "type": "object",
                    "properties": {
                      "recipe_id": {
                        "type": "string",
                        "description": "The recipe id: letters, digits, underscore and hyphen, at most 128 characters. Required to validate. To save it for later use it must look like `rec_` + four digits + `_` + a name (for example `rec_0001_speech_quality`); a draft save may leave it out."
                      },
                      "user_intent": {
                        "description": "What the recipe is for, in words.",
                        "type": "string"
                      },
                      "steps": {
                        "minItems": 1,
                        "maxItems": 10,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "step": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "The step number, starting at 1. Numbers must be unique."
                            },
                            "tool": {
                              "type": "string",
                              "description": "The capability to run, for example `tempo_analysis`. An unknown name is refused and the error lists the valid ones."
                            },
                            "parameters": {
                              "description": "Settings for the step. A plain object; leave it out for none.",
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            },
                            "features": {
                              "description": "Feature names to compute, where the capability takes them.",
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "depends_on": {
                              "description": "Earlier step numbers this step needs the output of.",
                              "type": "array",
                              "items": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            "timeout_ms": {
                              "description": "How long the step may run, in milliseconds, from 1000 to 300000.",
                              "type": "integer",
                              "minimum": 1000,
                              "maximum": 300000
                            }
                          },
                          "required": [
                            "step",
                            "tool"
                          ],
                          "additionalProperties": false
                        },
                        "description": "The ordered steps, from 1 to 10."
                      },
                      "budget": {
                        "description": "Optional budget settings: `mode` (`fast`, `balanced` or `quality`) and `compute` (`cpu_only` or `gpu_allowed`).",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "execution": {
                        "description": "Optional execution settings.",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "additionalProperties": false,
                    "description": "The recipe. At most 102400 bytes once serialized."
                  },
                  "recipe_name": {
                    "description": "A name, at most 200 characters.",
                    "type": "string",
                    "maxLength": 200
                  },
                  "tags": {
                    "description": "Tags to keep with the recipe.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "is_template": {
                    "description": "Save as a template recipe. Defaults to false.",
                    "type": "boolean"
                  },
                  "catalog_status": {
                    "description": "Whether this is a work-in-progress draft or a published recipe. Leave it out for neither.",
                    "type": "string",
                    "enum": [
                      "draft",
                      "published"
                    ]
                  }
                },
                "required": [
                  "recipe"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe": {
                  "recipe_id": "rec_4821_mix_check",
                  "user_intent": "Estimate the tempo of a track",
                  "steps": [
                    {
                      "step": 1,
                      "tool": "tempo_analysis",
                      "parameters": {}
                    }
                  ]
                },
                "recipe_name": "Tempo check",
                "catalog_status": "published"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "success": {
                              "type": "boolean",
                              "const": true,
                              "description": "Always true."
                            },
                            "recipe_id": {
                              "type": "string",
                              "description": "The id the recipe was saved under."
                            },
                            "saved_recipe": {
                              "type": "object",
                              "properties": {
                                "recipe_id": {
                                  "type": "string",
                                  "description": "Identifier of the recipe."
                                },
                                "recipe_name": {
                                  "description": "The recipe name.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "user_intent": {
                                  "type": "string",
                                  "description": "What the recipe is for."
                                },
                                "steps": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "propertyNames": {
                                      "type": "string"
                                    },
                                    "additionalProperties": {}
                                  },
                                  "description": "The ordered steps as stored."
                                },
                                "budget": {
                                  "description": "Budget settings, or null."
                                },
                                "execution": {
                                  "description": "Execution settings, or null."
                                },
                                "tags": {
                                  "type": "array",
                                  "items": {
                                    "type": "string"
                                  },
                                  "description": "Tags on the recipe."
                                },
                                "is_template": {
                                  "type": "boolean",
                                  "description": "True for a catalog template recipe."
                                },
                                "usage_count": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "How many times the recipe has been run."
                                },
                                "scope": {
                                  "type": "string",
                                  "description": "Who can see the recipe: `org-private` (your team) or `user-custom` (you)."
                                },
                                "catalog_status": {
                                  "description": "`draft`, `published`, or null for a recipe saved without a status.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "forked_from": {
                                  "description": "The recipe this one was forked from, or null.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "ai_description": {
                                  "description": "A short description, or null.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "domain": {
                                  "description": "The subject area, or null.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "author_id": {
                                  "description": "Author id for catalog recipes; null for yours.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "author_kind": {
                                  "description": "Author kind for catalog recipes; null for yours.",
                                  "type": [
                                    "string",
                                    "null"
                                  ]
                                },
                                "created_at": {
                                  "type": "integer",
                                  "minimum": -9007199254740991,
                                  "maximum": 9007199254740991,
                                  "description": "When the recipe was saved, in milliseconds since the Unix epoch."
                                },
                                "updated_at": {
                                  "description": "When it was last updated, or null.",
                                  "type": [
                                    "number",
                                    "null"
                                  ]
                                },
                                "last_used_at": {
                                  "description": "When it was last run, or null.",
                                  "type": [
                                    "number",
                                    "null"
                                  ]
                                }
                              },
                              "required": [
                                "recipe_id",
                                "recipe_name",
                                "user_intent",
                                "steps",
                                "budget",
                                "execution",
                                "tags",
                                "is_template",
                                "usage_count",
                                "scope",
                                "catalog_status",
                                "forked_from",
                                "ai_description",
                                "domain",
                                "author_id",
                                "author_kind",
                                "created_at",
                                "updated_at",
                                "last_used_at"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "required": [
                            "success",
                            "recipe_id",
                            "saved_recipe"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "success": true,
                    "recipe_id": "rec_4821_mix_check",
                    "saved_recipe": {
                      "recipe_id": "rec_4821_mix_check",
                      "recipe_name": "Tempo check",
                      "user_intent": "Estimate the tempo of a track",
                      "steps": [
                        {
                          "step": 1,
                          "tool": "tempo_analysis",
                          "parameters": {}
                        }
                      ],
                      "budget": null,
                      "execution": null,
                      "tags": [],
                      "is_template": false,
                      "usage_count": 0,
                      "scope": "user-custom",
                      "catalog_status": "published",
                      "forked_from": null,
                      "ai_description": null,
                      "domain": null,
                      "author_id": null,
                      "author_kind": null,
                      "created_at": 1792586336723,
                      "updated_at": null,
                      "last_used_at": null
                    }
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The recipe is missing or empty, failed validation, or `catalog_status` is not allowed (`invalid_request`); `recipe_id` has the wrong format (`invalid_recipe_id`); or `recipe_name` is too long (`name_too_long`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Cannot save invalid recipe:\n\n- Missing required field: recipe_id",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "403": {
            "description": "`catalog_status` was set on a template recipe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "forbidden",
                    "message": "catalog_status cannot be set on a template recipe; universal publishing is operator-only",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#forbidden"
                  }
                }
              }
            }
          },
          "404": {
            "description": "`recipe.recipe_id` names a recipe that belongs to another account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Recipe not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#not_found"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The recipe is over the size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "recipe_json_too_large",
                    "message": "recipe exceeds 102400 bytes (got 102401)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#recipe_json_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/recipe/validate": {
      "post": {
        "operationId": "validate_recipe",
        "tags": [
          "Recipes"
        ],
        "summary": "Validate a recipe",
        "description": "Checks a recipe without saving or running it. A valid recipe answers `{ valid: true, steps_count }`. An invalid one answers `400 invalid_request` and the `message` lists every problem, one per line. Run it before saving or running a recipe you built by hand. The recipe may be at most 102400 bytes once serialized.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_request",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "recipe_json_too_large",
          "unauthorized"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipe": {
                    "type": "object",
                    "properties": {
                      "recipe_id": {
                        "type": "string",
                        "description": "The recipe id: letters, digits, underscore and hyphen, at most 128 characters. Required to validate. To save it for later use it must look like `rec_` + four digits + `_` + a name (for example `rec_0001_speech_quality`); a draft save may leave it out."
                      },
                      "user_intent": {
                        "description": "What the recipe is for, in words.",
                        "type": "string"
                      },
                      "steps": {
                        "minItems": 1,
                        "maxItems": 10,
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "step": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "The step number, starting at 1. Numbers must be unique."
                            },
                            "tool": {
                              "type": "string",
                              "description": "The capability to run, for example `tempo_analysis`. An unknown name is refused and the error lists the valid ones."
                            },
                            "parameters": {
                              "description": "Settings for the step. A plain object; leave it out for none.",
                              "type": "object",
                              "propertyNames": {
                                "type": "string"
                              },
                              "additionalProperties": {}
                            },
                            "features": {
                              "description": "Feature names to compute, where the capability takes them.",
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "depends_on": {
                              "description": "Earlier step numbers this step needs the output of.",
                              "type": "array",
                              "items": {
                                "type": "integer",
                                "minimum": -9007199254740991,
                                "maximum": 9007199254740991
                              }
                            },
                            "timeout_ms": {
                              "description": "How long the step may run, in milliseconds, from 1000 to 300000.",
                              "type": "integer",
                              "minimum": 1000,
                              "maximum": 300000
                            }
                          },
                          "required": [
                            "step",
                            "tool"
                          ],
                          "additionalProperties": false
                        },
                        "description": "The ordered steps, from 1 to 10."
                      },
                      "budget": {
                        "description": "Optional budget settings: `mode` (`fast`, `balanced` or `quality`) and `compute` (`cpu_only` or `gpu_allowed`).",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      },
                      "execution": {
                        "description": "Optional execution settings.",
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    },
                    "required": [
                      "recipe_id",
                      "steps"
                    ],
                    "additionalProperties": false
                  }
                },
                "required": [
                  "recipe"
                ],
                "additionalProperties": false
              },
              "example": {
                "recipe": {
                  "recipe_id": "rec_4821_mix_check",
                  "user_intent": "Estimate the tempo of a track",
                  "steps": [
                    {
                      "step": 1,
                      "tool": "tempo_analysis",
                      "parameters": {}
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "valid": {
                              "type": "boolean",
                              "const": true
                            },
                            "steps_count": {
                              "type": "integer",
                              "minimum": -9007199254740991,
                              "maximum": 9007199254740991,
                              "description": "Steps in the recipe."
                            }
                          },
                          "required": [
                            "valid",
                            "steps_count"
                          ],
                          "additionalProperties": false
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "data": {
                    "valid": true,
                    "steps_count": 1
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The recipe is missing or not an object (`Error: recipe is required`), or it failed validation (the message lists the problems), or the body is not valid JSON (`invalid_json`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_request",
                    "message": "Recipe validation failed:\n\n- Step 1: Invalid tool 'unknown_tool'",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_request"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The recipe is over the size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "recipe_json_too_large",
                    "message": "recipe exceeds 102400 bytes (got 102401)",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#recipe_json_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget for the hour. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/upload": {
      "post": {
        "operationId": "upload_file",
        "tags": [
          "Files"
        ],
        "summary": "Upload a file for one-off use",
        "description": "Uploads one audio file in a single request and returns a public `url` you can pass as `audio_url` to the analysis routes. Send `multipart/form-data` with the audio in the `file` part. Audio only: video is refused here, use the presigned upload route instead. The bytes are checked, not the declared type: a file that is not valid audio is refused with 400 `invalid_file_signature`. The body is read in one piece, so the limit is 100 MiB; larger files, and anything you want to keep in your library, go through the presigned upload route or an upload session.\n\nThe file is temporary: it is removed 24 hours after upload. While it exists its size counts toward your storage. `url` never expires within that time and is the value to use as an `audio_url`; `playback_url` is a signed copy for playing the file in a browser and stops working sooner.\n\nThis route answers with a bare JSON object: there is no `data` wrapper, no `meta` on a success. Uploads are limited to 30 per hour per account and per source address. Available to free and paid accounts.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge; the file counts toward your storage while it exists."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "file_too_large",
          "invalid_auth_format",
          "invalid_content_type",
          "invalid_file_signature",
          "invalid_file_type",
          "invalid_form_data",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "missing_file",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "video_not_supported_here"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "contentEncoding": "binary",
                    "description": "The audio file, at most 100 MiB."
                  }
                },
                "required": [
                  "file"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The file is stored. The body is the bare object shown, without a `data` wrapper.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "url": {
                      "type": "string",
                      "description": "Public URL of the stored file. Pass it as `audio_url`. It does not expire while the file exists."
                    },
                    "playback_url": {
                      "type": "string",
                      "description": "Signed variant of `url` for playing the file in a browser; it expires sooner than the file does."
                    },
                    "file_id": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                      "description": "Identifier of the stored file."
                    },
                    "filename": {
                      "type": "string",
                      "description": "Name the file is stored under."
                    },
                    "size": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Size in bytes."
                    },
                    "content_type": {
                      "type": "string",
                      "description": "Content type the upload declared, or `application/octet-stream`."
                    },
                    "expires_in": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Seconds the file is kept: 86400."
                    },
                    "expires_at": {
                      "type": "string",
                      "description": "When the file is removed, as an ISO 8601 timestamp."
                    }
                  },
                  "required": [
                    "success",
                    "url",
                    "playback_url",
                    "file_id",
                    "filename",
                    "size",
                    "content_type",
                    "expires_in",
                    "expires_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "success": true,
                  "url": "https://api.scarleta.ai/audio-cache/temp-3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav",
                  "playback_url": "https://api.scarleta.ai/audio-cache/temp-3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav?exp=1792557639&sig=9f2c1d4e8a7b6c5d",
                  "file_id": "3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b",
                  "filename": "temp-3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b.wav",
                  "size": 176478,
                  "content_type": "audio/wav",
                  "expires_in": 86400,
                  "expires_at": "2026-10-22T03:40:39.370Z"
                }
              }
            }
          },
          "400": {
            "description": "The request is not `multipart/form-data`, has no `file` part, or the file is not audio (checked by its bytes, not its declared type), or is a video.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_file_signature",
                    "message": "File does not appear to be a valid audio file",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_file_signature"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "413": {
            "description": "The file is larger than 100 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "file_too_large",
                    "message": "File size exceeds maximum allowed size",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#file_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "list_webhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List registered webhook addresses",
        "description": "Returns the addresses registered for your account, oldest first. Registered addresses receive every `batch_completed` and `recipe_completed` event of your account, in addition to the `webhook_url` of a single request (an address identical to the request's `webhook_url` is delivered once). Each delivery is signed exactly like a `webhook_url` delivery, with the same 3 attempts (waiting 2 s and 4 s), 10-second timeout and no redirects. You can register at most 5 addresses.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "webhooks": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "Identifier of the registered address, for example `whk_3f9c1a7e5b2d4c8a6e01b9d3`."
                              },
                              "url": {
                                "type": "string",
                                "description": "The address deliveries are POSTed to."
                              },
                              "created_at": {
                                "type": "number",
                                "description": "When the address was registered, in milliseconds since the Unix epoch."
                              }
                            },
                            "required": [
                              "id",
                              "url",
                              "created_at"
                            ],
                            "additionalProperties": false
                          }
                        }
                      },
                      "required": [
                        "webhooks"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "webhooks": [
                      {
                        "id": "whk_3f9c1a7e5b2d4c8a6e01b9d3",
                        "url": "https://example.com/hooks/scarleta",
                        "created_at": 1761650000000
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "register_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Register a webhook address",
        "description": "Registers an address that receives your account's webhook events. Registered addresses receive every `batch_completed` and `recipe_completed` event of your account, in addition to the `webhook_url` of a single request (an address identical to the request's `webhook_url` is delivered once). Each delivery is signed exactly like a `webhook_url` delivery, with the same 3 attempts (waiting 2 s and 4 s), 10-second timeout and no redirects. You can register at most 5 addresses. Registering the same address again returns the existing registration and sends no second email. The address must be an https URL that resolves to a public address. The account owner is emailed a notice naming the address's host (never its path or query), because a registered address receives every event; `notice_sent` is false when no email was sent, and never means the registration failed.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_json",
          "invalid_key",
          "invalid_key_format",
          "invalid_webhook_url",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "webhook_endpoint_limit_reached",
          "webhook_url_too_large",
          "webhook_validation_unavailable"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096,
                    "description": "An https URL that resolves to a public address, at most 4096 bytes."
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              },
              "example": {
                "url": "https://example.com/hooks/scarleta"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "Identifier of the registered address, for example `whk_3f9c1a7e5b2d4c8a6e01b9d3`."
                        },
                        "url": {
                          "type": "string",
                          "description": "The address deliveries are POSTed to."
                        },
                        "created_at": {
                          "type": "number",
                          "description": "When the address was registered, in milliseconds since the Unix epoch."
                        },
                        "notice_sent": {
                          "type": "boolean",
                          "description": "True when an email notice was sent to the account owner. False when no email was sent, including when the address was already registered. A false value never means the registration failed."
                        }
                      },
                      "required": [
                        "id",
                        "url",
                        "created_at",
                        "notice_sent"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "whk_3f9c1a7e5b2d4c8a6e01b9d3",
                    "url": "https://example.com/hooks/scarleta",
                    "created_at": 1761650000000,
                    "notice_sent": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`url` is missing, not a string, or not an https URL that resolves to a public address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_webhook_url",
                    "message": "URL must use https",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_webhook_url"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The account already has 5 registered addresses.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "webhook_endpoint_limit_reached",
                    "message": "You can register at most 5 webhook URLs. Delete one with DELETE /v1/webhooks/{id} first.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#webhook_endpoint_limit_reached"
                  }
                }
              }
            }
          },
          "413": {
            "description": "`url` is too long.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "webhook_url_too_large",
                    "message": "webhook_url exceeds 4096 bytes",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#webhook_url_too_large"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "operationId": "delete_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a registered webhook address",
        "description": "Permanently deletes a registered address and erases its stored URL; no further event is delivered to it. Only addresses registered by your own account can be deleted; any other id, or an already deleted one, returns 404. The account owner is emailed a notice naming the address's host (never its path or query); `notice_sent` is false when no email was sent, and never means the deletion failed.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized",
          "webhook_not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `id` returned when the address was registered."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "deleted": {
                          "type": "boolean",
                          "const": true
                        },
                        "notice_sent": {
                          "type": "boolean",
                          "description": "True when an email notice was sent to the account owner. A false value never means the deletion failed."
                        }
                      },
                      "required": [
                        "id",
                        "deleted",
                        "notice_sent"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "whk_3f9c1a7e5b2d4c8a6e01b9d3",
                    "deleted": true,
                    "notice_sent": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No active registered address with this id exists for your account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "webhook_not_found",
                    "message": "Webhook not found",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#webhook_not_found"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/signing-secret": {
      "get": {
        "operationId": "get_signing_secret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Get the signing secret",
        "description": "Returns the secret that signs every webhook delivery of your account, creating it on the first call. Every key of one account returns the same secret. Verify a delivery by recomputing `v1=` plus the lowercase hex HMAC-SHA256 of `<X-Scarleta-Timestamp>.<raw body>` keyed with this secret, and reject a timestamp more than 300 seconds from your clock. After a revocation this route answers 409 `signing_secret_revoked` until you rotate.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "signing_secret_revoked",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "secret": {
                          "type": "string",
                          "description": "Your signing secret: 64 lowercase hex characters. Keep it private."
                        },
                        "created_at": {
                          "type": "number",
                          "description": "When this secret was created, in milliseconds since the Unix epoch."
                        }
                      },
                      "required": [
                        "secret",
                        "created_at"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "secret": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
                    "created_at": 1761650000000
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "409": {
            "description": "The secret was revoked; no secret is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "signing_secret_revoked",
                    "message": "The signing secret was revoked. Call POST /v1/webhooks/signing-secret/rotate to create a new one.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#signing_secret_revoked"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/signing-secret/revoke": {
      "post": {
        "operationId": "revoke_signing_secret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Revoke the signing secret",
        "description": "Revokes the signing secret. No webhook is delivered, to any address, until you rotate to a new secret. A revoked secret is never accepted as the previous secret. The account owner is emailed a notice. `notice_sent` is false when no email was sent, including when the secret was already revoked: revoking an already revoked secret changes nothing, it answers 200 with the original `revoked_at` and `notice_sent: false`, and sends no second email. Answers 404 `no_signing_secret` when the account has no secret yet.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "no_signing_secret",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "revoked_at": {
                          "type": "number",
                          "description": "When the secret was revoked, in milliseconds since the Unix epoch."
                        },
                        "notice_sent": {
                          "type": "boolean",
                          "description": "True when an email notice was sent to the account owner. False when no email was sent, including when the secret was already revoked. A false value never means the revocation failed."
                        }
                      },
                      "required": [
                        "revoked_at",
                        "notice_sent"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "revoked_at": 1761650000000,
                    "notice_sent": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The account never created a signing secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "no_signing_secret",
                    "message": "No signing secret exists for this account yet.",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#no_signing_secret"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/signing-secret/rotate": {
      "post": {
        "operationId": "rotate_signing_secret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate the signing secret",
        "description": "Creates a new signing secret and returns it. The new secret is in this response and can be read again with `GET /v1/webhooks/signing-secret`. For one day after a rotation each delivery also carries `X-Scarleta-Signature-Previous`, signed with the old secret, so a receiver that has not switched yet can verify that header with its old secret and you can switch over without dropping events. A rotation after a revocation restores deliveries. The account owner is emailed a notice that never contains the secret; `notice_sent` is false when no email was sent.",
        "x-scarleta-tier": "both",
        "x-scarleta-cost": {
          "kind": "none",
          "rule": "Free of charge."
        },
        "x-scarleta-error-codes": [
          "auth_unavailable",
          "invalid_auth_format",
          "invalid_key",
          "invalid_key_format",
          "missing_api_key",
          "missing_auth",
          "rate_limit_exceeded",
          "rate_limit_unavailable",
          "unauthorized"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "secret": {
                          "type": "string",
                          "description": "Your signing secret: 64 lowercase hex characters. Keep it private."
                        },
                        "created_at": {
                          "type": "number",
                          "description": "When this secret was created, in milliseconds since the Unix epoch."
                        },
                        "notice_sent": {
                          "type": "boolean",
                          "description": "True when an email notice was sent to the account owner. A false value never means the rotation failed."
                        }
                      },
                      "required": [
                        "secret",
                        "created_at",
                        "notice_sent"
                      ],
                      "additionalProperties": false
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "request_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "request_id"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "example": {
                  "data": {
                    "secret": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
                    "created_at": 1761650000000,
                    "notice_sent": true
                  },
                  "meta": {
                    "request_id": "req_0b7a3c2e-6f1d-4d9a-8e55-3a4b5c6d7e8f"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, unknown or revoked API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "invalid_key",
                    "message": "Invalid or revoked API key",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#invalid_key"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Over the account request budget or the per-minute cap of this route. Wait for the `Retry-After` header, then retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "rate_limit_exceeded",
                    "message": "Rate limit exceeded",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#rate_limit_exceeded"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Temporary platform condition; retry shortly.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "auth_unavailable",
                    "message": "Authentication service temporarily unavailable",
                    "request_id": "req_5b1c0f3e-2d41-4a8e-9a57-0c1b2d3e4f50",
                    "docs_url": "https://www.scarleta.ai/docs/errors#auth_unavailable"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "batch_completed": {
      "post": {
        "tags": [
          "Batch"
        ],
        "summary": "Batch completed",
        "description": "Sent when a batch ends as `completed`, `failed` or `partial`: to the `webhook_url` of the batch, if it has one, and to every address registered with `POST /v1/webhooks`. The body is a JSON object with exactly the fields below. Each delivery carries `X-Scarleta-Timestamp` (Unix seconds) and `X-Scarleta-Signature` (`v1=` followed by the lowercase hex HMAC-SHA256 of `<timestamp>.<raw body>`, keyed with your signing secret from `GET /v1/webhooks/signing-secret`). Reject deliveries whose timestamp is more than 300 seconds from your clock. For one day after a rotation a delivery also carries `X-Scarleta-Signature-Previous`, signed with the previous secret; a receiver that has not switched to the new secret yet can verify that header with its old secret. Addresses registered with `POST /v1/webhooks` receive this event too, signed the same way; an address identical to the `webhook_url` is delivered once.\n\nYour endpoint must answer with a 2xx status within 10 seconds. Scarleta makes up to 3 attempts, waiting 2 s and 4 s before the second and third; redirects are not followed. Targets that are not public https endpoints are never called. A batch you cancel sends no `batch_completed`: its `webhook_delivery_status` is `skipped`, and the cancel call itself is the answer. If you retry a batch, the webhook is sent when the retry ends. Each completion starts one delivery sequence to the `webhook_url` of the batch and never a second one, but inside that sequence an attempt that timed out or got a non-2xx answer is sent again with the same body, and the earlier attempt may already have reached you: de-duplicate by `batch_id` and `completed_at`. Registered addresses are delivered at least once, on a best-effort basis: a failed delivery to a registered address can also be sent again when the same completion is replayed, so de-duplicate by `batch_id` and `completed_at` there too. `webhook_delivery_status` on the batch shows the outcome of the delivery to its `webhook_url` only; registered addresses are retried the same way, but their outcome is not shown in that field.",
        "x-scarleta-triggered-by": [
          "submit_batch"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "const": "batch_completed"
                  },
                  "batch_id": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
                    "description": "The batch that ended."
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "completed",
                      "failed",
                      "partial"
                    ],
                    "description": "How the batch ended."
                  },
                  "total_items": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "description": "Items in the batch."
                  },
                  "completed_items": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "failed_items": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "cancelled_items": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991
                  },
                  "actual_total_cost": {
                    "type": "number",
                    "description": "Tokens charged for the whole batch."
                  },
                  "completed_at": {
                    "type": "number",
                    "description": "When the batch ended, in milliseconds since the Unix epoch."
                  }
                },
                "required": [
                  "event",
                  "batch_id",
                  "status",
                  "total_items",
                  "completed_items",
                  "failed_items",
                  "cancelled_items",
                  "actual_total_cost",
                  "completed_at"
                ],
                "additionalProperties": false
              },
              "example": {
                "event": "batch_completed",
                "batch_id": "b1a2c3d4-e5f6-4789-a0b1-c2d3e4f5a6b7",
                "status": "completed",
                "total_items": 2,
                "completed_items": 2,
                "failed_items": 0,
                "cancelled_items": 0,
                "actual_total_cost": 40,
                "completed_at": 1791333895009
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Return any 2xx status to acknowledge the delivery. Any other status, or no answer in time, counts as a failed attempt."
          }
        }
      }
    },
    "recipe_completed": {
      "post": {
        "tags": [
          "Recipes"
        ],
        "summary": "Recipe run completed",
        "description": "Sent when a run finishes, whether it completed or failed: to the `webhook_url` of the run, if it has one, and to every address registered with `POST /v1/webhooks`. A run that is cancelled, or that stalls and is stopped by Scarleta's automatic recovery, sends no `recipe_completed`; read `GET /v1/recipe/jobs/{job_id}` for its final `status`. The body is a JSON object with exactly the fields below. Each delivery carries `X-Scarleta-Timestamp` (Unix seconds) and `X-Scarleta-Signature` (`v1=` followed by the lowercase hex HMAC-SHA256 of `<timestamp>.<raw body>`, keyed with your signing secret from `GET /v1/webhooks/signing-secret`). Reject deliveries whose timestamp is more than 300 seconds from your clock. For one day after a rotation a delivery also carries `X-Scarleta-Signature-Previous`, signed with the previous secret; a receiver that has not switched to the new secret yet can verify that header with its old secret. Addresses registered with `POST /v1/webhooks` receive this event too, signed the same way; an address identical to the `webhook_url` is delivered once.\n\nYour endpoint must answer with a 2xx status within 10 seconds. Scarleta makes up to 3 attempts, waiting 2 s and 4 s before the second and third; redirects are not followed. Targets that are not public https endpoints are never called. A run starts one delivery sequence to its `webhook_url` and never a second one, but inside that sequence an attempt that timed out or got a non-2xx answer is sent again with the same body, and the earlier attempt may already have reached you: de-duplicate by `job_id`. Registered addresses are delivered at least once, on a best-effort basis: a failed delivery to a registered address can also be sent again when the same completion is replayed, so de-duplicate by `job_id` there too. `webhook_delivery_status` on the job shows the outcome of the delivery to its `webhook_url` only. Registered addresses are retried the same way, but their outcome is not shown in that field.",
        "x-scarleta-triggered-by": [
          "execute_recipe"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "const": "recipe_completed"
                  },
                  "job_id": {
                    "type": "string",
                    "description": "The run that ended."
                  },
                  "recipe_id": {
                    "description": "The recipe that ran; null if the run ended before the recipe was read.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "completed",
                      "failed"
                    ],
                    "description": "How the run ended."
                  },
                  "audio_url": {
                    "type": "string",
                    "description": "The audio the run used."
                  },
                  "num_steps": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "description": "Steps in the recipe."
                  },
                  "completed_steps": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "description": "Steps that finished."
                  },
                  "error": {
                    "description": "Why the run failed, or null.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "completed_at": {
                    "type": "number",
                    "description": "When the run ended, in milliseconds since the Unix epoch."
                  }
                },
                "required": [
                  "event",
                  "job_id",
                  "recipe_id",
                  "status",
                  "audio_url",
                  "num_steps",
                  "completed_steps",
                  "error",
                  "completed_at"
                ],
                "additionalProperties": false
              },
              "example": {
                "event": "recipe_completed",
                "job_id": "recipe_9f3a1c7e52b4",
                "recipe_id": "rec_4821_mix_check",
                "status": "completed",
                "audio_url": "https://example.com/track-1.wav",
                "num_steps": 1,
                "completed_steps": 1,
                "error": null,
                "completed_at": 1792586348723
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Return any 2xx status to acknowledge the delivery. Any other status, or no answer in time, counts as a failed attempt."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Send your API key as `Authorization: Bearer <key>`. Paid accounts use keys that start with `scar_live_`; free accounts use keys that start with `sk_free_`."
      }
    },
    "schemas": {
      "Meta": {
        "type": "object",
        "required": [
          "request_id"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Identifier of this request; also returned in the X-Request-ID header."
          }
        }
      },
      "Envelope": {
        "type": "object",
        "description": "Every successful response wraps its payload as `{ data, meta }`.",
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {},
          "meta": {
            "$ref": "#/components/schemas/Meta"
          }
        }
      },
      "LegacyError": {
        "type": "object",
        "description": "A few older routes answer some errors with a plain code instead of the standard Error body: `error` is the code and `message` explains it. The same route may also answer the standard Error body for other errors.",
        "oneOf": [
          {
            "type": "object",
            "required": [
              "error",
              "message"
            ],
            "properties": {
              "error": {
                "type": "string",
                "description": "Stable machine-readable error code."
              },
              "message": {
                "type": "string"
              }
            }
          },
          {
            "$ref": "#/components/schemas/Error"
          }
        ]
      },
      "Error": {
        "type": "object",
        "description": "Every error response has this shape. `docs_url` links to the explanation of `code`.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "request_id",
              "docs_url"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code."
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation."
              },
              "details": {
                "description": "Optional structured detail for this error."
              },
              "request_id": {
                "type": "string"
              },
              "docs_url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}