Generate MIDI Callbacks
Webhook callback payload specification sent to your server when an audio-to-MIDI polyphonic transcription task completes. Delivers granular note pitch, start and end timestamps, and velocities separated by instrument channel.
When Callbacks Are Sent
The SongMesh API automatically triggers an HTTP POST request to your designated callBackUrl under these events:
- Note Transcription Complete (code: 200): Dispatched once multi-channel polyphonic pitch tracking isolates instrument tracks and packages note velocity arrays.
- Audio Decoding Failure (code: 400/500): Dispatched if source audio is inaudible, clipping, or inaccessible.
Webhook Payload Format
{
"code": 200,
"msg": "success",
"data": {
"taskId": "5c798a1209be4a6385cf71e3b699be8e",
"instruments": [
{
"name": "Drums",
"notes": [
{
"pitch": 36,
"start": 0.036,
"end": 0.182,
"velocity": 100
},
{
"pitch": 38,
"start": 0.485,
"end": 0.628,
"velocity": 95
}
]
},
{
"name": "Electric Bass (finger)",
"notes": [
{
"pitch": 40,
"start": 0.036,
"end": 0.48,
"velocity": 110
}
]
}
]
}
}Callback Payload Fields
| Field | Type | Description |
|---|---|---|
code | integer | HTTP status code of task processing (200 = Success, 400/500 = Error). |
msg | string | Status message indicating outcome (e.g. "success"). |
data.taskId | string | Unique identifier matching the taskId returned by POST /api/v1/createTask. |
data.instruments | array | Array of detected instrument channels and polyphonic note sequences. |
data.instruments[].name | string | Instrument classification (e.g. "Drums", "Electric Bass (finger)", "Acoustic Grand Piano"). |
data.instruments[].notes | array | Chronological array of note events occurring on this instrument channel. |
data.instruments[].notes[].pitch | integer | Standard MIDI note number (0 - 127), where 60 represents Middle C (C4). |
data.instruments[].notes[].start | number | Timestamp in seconds marking when the note begins (Note On). |
data.instruments[].notes[].end | number | Timestamp in seconds marking when the note ends (Note Off). |
data.instruments[].notes[].velocity | number | MIDI strike velocity (0 - 127) indicating note loudness / dynamic intensity. |
Receiver Implementation Example
const express = require('express');
const app = express();
app.use(express.json({ limit: '15mb' }));
app.post('/suno-midi-callback', (req, res) => {
const { code, msg, data } = req.body;
const taskId = data?.taskId;
const instruments = data?.instruments || [];
console.log('Received MIDI transcription callback:', {
taskId,
status: code,
message: msg
});
if (code === 200 && data) {
console.log(`Detected ${instruments.length} instrument channels:`);
instruments.forEach(inst => {
console.log(`- ${inst.name}: ${inst.notes.length} note events`);
});
} else {
console.error('MIDI transcription failed:', msg);
}
// Always return HTTP 200 within 15 seconds to acknowledge receipt
return res.status(200).json({ status: 'received' });
});
app.listen(3000, () => {
console.log('MIDI callback server running on port 3000');
});Webhook Security Recommendation
Always verify incoming webhook payloads on your server. Respond with a 200 OK immediately after parsing the payload to prevent redundant delivery retries from the webhook dispatcher.
Polyphonic Pitch Tracking & Channel Mapping
When submitting an audio file to POST /api/v1/createTask (taskType: "generate_midi"), the deep learning transcriber converts waveform harmonics into discrete musical note events:
Notes are classified into discrete channels (Drums, Bass, Piano, Guitars, Synths) allowing direct import into DAWs like Ableton Live, Logic Pro, or FL Studio.
Every note preserves attack dynamic velocity and microsecond-level timing offsets, ensuring expressive human groove is preserved in digital sheet music.
Webhook Delivery & Reliability Protocol
Webhook Receiver Examples
// app/api/webhook/suno-midi/route.ts
import { NextRequest, NextResponse } from 'next/server';
interface MidiNote {
pitch: number;
start: number | string;
end: number | string;
velocity: number;
}
interface MidiInstrument {
name: string;
notes: MidiNote[];
}
interface MidiCallbackPayload {
code: number;
msg: string;
data: {
taskId: string;
instruments?: MidiInstrument[];
};
}
export async function POST(req: NextRequest) {
try {
const payload: MidiCallbackPayload = await req.json();
const { code, msg, data } = payload;
const taskId = data?.taskId;
const instruments = data?.instruments || [];
console.log(`[MIDI Webhook] Task ${taskId} -> Status: ${msg} (Code: ${code})`);
if (code === 200 && data) {
console.log(`Extracted MIDI notes across ${instruments.length} instrument tracks:`);
instruments.forEach((inst) => {
console.log(`Instrument: "${inst.name}" -> ${inst.notes.length} note events`);
});
// Convert to .mid Standard MIDI File (SMF) or save to database
} else {
console.error(`MIDI transcription failed: ${msg}`);
}
// Always acknowledge receipt immediately with HTTP 200
return NextResponse.json({ code: 200, msg: 'success' });
} catch (error) {
console.error('Webhook error:', error);
return NextResponse.json({ code: 500, msg: 'Internal server error' }, { status: 500 });
}
}{
"code": 200,
"msg": "success"
}Ready to integrate Generate MIDI Callbacks?
Create your free account, obtain your Secret Key, and receive polyphonic MIDI note events with 5 free generation credits.