{"openapi":"3.1.0","info":{"title":"MVT Public API","version":"1.0.0","description":"Small, stable, REST-shaped subset of the MVT platform for third-party integrations (club websites, CMSs, sponsor reporting tools) and the embeddable gallery widget. Wire convention is deliberately snake_case throughout (bodies, query params, response fields) — this is a distinct, idiomatic REST contract for external integrators, NOT a mirror of the internal camelCase RPC contract used by our own web/worker apps. ISO-8601 timestamps, `{data,next_cursor}` keyset pagination, RFC 7807 (`application/problem+json`) errors throughout."},"servers":[{"url":"https://api-production-4b3c.up.railway.app/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"mvt_live_...","description":"Tenant-scoped API key. Create one in team Settings → API & agent access (owner/admin only). Scopes: `media:read`, `galleries:read`, `identities:read`, `identities:write`, `brands:read`, `brands:write`, `uploads:write`, `creative:write`, `webhooks:manage`. `GET /tags` and `GET /events` are covered by `media:read` — there is no separate `tags:read`/`events:read` scope, since both are facet lookups over media rather than sensitive resources in their own right."}},"schemas":{"Media":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"type":"string","enum":["image","video"]},"state":{"type":"string"},"event_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"caption":{"type":["string","null"]},"alt_text":{"type":["string","null"]},"width":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"duration_ms":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"blurhash":{"type":["string","null"]},"captured_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},"tag_ids":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"brands":{"type":"array","items":{"type":"object","properties":{"brand_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"confidence":{"type":["number","null"]},"confirmed":{"type":"boolean"}},"required":["brand_id","confidence","confirmed"],"additionalProperties":false}},"identities":{"type":"array","items":{"type":"object","properties":{"identity_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"required":["identity_id"],"additionalProperties":false}},"renditions":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"url":{"type":"string","format":"uri"},"width":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["label","url","width","height"],"additionalProperties":false}}},"required":["id","type","state","event_id","caption","alt_text","width","height","duration_ms","blurhash","captured_at","created_at","tag_ids","brands","identities","renditions"],"additionalProperties":false},"MediaList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Media"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]},"Gallery":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"mode":{"type":"string","enum":["dynamic","manual"]},"cover_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["id","name","slug","description","mode","cover_url","created_at"],"additionalProperties":false},"GalleryList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Gallery"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]},"Identity":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string","enum":["athlete","staff","other"]},"shirt_number":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["id","name","slug","kind","shirt_number","created_at"],"additionalProperties":false},"IdentityCreate":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"kind":{"type":"string","enum":["athlete","staff","other"]},"shirt_number":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["name","slug"],"additionalProperties":false},"IdentityList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Identity"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]},"Brand":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"slug":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}},"logo_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["id","name","slug","aliases","logo_url","created_at"],"additionalProperties":false},"BrandCreate":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"aliases":{"type":"array","items":{"type":"string"}}},"required":["name","slug"],"additionalProperties":false},"Processing":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"media_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"state":{"type":"string"},"failure_reason":{"type":["string","null"]},"steps":{"type":"array","items":{"type":"object","properties":{"step":{"type":"string"},"state":{"type":"string","enum":["pending","running","succeeded","failed","skipped"]},"started_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"finished_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"duration_ms":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"error":{"type":["string","null"]}},"required":["step","state","started_at","finished_at","duration_ms","error"],"additionalProperties":false}}},"required":["media_id","state","failure_reason","steps"],"additionalProperties":false},"BrandList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Brand"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]},"Tag":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"slug":{"type":"string"},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["id","name","slug","created_at"],"additionalProperties":false},"TagList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Tag"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]},"Event":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string"},"category":{"type":"string","enum":["match","training","press_conference","post_match","other"]},"starts_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"venue":{"type":["string","null"]},"opponent":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["id","name","category","starts_at","venue","opponent","created_at"],"additionalProperties":false},"EventList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]},"PublicGallery":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string"},"description":{"type":["string","null"]},"cover_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"media_count":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["name","description","cover_url","media_count"],"additionalProperties":false},"PublicMedia":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"type":{"type":"string","enum":["image","video"]},"caption":{"type":["string","null"]},"captured_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}]},"width":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"blurhash":{"type":["string","null"]},"renditions":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"url":{"type":"string","format":"uri"},"width":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"height":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["label","url","width","height"],"additionalProperties":false}}},"required":["id","type","caption","captured_at","width","height","blurhash","renditions"],"additionalProperties":false},"PublicMediaList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicMedia"}},"next_cursor":{"type":["string","null"]}},"required":["data","next_cursor"]},"UploadCreate":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"file_name":{"type":"string"},"mime_type":{"type":"string"},"byte_size":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"event_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"tags":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"captured_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["file_name","mime_type","byte_size"],"additionalProperties":false},"UploadCreated":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"media_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"storage_key":{"type":"string"},"upload_url":{"type":"string","format":"uri"},"complete_url":{"type":"string","format":"uri"},"method":{"type":"string","const":"PUT"},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["media_id","storage_key","upload_url","complete_url","method","expires_at"],"additionalProperties":false},"CreativeCreate":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"request_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"prompt":{"type":"string","minLength":10,"maxLength":8000},"source_media_ids":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"format":{"default":"portrait","type":"string","enum":["square","portrait","story","landscape"]}},"required":["request_id","prompt","source_media_ids","format"],"additionalProperties":false},"Creative":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"prompt":{"type":"string"},"source_media_ids":{"type":"array","items":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},"format":{"type":"string"},"state":{"type":"string","enum":["queued","running","ready","failed"]},"model":{"type":["string","null"]},"output_media_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"output_url":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"error":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"}},"required":["id","prompt","source_media_ids","format","state","model","output_media_id","output_url","error","created_at"],"additionalProperties":false},"Problem":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"detail":{"type":"string"}},"required":["type","title","status","detail"],"additionalProperties":false}}},"paths":{"/media":{"get":{"summary":"List media","description":"Filter by tag, brand, identity, event, category, media type, and captured-date range. Keyset paginated.","parameters":[{"name":"tag","in":"query","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},{"name":"brand","in":"query","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},{"name":"identity","in":"query","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},{"name":"event","in":"query","schema":{"type":"array","items":{"type":"string"}},"style":"form","explode":true},{"name":"category","in":"query","schema":{"type":"string","enum":["match","training","press_conference","post_match","other"]}},{"name":"media_type","in":"query","schema":{"type":"string","enum":["image","video"]}},{"name":"date_from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"date_to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"q","in":"query","schema":{"type":"string","maxLength":500},"description":"Search captions, people, tags, sponsors and video moments. Response includes search_mode/search_notice when semantic search falls back."},{"name":"search_mode","in":"query","schema":{"type":"string","enum":["hybrid","keyword","semantic"],"default":"hybrid"}},{"name":"identity_match","in":"query","schema":{"type":"string","enum":["any","all"],"default":"any"}},{"name":"sort","in":"query","schema":{"type":"string","enum":["relevance","capturedAt","createdAt","name"]}},{"name":"direction","in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaList"}}}},"401":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/media/{id}":{"get":{"summary":"Get media by id","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Media"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/media/{id}/processing":{"get":{"summary":"Get media processing steps","description":"Requires media:read. Poll while processing; states are pending, running, succeeded, failed or skipped.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Processing"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/galleries":{"get":{"summary":"List galleries","parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GalleryList"}}}}}}},"/galleries/{idOrSlug}":{"get":{"summary":"Get gallery by id or slug","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Gallery"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/galleries/{idOrSlug}/media":{"get":{"summary":"List a gallery's media","parameters":[{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaList"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/identities":{"get":{"summary":"List identities","parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityList"}}}}}},"post":{"summary":"Create an identity","description":"Requires identities:write. Slug must be unique within the team.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentityCreate"}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Identity"}}}},"409":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/brands":{"get":{"summary":"List brands","parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandList"}}}}}},"post":{"summary":"Create a brand","description":"Requires brands:write. Slug must be unique within the team.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandCreate"}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Brand"}}}},"409":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/tags":{"get":{"summary":"List tags","description":"Requires `media:read`, not a dedicated `tags:read` scope — tags are a facet of media, not a sensitive resource of their own, so a key granted `media:read` can list them.","parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagList"}}}}}}},"/events":{"get":{"summary":"List events","description":"Requires `media:read`, not a dedicated `events:read` scope — events are a facet of media, not a sensitive resource of their own, so a key granted `media:read` can list them.","parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}}}}},"/uploads":{"post":{"summary":"Presign + register a media upload","description":"Requires uploads:write. PUT bytes to upload_url, then POST complete_url to verify the object and enqueue processing. Upload is not processed before completion.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadCreate"}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadCreated"}}}},"422":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/uploads/{id}/complete":{"post":{"summary":"Complete an uploaded object","description":"Requires uploads:write. Idempotently verifies size and starts the image or video pipeline.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Already processing or finished"},"202":{"description":"Processing queued"},"400":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/creative":{"post":{"summary":"Create a social-image draft","description":"Requires creative:write AND media:read. Reuse request_id for retries with the same brief/references. At most 20 requests per tenant/hour. Does not publish.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreativeCreate"}}}},"responses":{"202":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Creative"}}}},"403":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/creative/{id}":{"get":{"summary":"Get a social draft","description":"Requires media:read. Poll at most every five seconds. Ready drafts include a signed 15-minute output URL.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Creative"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/public/galleries/{shareToken}":{"get":{"summary":"Get a shared gallery (no API key)","security":[],"description":"The share token IS the credential. Pass `?password=` (or `X-Gallery-Password`) if the link is password-protected.","parameters":[{"name":"shareToken","in":"path","required":true,"schema":{"type":"string"}},{"name":"password","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicGallery"}}}},"401":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/public/galleries/{shareToken}/media":{"get":{"summary":"List a shared gallery's media (no API key)","security":[],"parameters":[{"name":"shareToken","in":"path","required":true,"schema":{"type":"string"}},{"name":"password","in":"query","schema":{"type":"string"}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a previous page's `next_cursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicMediaList"}}}},"401":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}}}