Die Liederstellen-API erzeugt personalisierte Lieder programmatisch: Anlass und ein paar Details hinein, fertiger Liedtext und produzierte Aufnahme heraus. Reines HTTPS und JSON, kein Pflicht-SDK.
Stand: 2026-10-10
Schlüssel werden manuell vergeben. Eine kurze Mail mit Vorhaben, erwartetem Volumen und Sprachen genügt, die Freischaltung dauert in der Regel einen Werktag.
Die API bildet genau den Ablauf ab, den auch die Website nutzt. Du schickst einen Anlass, den Namen der beschenkten Person und ein paar konkrete Details. Daraus entsteht zuerst ein vollständiger Liedtext, danach eine produzierte Aufnahme mit Gesang, Arrangement und Mischung. Der ganze Vorgang dauert üblicherweise zwei bis drei Minuten.
Alle Anfragen gehen an https://api.liederstellen.de/v1. Die API spricht ausschließlich HTTPS, nimmt JSON entgegen und antwortet mit JSON. Es gibt kein verpflichtendes SDK: jede Sprache, die HTTP kann, reicht aus. Die Beispiele auf dieser Seite verwenden curl, Python und Node, weil das die drei häufigsten Fälle sind.
Jede Domain hat ihre eigene API-Basis und ihren eigenen Preis in der jeweiligen Landeswährung. Ein Schlüssel gilt für die Domain, für die er ausgestellt wurde. Wer mehrere Märkte bedient, bekommt mehrere Schlüssel oder einen Schlüssel mit mehreren freigeschalteten Domains.
Abrechnet wird pro fertiggestelltem Lied, aktuell 29,99 €. Entwürfe, abgebrochene Anfragen und Neugenerierungen kosten nichts.
Es gibt bewusst keine Selbstregistrierung. Wir schalten Schlüssel von Hand frei, weil hinter jedem Lied echte Produktionskosten stehen und wir wissen wollen, wofür die Integration gedacht ist. In der Praxis ist das eine kurze Mail und ein Werktag Wartezeit.
Schreib an songs@maxkuch.com und nenne vier Dinge:
Du bekommst dann zwei Schlüssel: einen Testschlüssel mit dem Präfix sk_test_, der nichts kostet und feste Demo-Aufnahmen liefert, und einen Liveschlüssel mit dem Präfix sk_live_. Beide funktionieren sofort, ohne weitere Freischaltung einzelner Endpunkte.
Jede Anfrage trägt den Schlüssel im Authorization-Header als Bearer-Token. Anfragen ohne gültigen Header beantwortet die API mit 401 und dem Fehlertyp authentication_error.
curl https://api.liederstellen.de/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"occasion": "birthday",
"recipient_name": "Anna",
"relationship": "sister",
"language": "de",
"mood": "happy",
"style": "pop",
"voice": "female",
"details": "Climbs every weekend, always ten minutes late, calls everyone chef.",
"callback_url": "https://example.com/hooks/songs"
}'
Behandle den Schlüssel wie ein Passwort: nur serverseitig verwenden, nie in Frontend-Code, nie in ein öffentliches Repository. Wenn ein Schlüssel abhandenkommt, schreib uns, wir sperren ihn sofort und stellen einen neuen aus. Ein Konto darf mehrere aktive Schlüssel haben, damit sich ein Wechsel ohne Ausfall fahren lässt.
Testschlüssel und Liveschlüssel teilen sich denselben Endpunkt. Ob eine Anfrage im Testmodus lief, steht im Feld livemode jedes Objekts.
Ein Lied zu erzeugen ist ein einziger Aufruf. Die Antwort kommt sofort und enthält eine Song-ID mit dem Status queued. Alles Weitere passiert im Hintergrund.
import os, time, requests
API = "https://api.liederstellen.de/v1"
HEAD = {"Authorization": "Bearer " + os.environ["SONG_API_KEY"]}
song = requests.post(API + "/songs", headers=HEAD, json={
"occasion": "wedding",
"recipient_name": "Lea and Tim",
"relationship": "friends",
"language": "de",
"mood": "romantic",
"details": "Met at a bike repair shop, dog named Miso, both terrible dancers.",
}).json()
while song["status"] not in ("preview_ready", "complete", "failed"):
time.sleep(5)
song = requests.get(API + "/songs/" + song["id"], headers=HEAD).json()
print(song["lyrics"])
print(song["preview_url"])
Das Beispiel pollt der Einfachheit halber im Fünf-Sekunden-Takt. Für den Produktivbetrieb sind Webhooks der bessere Weg, weil sie die offene Verbindung und die Wartezeit sparen. Beides ist unterstützt, Webhooks sind weiter unten beschrieben.
Das wichtigste Feld ist details. Dort stehen die konkreten Dinge über die Person: der Spitzname, die Marotte, der Urlaub, der schiefging. Allgemeine Sätze wie "sie ist ein herzlicher Mensch" ergeben allgemeine Zeilen. Drei bis fünf konkrete Details reichen und machen den Unterschied zwischen nett und wirklich persönlich.
| Methode | Pfad | Zweck |
|---|---|---|
| POST | /v1/songs | Neues Lied in Auftrag geben. |
| GET | /v1/songs/{id} | Ein Lied mit allen aktuellen Feldern abrufen. |
| GET | /v1/songs | Lieder des Kontos auflisten, filterbar und seitenweise. |
| GET | /v1/songs/{id}/lyrics | Nur den Liedtext als reinen Text abrufen. |
| GET | /v1/songs/{id}/audio | Signierte Download-URL für Vorschau oder vollständige Aufnahme. |
| POST | /v1/songs/{id}/regenerate | Kostenlose Neugenerierung anstoßen. |
| POST | /v1/songs/{id}/checkout | Bezahlseite für den Endkunden erzeugen. |
| POST | /v1/songs/{id}/unlock | Lied direkt freischalten und über das Konto abrechnen. |
| GET | /v1/options | Alle gültigen Werte für Anlass, Stimmung, Stil, Stimme und Sprache. |
| GET | /v1/account | Kontostand, Limits und freigeschaltete Domains. |
| DELETE | /v1/songs/{id} | Ein noch nicht fertiges Lied abbrechen. |
POST /v1/songs nimmt die Beschreibung entgegen und legt sofort los. Pflicht sind nur drei Felder, alles andere hat sinnvolle Vorgaben oder wird passend zum Anlass gewählt.
| Feld | Typ | Beschreibung |
|---|---|---|
| string | Pflicht | Anlass. Gültige Werte liefert /v1/options. |
| string | Pflicht | Name der Person, für die das Lied ist. Wird im Text verwendet. |
| string | Pflicht | Konkrete Details über die Person, 40 bis 4000 Zeichen. Das Feld bestimmt die Qualität des Ergebnisses. |
| string | optional | Verhältnis der bestellenden zur beschenkten Person, etwa Schwester, Kollege, Partnerin. |
| string | optional | Sprache, in der gesungen wird. Vorgabe ist de. |
| string | optional | Grundstimmung. Ohne Angabe wählen wir sie passend zum Anlass. |
| string | optional | Musikstil. Ohne Angabe wählen wir ihn passend zu Anlass und Stimmung. |
| string | optional | Gesangsstimme. Ohne Angabe wählen wir sie passend zum Anlass. |
| string | optional | Eine Botschaft, die im Lied vorkommen soll. |
| string | optional | Freitext für alles, was sonst nirgends passt, etwa Wünsche zum Tempo. |
| string | optional | HTTPS-Adresse, an die Ereignisse geschickt werden. |
| object | optional | Frei belegbare Schlüssel-Wert-Paare, maximal 20. Kommen unverändert zurück. |
const res = await fetch("https://api.liederstellen.de/v1/songs", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SONG_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
occasion: "anniversary",
recipient_name: "Mara",
relationship: "partner",
language: "de",
mood: "warm",
details: "Ten years, three apartments, one very loud coffee machine.",
callback_url: "https://example.com/hooks/songs",
metadata: { order_id: "A-10423" },
}),
});
const song = await res.json();
console.log(song.id, song.status);
Der Aufruf kostet nichts. Berechnet wird erst, wenn das Lied über /unlock oder eine bezahlte Checkout-Sitzung freigeschaltet wird.
Jeder Endpunkt, der ein einzelnes Lied zurückgibt, liefert dasselbe Objekt. Felder, die noch nicht feststehen, sind null und füllen sich im Lauf der Produktion.
{
"id": "sng_3n8Kd2ZpQv",
"object": "song",
"status": "queued",
"created_at": "2026-09-16T09:41:02Z",
"occasion": "birthday",
"recipient_name": "Anna",
"relationship": "sister",
"language": "de",
"mood": "happy",
"style": "pop",
"voice": "female",
"lyrics": null,
"preview_url": null,
"audio_url": null,
"duration_seconds": null,
"paid": false,
"price": { "amount": 2999, "currency": "EUR" },
"metadata": {},
"livemode": true
}
| Feld | Typ | Beschreibung |
|---|---|---|
| string | optional | Eindeutige Kennung, beginnt immer mit sng_. |
| string | optional | Aktueller Produktionsstand, siehe nächster Abschnitt. |
| string | optional | Vollständiger Liedtext mit Strophen- und Refrainmarkierungen. Kostenlos, auch ohne Zahlung. |
| string | optional | Die ersten 45 Sekunden als MP3. Dauerhaft abrufbar, keine Zahlung nötig. |
| string | optional | Vollständige Aufnahme als MP3, signiert und 24 Stunden gültig. Erst nach Zahlung gesetzt. |
| integer | optional | Länge der fertigen Aufnahme in Sekunden, üblicherweise zwischen 120 und 240. |
| boolean | optional | Ob das Lied freigeschaltet ist. |
| object | optional | Betrag in kleinster Währungseinheit plus Währungscode, hier 29,99 €. |
| object | optional | Was du beim Erstellen mitgegeben hast, unverändert. |
| boolean | optional | false, wenn die Anfrage mit einem Testschlüssel lief. |
{
"id": "sng_3n8Kd2ZpQv",
"object": "song",
"status": "complete",
"created_at": "2026-09-16T09:41:02Z",
"completed_at": "2026-09-16T09:47:35Z",
"lyrics": "[Verse 1]\nAnna, six in the morning, chalk on your hands ...",
"preview_url": "https://cdn.liederstellen.de/preview/sng_3n8Kd2ZpQv.mp3",
"audio_url": "https://cdn.liederstellen.de/full/sng_3n8Kd2ZpQv.mp3?expires=1789412855&sig=...",
"duration_seconds": 184,
"paid": true,
"price": { "amount": 2999, "currency": "EUR" },
"metadata": { "order_id": "A-10423" },
"livemode": true
}
Ein Lied durchläuft die Zustände in dieser Reihenfolge. Es springt nie zurück, und complete, failed sowie cancelled sind Endzustände.
| Status | Wert | Bedeutung |
|---|---|---|
| queued | Angenommen, wartet auf einen freien Produktionsplatz. Normalerweise wenige Sekunden. | |
| writing_lyrics | Der Liedtext entsteht. | |
| lyrics_ready | Der Text steht vollständig und ist abrufbar. Das ist die erste Stufe; die ganze Produktion dauert meist zwei bis drei Minuten. | |
| generating_audio | Gesang, Arrangement und Mischung werden produziert. | |
| preview_ready | Die ersten 45 Sekunden sind abrufbar, die vollständige Datei liegt bereit. | |
| complete | Bezahlt und vollständig ausgeliefert. | |
| failed | Produktion endgültig gescheitert. Es wird nichts berechnet, das Feld error nennt den Grund. | |
| cancelled | Vor Fertigstellung abgebrochen. |
Ein einzelner fehlgeschlagener Produktionsversuch führt nicht sofort zu failed. Wir wiederholen intern mehrfach und geben erst auf, wenn alle Versuche scheitern. Der Status failed ist deshalb selten und heißt wirklich: dieses Lied kommt nicht.
GET /v1/songs/{id} liefert den aktuellen Stand eines Liedes. Der Endpunkt ist günstig und darf im Sekundentakt abgefragt werden, solange das Ratelimit eingehalten wird.
curl -G https://api.liederstellen.de/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-d status=complete \
-d limit=20 \
-d starting_after=sng_3n8Kd2ZpQv
Listen sind cursorbasiert. Du bekommst maximal limit Einträge, standardmäßig 20 und höchstens 100, absteigend nach Erstellungszeit. Ist has_more wahr, reichst du next_cursor beim nächsten Aufruf als starting_after mit. Filtern kannst du nach status, occasion, language, paid sowie created_after und created_before.
{
"object": "list",
"data": [
{ "id": "sng_9Wq1LmT4bR", "status": "complete", "recipient_name": "Jonas", "...": "..." },
{ "id": "sng_3n8Kd2ZpQv", "status": "complete", "recipient_name": "Anna", "...": "..." }
],
"has_more": true,
"next_cursor": "sng_3n8Kd2ZpQv"
}
Der Liedtext ist kostenlos und vollständig, nicht nur ausschnittsweise. GET /v1/songs/{id}/lyrics gibt ihn als text/plain zurück, mit Markierungen für Strophen und Refrain. Dasselbe steht im Feld lyrics des Song-Objekts.
Beim Audio gibt es zwei Stufen. Die Vorschau umfasst die ersten 45 Sekunden der fertigen Aufnahme, nicht eine gesonderte Demo: dieselbe Stimme, dasselbe Arrangement, derselbe Text. Sie ist ohne Zahlung abrufbar und bleibt es. Die vollständige Datei liefert GET /v1/songs/{id}/audio erst nach Freischaltung.
Beide Adressen sind signiert und 24 Stunden gültig. Sie sind zum Herunterladen gedacht, nicht zum dauerhaften Verlinken. Wenn du eine Datei länger brauchst, lade sie einmal herunter und lege sie bei dir ab. Ein erneuter Aufruf des Endpunkts erzeugt jederzeit eine frische Adresse.
Format ist durchgehend MP3 mit 320 kbit/s. Wer WAV braucht, hängt ?format=wav an, das steht Konten mit Studio-Freischaltung zur Verfügung.
Zu jedem bezahlten Lied lässt sich zusätzlich ein animierter Kurzfilm erstellen: gezeichnete Szenen zu jeder Zeile, Wort für Wort auf den Gesang getaktet, der Liedtext als Untertitel. Der Film ist nicht Teil der API. Erstellt und freigeschaltet wird er vom Endkunden auf der Download-Seite des Liedes: Das Erstellen ist kostenlos und dauert etwa 15 Minuten, die ersten 45 Sekunden laufen als Vorschau, der ganze Film kostet 19,99 €.
Wenn ein Ergebnis nicht passt, kostet die Neugenerierung nichts. POST /v1/songs/{id}/regenerate erzeugt eine neue Fassung unter derselben ID und setzt den Status zurück auf queued. Die bisherige Fassung bleibt unter previous_versions erhalten.
curl https://api.liederstellen.de/v1/songs/sng_3n8Kd2ZpQv/regenerate \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"keep_lyrics": false,
"reason": "voice_not_matching",
"note": "Please try a lower male voice and a slower tempo."
}'
Mit keep_lyrics: true bleibt der Text unverändert und nur die Aufnahme entsteht neu. Das ist der richtige Weg, wenn der Text sitzt und nur die Stimme oder das Tempo danebenlag. Mit false wird auch der Text neu geschrieben.
Das Feld note geht direkt in die Neugenerierung ein, also lohnt sich ein konkreter Satz. "Tiefere Männerstimme, langsamer" wirkt, "besser machen" nicht. Neugeneriert wird, bis das Ergebnis sitzt, bis zu sechs Mal je Lied kostenlos. Danach sprich uns an.
Es gibt zwei Wege, ein Lied freizuschalten, je nachdem, wer bezahlt.
POST /v1/songs/{id}/checkout erzeugt eine gehostete Bezahlseite in der Währung der Domain, inklusive der im jeweiligen Land üblichen Zahlungsarten. Du leitest den Kunden dorthin weiter und bekommst nach erfolgreicher Zahlung das Ereignis song.paid.
curl https://api.liederstellen.de/v1/songs/sng_3n8Kd2ZpQv/checkout \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"success_url": "https://example.com/thanks?song=sng_3n8Kd2ZpQv",
"cancel_url": "https://example.com/cart"
}'
{
"object": "checkout_session",
"song": "sng_3n8Kd2ZpQv",
"url": "https://pay.liederstellen.de/c/cs_live_8Hd2Kq...",
"amount": 2999,
"currency": "EUR",
"expires_at": "2026-09-16T11:41:02Z"
}
Bei Konten mit Sammelabrechnung schaltet POST /v1/songs/{id}/unlock das Lied sofort frei und bucht 29,99 € auf das Konto. Kein Umweg über eine Bezahlseite, sinnvoll für eigene Kassensysteme.
curl https://api.liederstellen.de/v1/songs/sng_3n8Kd2ZpQv/unlock \
-H "Authorization: Bearer $SONG_API_KEY" \
-X POST
In beiden Fällen gilt dasselbe Nutzungsrecht: nicht exklusiv, aber ausdrücklich kommerziell verwendbar. Du darfst das fertige Lied im Rahmen deines Angebots weitergeben, verkaufen und veröffentlichen.
Die Aufzählungen für Anlass, Stimmung, Stil, Stimme und Sprache ändern sich gelegentlich. Statt sie fest einzubauen, frag GET /v1/options ab und halte das Ergebnis ein paar Stunden im Cache.
{
"object": "options",
"language": "de",
"occasions": ["birthday", "wedding", "anniversary", "farewell", "funeral",
"christening", "graduation", "christmas", "declaration", "other"],
"moods": ["happy", "warm", "funny", "romantic", "gentle", "epic", "surprise_me"],
"styles": ["pop", "rock", "folk", "schlager", "hiphop", "ballad", "country",
"electronic", "jazz", "childrens", "surprise_me"],
"voices": ["female", "male", "duet", "choir", "childrens", "surprise_me"],
"languages": ["de", "en", "dk", "nl", "it", "se", "fr", "es", "no", "pl", "fi", "is", "jp"]
}
Jeder dieser Werte darf auch weggelassen werden. Der Wert surprise_me ist kein Platzhalter, sondern eine echte Anweisung: wir wählen dann bewusst etwas, das zum Anlass und zu den Details passt.
Gib beim Erstellen eine callback_url an, und wir schicken jedes Ereignis als POST dorthin. Das ist der empfohlene Weg, weil er Polling und Wartezeit erspart.
| Ereignis | Typ | Ausgelöst wenn |
|---|---|---|
| song.lyrics_ready | Der Liedtext steht vollständig. | |
| song.preview_ready | Die 45-Sekunden-Vorschau ist abrufbar. | |
| song.completed | Die vollständige Aufnahme ist ausgeliefert. | |
| song.failed | Die Produktion ist endgültig gescheitert. | |
| song.regenerated | Eine Neugenerierung ist fertig. | |
| song.paid | Die Zahlung ist eingegangen, das Lied ist freigeschaltet. |
{
"id": "evt_5Tb7Rn2WqX",
"object": "event",
"type": "song.completed",
"created_at": "2026-09-16T09:47:35Z",
"data": {
"object": {
"id": "sng_3n8Kd2ZpQv",
"object": "song",
"status": "complete",
"audio_url": "https://cdn.liederstellen.de/full/sng_3n8Kd2ZpQv.mp3?expires=1789412855&sig=...",
"...": "..."
}
}
}
Jede Zustellung trägt einen Header mit Zeitstempel und HMAC-SHA256 über Zeitstempel, Punkt und Rohkörper. Prüfe ihn, bevor du dem Inhalt glaubst, und verwirf alles, was älter als fünf Minuten ist.
X-Song-Signature: t=1789412855,v1=7f2c1d9a4b6e8035c1f7a29d4e5b0c8371a6d2f94e8b3c07a15d9e2f6b4c8a01
import hashlib, hmac, os, time
from flask import Flask, request, abort
SECRET = os.environ["SONG_WEBHOOK_SECRET"].encode()
app = Flask(__name__)
@app.post("/hooks/songs")
def hook():
header = request.headers.get("X-Song-Signature", "")
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
timestamp, signature = parts.get("t", ""), parts.get("v1", "")
if abs(time.time() - int(timestamp or 0)) > 300:
abort(400) # older than five minutes, treat as replay
expected = hmac.new(
SECRET, (timestamp + "." + request.get_data(as_text=True)).encode(),
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, signature):
abort(400)
event = request.get_json()
if event["type"] == "song.completed":
store(event["data"]["object"])
return "", 200
Wir erwarten innerhalb von zehn Sekunden eine Antwort mit Status 2xx. Bleibt sie aus, wiederholen wir mit wachsendem Abstand acht Mal über 24 Stunden. Zustellungen können sich dabei wiederholen und in seltenen Fällen die Reihenfolge tauschen, also behandle deinen Endpunkt idempotent und richte dich nach created_at, nicht nach der Ankunftszeit.
Jeder POST akzeptiert den Header Idempotency-Key mit einem beliebigen eindeutigen Wert, üblicherweise eine UUID. Kommt derselbe Schlüssel innerhalb von 24 Stunden erneut an, geben wir die ursprüngliche Antwort zurück, statt ein zweites Lied zu erzeugen.
curl https://api.liederstellen.de/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Idempotency-Key: 9f1c7c2e-0a3b-4c8d-9e21-5f7a1b6c3d40" \
-H "Content-Type: application/json" \
-d '{ "occasion": "birthday", "recipient_name": "Anna", "language": "de", "details": "..." }'
Das ist genau der Schutz, den man bei Netzwerkfehlern braucht: Wenn eine Antwort verlorengeht und dein Code die Anfrage wiederholt, entsteht trotzdem nur ein Lied. Schickst du denselben Schlüssel mit abweichendem Körper, antworten wir mit 409 und dem Fehlertyp conflict.
Fehler kommen immer im selben Format, mit maschinenlesbarem type und code, einer lesbaren Meldung und, wo sinnvoll, dem betroffenen Feld. Die request_id gehört in jede Supportanfrage, damit wir den Vorgang in den Protokollen finden.
{
"error": {
"type": "validation_error",
"code": "details_too_short",
"message": "details must contain at least 40 characters so the song has something to work with",
"param": "details",
"request_id": "req_2Lm9Xc4Kd1"
}
}
| Typ | HTTP | Bedeutung |
|---|---|---|
| 400 | invalid_request | Die Anfrage ist formal kaputt, etwa ungültiges JSON oder ein unbekanntes Feld. |
| 401 | authentication_error | Schlüssel fehlt, ist abgelaufen oder gesperrt. |
| 403 | permission_error | Der Schlüssel ist gültig, darf aber diese Domain oder diesen Endpunkt nicht. |
| 404 | not_found | Die angefragte Kennung gehört nicht zu diesem Konto oder existiert nicht. |
| 409 | conflict | Die Aktion passt nicht zum Zustand, etwa Freischalten eines abgebrochenen Liedes. |
| 422 | validation_error | Die Anfrage ist formal in Ordnung, ein Wert aber unbrauchbar, etwa zu kurze Details. |
| 429 | rate_limit | Zu viele Anfragen oder zu viele gleichzeitige Produktionen. |
| 500 | api_error | Fehler auf unserer Seite. Wiederhole mit wachsendem Abstand. |
Bei 429 und 5xx ist eine Wiederholung sinnvoll, am besten mit exponentiell wachsendem Abstand und etwas Zufall. Bei 4xx außer 429 ist sie es nicht: dieselbe Anfrage wird wieder scheitern.
| Grenze | Wert | Gilt für |
|---|---|---|
| 60 / min | Anfragen pro Minute und Schlüssel über alle Endpunkte. | |
| 10 | Gleichzeitig laufende Produktionen. Weitere Anfragen warten in der Warteschlange. | |
| 64 KB | Maximale Größe eines Anfragekörpers. | |
| 40 - 4000 | Zeichen im Feld details, Minimum und Maximum. | |
| 90 | Tage, die wir Lieder und Eingaben aufbewahren, danach werden sie gelöscht. | |
| 24 h | Zeitraum, in dem ein Idempotenzschlüssel die alte Antwort zurückgibt. |
Jede Antwort trägt den aktuellen Stand in den Headern, damit du nicht raten musst.
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1789412880
X-Concurrent-Limit: 10
X-Concurrent-Running: 3
Höhere Limits sind kein Problem, sie sind nur nicht die Voreinstellung. Wenn dein Volumen wächst, schreib uns kurz, dann heben wir sie an.
Die Hauptversion steht im Pfad und bleibt stabil. Innerhalb von v1 kommen nur additive Änderungen: neue Felder, neue Werte in Aufzählungen, neue Endpunkte. Bestehende Felder verschwinden nicht und ändern ihre Bedeutung nicht.
Wer sich zusätzlich absichern will, pinnt einen Stichtag im Header. Ohne Header gilt immer der neueste Stand.
X-Song-Version: 2026-09-01
Dein Code sollte unbekannte Felder in Antworten ignorieren, statt an ihnen zu scheitern. Das ist die einzige Annahme, die wir an Clients stellen.
Schlüssel mit dem Präfix sk_test_ durchlaufen genau dieselben Endpunkte, erzeugen aber keine echte Produktion und kosten nichts. Du bekommst nach wenigen Sekunden einen festen Demo-Liedtext und eine Demo-Aufnahme, und alle Objekte tragen livemode: false.
Damit lassen sich auch die unangenehmen Fälle proben. Bestimmte Namen im Feld recipient_name erzwingen einen bestimmten Ausgang: test_fail führt zu failed, test_slow zu einer Produktion von etwa zehn Minuten, test_ratelimit zu einer 429-Antwort. So lässt sich die Fehlerbehandlung testen, ohne auf einen echten Ausfall zu warten.
Webhooks funktionieren im Testmodus ebenfalls, mit demselben Signaturverfahren und einem eigenen Geheimnis.
Mit der Freischaltung erhältst du ein nicht exklusives, aber ausdrücklich kommerzielles Nutzungsrecht am fertigen Lied. Du darfst es weitergeben, verkaufen, öffentlich abspielen und in dein eigenes Produkt einbetten. Nicht exklusiv heißt: wir behalten das Recht, die Aufnahme selbst zu verwenden, etwa als Beispiel.
Zur Urheberrechtslage bei KI-erzeugter Musik gibt es in vielen Rechtsordnungen noch keine abschließende Klärung. Wir sichern dir vertraglich die Nutzung zu, können aber nicht zusagen, dass an der Aufnahme ein eigenes Urheberrecht entsteht, das du gegen Dritte durchsetzen kannst. Wer darauf angewiesen ist, sollte das vorher rechtlich prüfen lassen.
Eingaben und fertige Lieder bewahren wir 90 Tage auf, danach werden sie gelöscht. Ein früheres Löschen einzelner Lieder geht per DELETE /v1/songs/{id}. Die Angaben aus details nutzen wir ausschließlich für die Produktion des jeweiligen Liedes und nicht zum Training eigener Modelle.
Wenn du Daten deiner Kunden an uns schickst, bist du dafür der Verantwortliche und wir der Auftragsverarbeiter. Einen Auftragsverarbeitungsvertrag bekommst du auf Anfrage.
Fragen, höhere Limits, Auftragsverarbeitungsvertrag, Sonderfälle: songs@maxkuch.com. Nenne bei technischen Problemen die request_id aus der Fehlerantwort, damit wir den Vorgang direkt finden.
Für Integrationen über KI-Agenten gibt es zusätzlich einen Model-Context-Protocol-Server. Der ist unter /mcp/ dokumentiert und benutzt dieselben Schlüssel wie die REST-API.
Schlüssel werden manuell vergeben. Eine kurze Mail mit Vorhaben, erwartetem Volumen und Sprachen genügt, die Freischaltung dauert in der Regel einen Werktag.