Wat de API doet
De familie /mastering van de REST-API van Jam Jam rendert een audiobestand met een preset: ze balanceert de toon, temt sisklanken, stelt de stereobreedte in en brengt het niveau naar een volumedoel (streaming, Apple Music, Deezer, podcast of club), met de instellingen van de webtool op jam-jam.org/app/mastering. Het OpenAPI 3.1-contract staat op jam-jam.org/api/v1/openapi.json en de referentie op jam-jam.org/developers. Een bestand is hoogstens 200 MB en 10 minuten, mono of stereo (bij meer dan twee kanalen worden de eerste twee gebruikt) en wordt verwerkt op 48 kHz. De uitvoer is een WAV van 16 bit (wav-pcm16, de standaard) of 32 bit float (wav-f32); de API biedt geen 24 bit. Het bronbestand wordt verwijderd zodra het gedecodeerd is en het resultaat wordt 24 uur bewaard. Een serverrender is reproduceerbaar (zelfde bestand, zelfde instellingen, zelfde engineVersion), maar niet gegarandeerd bit voor bit gelijk aan de export van de browser.
Een sleutel halen en je toegang controleren
Maak een account aan op jam-jam.org, open Instellingen en dan API-sleutels (jam-jam.org/app/prefs/api-keys) en maak een sleutel met de scopes mastering:read en mastering:write. De sleutel begint met jj_live_, wordt maar één keer getoond, en een account kan er vijf hebben. Bewaar hem in de omgevingsvariabele JAM_JAM_API_KEY, nooit in een repository of op een gedeelde opdrachtregel. Het renderen van een bestand via de API (POST /mastering/jobs) staat open voor elk account: 3 renders per ISO-week met een gratis account, op dezelfde teller als de webtool, zonder plafond met Premium. Het contract lezen en presets opsommen of opslaan staat ook open voor elk account.
Het actuele contract lezen
GET /mastering/capabilities heeft geen sleutel nodig. Het geeft de engineversie, het bereik en de stapgrootte van elke instelling, de volumedoelen, de ingebouwde presets en de limieten, en met een sleutel ook renderAllowed en je tellersaldo. Lees het in plaats van de grenzen vast in te coderen. Vijf ingebouwde presets zijn alleen-lezen en worden gebruikt als preset=builtin:<id>: builtin:balanced, builtin:warm, builtin:bright, builtin:punchy en builtin:crushed. Je kunt ook tot 50 eigen presets opslaan (een naam van hoogstens 60 tekens) met POST /mastering/presets en ze oproepen via hun id.
Het contract lezen (geen sleutel nodig)
curl https://jam-jam.org/api/v1/mastering/capabilities Een bestand renderen met curl
De gang van zaken is die van elke Jam Jam-taak: een POST die 202 antwoordt, pollen tot het einde en dan de download. De header Idempotency-Key (16 tot 80 tekens uit A-Z, a-z, 0-9, _ en -) is verplicht bij elke schrijfactie: dezelfde sleutel met dezelfde inhoud opnieuw sturen geeft dezelfde taak zonder tweede afschrijving. De taak doorloopt queued, decoding, analyzing en rendering en eindigt als done, failed, cancelled of expired; als hij klaar is bevat hij een report met het geïntegreerde volume (LUFS) en de true peak (dBTP) ervoor en erna. Een account heeft hoogstens één actieve render en drie wachtende. De voorbeeldrepository bevat dezelfde stappen als genummerde scripts, van curl/09-mastering-capabilities.sh tot curl/14-mastering-delete.sh.
Renderen met een ingebouwd preset, de taak volgen, de WAV downloaden
# 1. Upload the file with a built-in preset (Idempotency-Key is required)
curl -X POST https://jam-jam.org/api/v1/mastering/jobs \
-H "Authorization: Bearer $JAM_JAM_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-F [email protected] -F preset=builtin:warm -F format=wav-pcm16
# The 202 answer carries the job "id": JOB_ID=<that id>
# 2. Follow the job, honouring Retry-After, until "status" is "done"
curl https://jam-jam.org/api/v1/mastering/jobs/$JOB_ID \
-H "Authorization: Bearer $JAM_JAM_API_KEY"
# 3. Download the mastered WAV
curl -o mix-master.wav https://jam-jam.org/api/v1/mastering/jobs/$JOB_ID/result \
-H "Authorization: Bearer $JAM_JAM_API_KEY" Python en Node
Deze twee fragmenten vatten python/mastering_lib.py en javascript/mastering-lib.mjs uit de voorbeeldrepository github.com/titouannwtt/jam-jam-api-examples samen (MIT-licentie): Python 3.10 of hoger met requests, Node 20 of hoger zonder afhankelijkheden. De volledige scripts voegen een leesbare melding toe bij elke HTTP-code en worden gestart met python mastering.py master mix.wav --preset builtin:warm of node mastering.mjs master mix.wav --preset builtin:warm.
Python (3.10 of hoger, requests)
import os, time, uuid, requests
API = "https://jam-jam.org/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['JAM_JAM_API_KEY']}"}
FINAL = ("done", "failed", "cancelled", "expired")
# 1. Upload the file with a built-in preset. Idempotency-Key is required.
with open("mix.wav", "rb") as audio:
res = requests.post(
f"{API}/mastering/jobs",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
data={"preset": "builtin:warm", "format": "wav-pcm16"},
files={"file": ("mix.wav", audio)},
)
res.raise_for_status()
job = res.json()
# 2. Poll, waiting as long as the server asks.
while job["status"] not in FINAL:
time.sleep(int(res.headers.get("Retry-After") or 2))
res = requests.get(f"{API}/mastering/jobs/{job['id']}", headers=HEADERS)
res.raise_for_status()
job = res.json()
if job["status"] != "done":
raise SystemExit(f"mastering {job['status']}: {job.get('error')}")
before, after = job["report"]["before"], job["report"]["after"]
print(f"LUFS {before['integratedLufs']} -> {after['integratedLufs']}")
# 3. Download the mastered WAV.
audio = requests.get(f"{API}/mastering/jobs/{job['id']}/result", headers=HEADERS)
audio.raise_for_status()
with open("mix-master.wav", "wb") as out:
out.write(audio.content) Node (20 of hoger, zonder afhankelijkheden)
import { openAsBlob } from 'node:fs';
import { writeFile } from 'node:fs/promises';
const API = 'https://jam-jam.org/api/v1';
const headers = { Authorization: `Bearer ${process.env.JAM_JAM_API_KEY}` };
const FINAL = ['done', 'failed', 'cancelled', 'expired'];
// 1. Upload the file with a built-in preset. Idempotency-Key is required.
const body = new FormData();
body.append('file', await openAsBlob('mix.wav'), 'mix.wav');
body.append('preset', 'builtin:warm');
body.append('format', 'wav-pcm16');
let res = await fetch(`${API}/mastering/jobs`, {
method: 'POST',
headers: { ...headers, 'Idempotency-Key': crypto.randomUUID() },
body,
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
let job = await res.json();
// 2. Poll, waiting as long as the server asks.
while (!FINAL.includes(job.status)) {
await new Promise((r) => setTimeout(r, (Number(res.headers.get('retry-after')) || 2) * 1000));
res = await fetch(`${API}/mastering/jobs/${job.id}`, { headers });
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
job = await res.json();
}
if (job.status !== 'done') throw new Error(`mastering ${job.status}: ${JSON.stringify(job.error)}`);
const { before, after } = job.report;
console.log(`LUFS ${before.integratedLufs} -> ${after.integratedLufs}`);
// 3. Download the mastered WAV.
res = await fetch(`${API}/mastering/jobs/${job.id}/result`, { headers });
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
await writeFile('mix-master.wav', Buffer.from(await res.arrayBuffer())); Je eigen instellingen
In plaats van een preset stuur je de instellingen als JSON in het veld settings: precies een van de twee, preset of settings. Het formaat (MasteringSettingsV1) bevat acht modules, elk met een value en een vlag enabled, een volumedoel (streaming, apple, deezer, podcast of club) en normalize. Toonregelingen zijn in decibel en de rest in procenten, tot 150; een waarde buiten het bereik of buiten de stap antwoordt 422 invalid-settings met een regel per probleem. Om een set instellingen te hergebruiken sla je hem op met POST /mastering/presets en geef je zijn id mee in preset. Instellingen worden bij het uploaden gekopieerd: het preset achteraf wijzigen verandert een al gestarte taak niet.
Je eigen instellingen sturen
{
"modules": {
"autoEq": { "value": 50, "enabled": true },
"lows": { "value": 2, "enabled": true },
"mids": { "value": -0.5, "enabled": true },
"highs": { "value": -1.5, "enabled": true },
"deEss": { "value": 40, "enabled": true },
"width": { "value": 10, "enabled": true },
"loudness": { "value": 45, "enabled": true },
"destruct": { "value": 0, "enabled": false }
},
"target": "streaming",
"normalize": false
} Je eigen instellingen sturen
curl -X POST https://jam-jam.org/api/v1/mastering/jobs \
-H "Authorization: Bearer $JAM_JAM_API_KEY" -H "Idempotency-Key: $(uuidgen)" \
-F [email protected] -F "settings=<samples/mastering-settings.json" -F format=wav-pcm16 Een hele map in batch masteren
De repository bevat twee batchscripts, python/mastering_batch.py en javascript/mastering-batch.mjs, die een map met één preset masteren, het ene bestand na het andere. Drie keuzes zijn het overnemen waard. Bestanden gaan één voor één, omdat een account één actieve render en drie wachtende toestaat. Een bestand waarvan naam-master.wav al bestaat wordt overgeslagen, dus je kunt na een onderbreking opnieuw starten. Bij een 429 met korte wachttijd (hoogstens vijf minuten) wacht het script op Retry-After en stuurt hetzelfde bestand opnieuw met dezelfde idempotentiesleutel, en het stopt bij een 403 of een lange 429, omdat de volgende bestanden net zo zouden mislukken.
Een map masteren, één bestand per keer
python mastering_batch.py ~/Music/mixes --preset builtin:balanced --out masters
node mastering-batch.mjs ~/Music/mixes --preset builtin:balanced --out masters Fouten en quota
Elke fout is een application/problem+json met een stabiele code die je kunt testen, en renderantwoorden bevatten de headers X-Mastering-Quota-Limit, X-Mastering-Quota-Remaining en X-Mastering-Quota-Reset. Premium-accounts hebben geen plafond op het aantal renders. Bij een gratis account betekent een 429 met de code quota-exhausted dat de renders van de week op zijn; elke andere 429 betekent een snelheidslimiet of een drukke wachtrij. Een mislukte of geannuleerde render telt niet mee. Het renderen van een bestand via de API (POST /mastering/jobs) staat open voor elk account: 3 renders per ISO-week met een gratis account, op dezelfde teller als de webtool, zonder plafond met Premium. Het contract lezen en presets opsommen of opslaan staat ook open voor elk account.
| Status | Code | Betekenis |
|---|---|---|
| 401 | Sleutel ontbreekt of is ongeldig. | |
| 403 | insufficient-scope | De sleutel mist de scope mastering:read of mastering:write. |
| 403 | premium-required | Renderen staat niet open voor jouw abonnement (zie renderAllowed in GET /mastering/capabilities). |
| 409 | not-ready | Resultaat gevraagd voordat de render klaar is. |
| 410 | expired | De 24 uur zijn voorbij: render opnieuw. |
| 413, 415, 422 | Bestand te groot, formaat niet ondersteund, audio langer dan 10 minuten of ongeldige instellingen (lees errors[]). | |
| 429 | rate-limited | Te veel verzoeken, of al een render bezig en drie wachtend (client-quota), of een volle wachtrij (queue-full): wacht Retry-After seconden en loop niet in een lus. |
De MCP-server voor assistenten
De officiële MCP-server @jam-jam/convert-mcp biedt Mastering aan Claude Desktop, Claude Code, Cursor en andere Model Context Protocol-clients en toont alleen de tools die de scopes van je sleutel toestaan. Zes tools dekken Mastering: jj_mastering_capabilities (zonder scope), jj_list_mastering_presets, jj_create_mastering_preset, jj_master_audio, jj_mastering_get_job en jj_mastering_cancel_job. jj_master_audio uploadt een lokaal bestand met een preset of inline instellingen en wacht met maxWaitMs op het resultaat en downloadt het. Je kunt je assistent dan vragen een bestand te masteren met het preset warm en je het volume ervoor en erna te geven. Zet de sleutel in de omgeving, nooit op een opdrachtregel.
Configuratie van een MCP-client
{
"mcpServers": {
"jam-jam": {
"command": "npx",
"args": ["-y", "@jam-jam/convert-mcp"],
"env": { "JAM_JAM_API_KEY": "jj_live_..." }
}
}
} Om te begrijpen wat de instellingen doen en op welk volume je moet mikken, lees onze gids om gratis een nummer te masteren.
Veelgestelde vragen over de mastering-API
Is de mastering-API van Jam Jam gratis?
Ja. Met een gratis account rendert POST /mastering/jobs 3 bestanden per ISO-week, op dezelfde teller als de webtool; een mislukte of geannuleerde render wordt teruggegeven. Premium haalt het plafond weg. Het actuele contract lezen en je presets beheren kost niets.
Wat zijn de bestandslimieten?
Hoogstens 200 MB en 10 minuten, mono of stereo. Het resultaat is een WAV van 48 kHz, 16 bit, 24 bit of 32 bit float, 24 uur bewaard.
Is het resultaat identiek aan dat van de browser?
Het is op de server reproduceerbaar (zelfde bestand, zelfde instellingen, zelfde engineVersion), maar niet gegarandeerd bit voor bit gelijk aan de export van de browser. De instellingen zijn dezelfde.
Kan ik meerdere bestanden tegelijk sturen?
Een account heeft één actieve render en drie wachtende. Stuur voor een map de bestanden één voor één met de batchscripts van de voorbeeldrepository.
Hoe gebruik ik het met een AI-assistent?
Met de MCP-server @jam-jam/convert-mcp: de tool jj_master_audio masterd een lokaal bestand en jj_mastering_get_job leest het volume ervoor en erna.
Dezelfde engine kun je gratis proberen in je browser, met je bestand op je apparaat.