SORI

AI-MIDI API

Send HTTP requests to convert MP3 and audio files into editable MIDI.

Use this page when you want to integrate AI-MIDI without the Python SDK. All requests should come from server-side code.

Base URL and Auth

Base URL: https://api.ai-midi.com. Send your API key with Authorization: Bearer. The x-api-key header is also accepted.

shell

1curl "https://api.ai-midi.com/v1/usage" \2  -H "Authorization: Bearer YOUR_API_KEY"

Convert Immediately

Use POST /v1/convert for scripts or backend jobs that can wait for the conversion response. A conversion that finishes within the synchronous wait returns the generated MIDI file. Otherwise the API returns HTTP 202 with a job body containing code=CONVERSION_PENDING and a polling Location. The Python SDK follows that job and downloads the MIDI automatically.

shell

1curl -X POST "https://api.ai-midi.com/v1/convert" \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -F "audio=@song.mp3" \4  -F "model=piano" \5  --output song.mid

Asynchronous Jobs

Use the job flow when your application should upload first, poll status separately, and download the MIDI after completion.

shell

1curl -X POST "https://api.ai-midi.com/v1/transcriptions" \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -F "audio=@song.mp3" \4  -F "model=piano"

json

1{2  "id": "a1b2c3d4e5f6g7h8",3  "status": "queued",4  "model": "piano",5  "audio_duration_seconds": 42.1,6  "credits_used": 12,7  "created_at": "2026-06-30T09:00:00Z",8  "completed_at": null,9  "error": null10}

shell

1curl "https://api.ai-midi.com/v1/transcriptions/a1b2c3d4e5f6g7h8" \2  -H "Authorization: Bearer YOUR_API_KEY"

shell

1curl "https://api.ai-midi.com/v1/transcriptions/a1b2c3d4e5f6g7h8/midi" \2  -H "Authorization: Bearer YOUR_API_KEY" \3  --output song.mid

Idempotency

Send an Idempotency-Key header to make retries safe on POST /v1/convert and POST /v1/transcriptions. Generate the key yourself, such as a UUID, and reuse the same value when you retry a request.

Reusing the same key for the same account returns the original job without creating a second job or charging a second time, so a retry is safe. A new key always starts a new conversion, so re-converting the same file on purpose still works. The key identifies the request intent, not the file. Only reuse a key for the exact same request; using it with different audio or options returns the original job. Keys are remembered for 24 hours, and omitting the header keeps the previous behavior.

On POST /v1/convert, a keyed replay re-streams the same MIDI when it is still available. A queued or processing replay returns the same HTTP 202 pending job without another upload, charge, or dispatch. A failed job or completed job whose MIDI is unavailable returns HTTP 409 JSON with top-level code and detail fields and the existing job nested under job.

shell

1curl -X POST "https://api.ai-midi.com/v1/convert" \2  -H "Authorization: Bearer YOUR_API_KEY" \3  -H "Idempotency-Key: 3f8c1e2a-9b7d-4c6f-8a1b-2d3e4f5a6b7c" \4  -F "audio=@song.mp3" \5  -F "model=piano" \6  --output song.mid

Usage and Credits

Check usage before large batches. 1 credit covers 5 seconds of audio, and each conversion has a 12 credits minimum.

shell

1curl "https://api.ai-midi.com/v1/usage" \2  -H "Authorization: Bearer YOUR_API_KEY"

json

1{2  "credits_total": 540,3  "credits_remaining": 360,4  "credits_used": 180,5  "billing_debt_credits": 0,6  "billing_risk_hold_credits": 0,7  "next_credit_expiry_at": "2027-07-21T09:00:00Z",8  "credits_expiring_next": 360,9  "credits_expired": 0,10  "used_percent": 33.3311}

Endpoints

These are the public HTTP endpoints for API key based access.

GET /v1/usageCheck credit balance and usage for the API key.
POST /v1/convertUpload audio and receive MIDI bytes, or a resumable pending job after the synchronous wait window.
POST /v1/transcriptionsUpload audio and create an asynchronous conversion job.
GET /v1/transcriptions/{id}Poll a conversion job until it is completed or failed.
GET /v1/transcriptions/{id}/midiDownload the MIDI file for a completed asynchronous job.

Upload Fields

These fields are accepted by conversion endpoints as multipart form data.

audioRequired multipart file field. Supported formats: MP3, WAV, FLAC, OGG, or M4A. Maximum file size 50 MB.
modelOptional. "piano" or "guitar". Default is "piano".
bpmOptional. Default is 120.
beatOptional. Default is 4.
barOptional. Default is 4.
input_processing_typeOptional. "original" or "source_separated". Default is "original".
input_processing_targetOptional source separation target: "other", "bass", "drums", or "vocals".

Job Response

The asynchronous job endpoints return this shape.

idConversion job identifier.
statusCurrent job state: "queued", "processing", "completed", or "failed".
modelThe selected transcription model: "piano" or "guitar".
audio_duration_secondsDetected source audio duration.
credits_usedCredits held for this conversion.
download_urlPresent when the job is completed.
errorFailure details when the job fails.

Errors

Error responses use a JSON body with a detail message.

json

1{2  "detail": "Insufficient API credits"3}
401Missing or invalid API key.
402Insufficient API credits.
409MIDI download requested before the job is completed.
413File size exceeds the 50 MB limit.
415Unsupported audio format (file extension not supported: use MP3, WAV, FLAC, OGG, or M4A).
422Audio content or request metadata could not be processed.
500Conversion failed after processing started.
503The conversion service could not queue or process the request. Retry with the same Idempotency-Key.