{"openapi": "3.0.3", "info": {"title": "piano.ai2.fun Transcription API", "version": "1.0.0", "description": "Turn a piano performance (audio/video) into MIDI, MusicXML, engraved sheet SVG/PDF, chords and beats."}, "servers": [{"url": "https://piano.ai2.fun/v1"}], "components": {"securitySchemes": {"bearer": {"type": "http", "scheme": "bearer"}}, "schemas": {"Job": {"type": "object", "properties": {"id": {"type": "string"}, "status": {"type": "string", "enum": ["queued", "running", "ready", "error"]}, "stage": {"type": "string"}, "error": {"type": "string", "nullable": true}, "name": {"type": "string"}, "key": {"type": "string", "nullable": true}, "bpm": {"type": "number", "nullable": true}, "duration_s": {"type": "number", "nullable": true}, "created_at": {"type": "number"}, "assets": {"type": "object", "additionalProperties": {"type": "string"}}}}, "Error": {"type": "object", "properties": {"error": {"type": "object", "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}}}}}, "security": [{"bearer": []}], "paths": {"/me": {"get": {"summary": "Key info and this month's usage", "responses": {"200": {"description": "ok"}}}}, "/transcriptions": {"post": {"summary": "Create a transcription job", "description": "JSON {url, name?, style?, tag?, callback_url?} for a media URL you host, or raw binary body (Content-Type audio/* or video/*) with X-Filename, X-Song-Name, X-Callback-Url headers. Third-party platform URLs (Bilibili, YouTube, Xiaohongshu, Douyin…) are rejected.", "responses": {"202": {"description": "job accepted", "content": {"application/json": {"schema": {"type": "object", "properties": {"id": {"type": "string"}, "status": {"type": "string", "enum": ["queued", "running", "ready", "error"]}, "stage": {"type": "string"}, "error": {"type": "string", "nullable": true}, "name": {"type": "string"}, "key": {"type": "string", "nullable": true}, "bpm": {"type": "number", "nullable": true}, "duration_s": {"type": "number", "nullable": true}, "created_at": {"type": "number"}, "assets": {"type": "object", "additionalProperties": {"type": "string"}}}}}}}, "402": {"description": "quota exceeded"}, "422": {"description": "content not allowed"}}}, "get": {"summary": "List this key's jobs", "responses": {"200": {"description": "ok"}}}}, "/transcriptions/{id}": {"get": {"summary": "Job status + asset links", "parameters": [{"name": "id", "in": "path", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "object", "properties": {"id": {"type": "string"}, "status": {"type": "string", "enum": ["queued", "running", "ready", "error"]}, "stage": {"type": "string"}, "error": {"type": "string", "nullable": true}, "name": {"type": "string"}, "key": {"type": "string", "nullable": true}, "bpm": {"type": "number", "nullable": true}, "duration_s": {"type": "number", "nullable": true}, "created_at": {"type": "number"}, "assets": {"type": "object", "additionalProperties": {"type": "string"}}}}}}, "description": "ok"}}}}, "/transcriptions/{id}/assets/{file}": {"get": {"summary": "Download an asset (midi/musicxml/svg/pdf/json)", "responses": {"200": {"description": "file"}}}}}, "x-webhook": {"description": "When callback_url is set, a POST with the Job object is sent on ready/error. Header X-Piano-Signature: t=<unix>,v1=<hex HMAC-SHA256(webhook_secret, \"<t>.<body>\")>. Retried up to 6 times with backoff."}}