← Liederstellen

API-Dokumentation

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

Zugang anfragen

Schlüssel werden manuell vergeben. Eine kurze Mail mit Vorhaben, erwartetem Volumen und Sprachen genügt, die Freischaltung dauert in der Regel einen Werktag.

Zugang anfragen

Einführung

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.

Zugang

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:

  • Was du bauen willst, in zwei bis drei Sätzen.
  • Ungefähres Volumen pro Monat.
  • In welchen Sprachen die Lieder gesungen werden sollen.
  • Ob du Webhooks empfangen kannst oder lieber pollst.

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.

Authentifizierung

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.

bash Vollständige Anfrage mit Header
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.

Schnellstart

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.

python Erstellen und auf die Vorschau warten (Python)
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.

Endpunkte im Überblick

MethodePfadZweck
POST/v1/songsNeues Lied in Auftrag geben.
GET/v1/songs/{id}Ein Lied mit allen aktuellen Feldern abrufen.
GET/v1/songsLieder des Kontos auflisten, filterbar und seitenweise.
GET/v1/songs/{id}/lyricsNur den Liedtext als reinen Text abrufen.
GET/v1/songs/{id}/audioSignierte Download-URL für Vorschau oder vollständige Aufnahme.
POST/v1/songs/{id}/regenerateKostenlose Neugenerierung anstoßen.
POST/v1/songs/{id}/checkoutBezahlseite für den Endkunden erzeugen.
POST/v1/songs/{id}/unlockLied direkt freischalten und über das Konto abrechnen.
GET/v1/optionsAlle gültigen Werte für Anlass, Stimmung, Stil, Stimme und Sprache.
GET/v1/accountKontostand, Limits und freigeschaltete Domains.
DELETE/v1/songs/{id}Ein noch nicht fertiges Lied abbrechen.

Lied erstellen

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.

FeldTypBeschreibung
stringPflichtAnlass. Gültige Werte liefert /v1/options.
stringPflichtName der Person, für die das Lied ist. Wird im Text verwendet.
stringPflichtKonkrete Details über die Person, 40 bis 4000 Zeichen. Das Feld bestimmt die Qualität des Ergebnisses.
stringoptionalVerhältnis der bestellenden zur beschenkten Person, etwa Schwester, Kollege, Partnerin.
stringoptionalSprache, in der gesungen wird. Vorgabe ist de.
stringoptionalGrundstimmung. Ohne Angabe wählen wir sie passend zum Anlass.
stringoptionalMusikstil. Ohne Angabe wählen wir ihn passend zu Anlass und Stimmung.
stringoptionalGesangsstimme. Ohne Angabe wählen wir sie passend zum Anlass.
stringoptionalEine Botschaft, die im Lied vorkommen soll.
stringoptionalFreitext für alles, was sonst nirgends passt, etwa Wünsche zum Tempo.
stringoptionalHTTPS-Adresse, an die Ereignisse geschickt werden.
objectoptionalFrei belegbare Schlüssel-Wert-Paare, maximal 20. Kommen unverändert zurück.
javascript Erstellen mit Idempotenzschlüssel (Node)
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.

Das Song-Objekt

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.

json Direkt nach dem Erstellen
{
  "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
}
FeldTypBeschreibung
stringoptionalEindeutige Kennung, beginnt immer mit sng_.
stringoptionalAktueller Produktionsstand, siehe nächster Abschnitt.
stringoptionalVollständiger Liedtext mit Strophen- und Refrainmarkierungen. Kostenlos, auch ohne Zahlung.
stringoptionalDie ersten 45 Sekunden als MP3. Dauerhaft abrufbar, keine Zahlung nötig.
stringoptionalVollständige Aufnahme als MP3, signiert und 24 Stunden gültig. Erst nach Zahlung gesetzt.
integeroptionalLänge der fertigen Aufnahme in Sekunden, üblicherweise zwischen 120 und 240.
booleanoptionalOb das Lied freigeschaltet ist.
objectoptionalBetrag in kleinster Währungseinheit plus Währungscode, hier 29,99 €.
objectoptionalWas du beim Erstellen mitgegeben hast, unverändert.
booleanoptionalfalse, wenn die Anfrage mit einem Testschlüssel lief.
json Nach Abschluss und Zahlung
{
  "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
}

Statuswerte

Ein Lied durchläuft die Zustände in dieser Reihenfolge. Es springt nie zurück, und complete, failed sowie cancelled sind Endzustände.

StatusWertBedeutung
queuedAngenommen, wartet auf einen freien Produktionsplatz. Normalerweise wenige Sekunden.
writing_lyricsDer Liedtext entsteht.
lyrics_readyDer Text steht vollständig und ist abrufbar. Das ist die erste Stufe; die ganze Produktion dauert meist zwei bis drei Minuten.
generating_audioGesang, Arrangement und Mischung werden produziert.
preview_readyDie ersten 45 Sekunden sind abrufbar, die vollständige Datei liegt bereit.
completeBezahlt und vollständig ausgeliefert.
failedProduktion endgültig gescheitert. Es wird nichts berechnet, das Feld error nennt den Grund.
cancelledVor 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.

Abrufen und auflisten

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.

bash Auflisten mit Filter und Seitenzeiger
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.

json Antwort einer Liste
{
  "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"
}

Liedtext und Audio

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 €.

Neu generieren

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.

bash Neugenerierung mit Begründung
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.

Bezahlen und freischalten

Es gibt zwei Wege, ein Lied freizuschalten, je nachdem, wer bezahlt.

Der Endkunde 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.

bash Bezahlseite erzeugen
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"
  }' 
json Antwort
{
  "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"
}

Du bezahlst

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.

bash Direkt freischalten
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.

Gültige Werte

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.

json Antwort
{
  "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.

Webhooks

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.

EreignisTypAusgelöst wenn
song.lyrics_readyDer Liedtext steht vollständig.
song.preview_readyDie 45-Sekunden-Vorschau ist abrufbar.
song.completedDie vollständige Aufnahme ist ausgeliefert.
song.failedDie Produktion ist endgültig gescheitert.
song.regeneratedEine Neugenerierung ist fertig.
song.paidDie Zahlung ist eingegangen, das Lied ist freigeschaltet.
json Beispiel-Payload
{
  "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=...",
      "...": "..."
    }
  }
}

Signatur prüfen

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.

http Signaturheader
X-Song-Signature: t=1789412855,v1=7f2c1d9a4b6e8035c1f7a29d4e5b0c8371a6d2f94e8b3c07a15d9e2f6b4c8a01
python Prüfung in Python
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

Wiederholungen

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.

Idempotenz

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.

bash Wiederholungssichere Anfrage
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

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.

json Fehlerobjekt
{
  "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"
  }
}
TypHTTPBedeutung
400invalid_requestDie Anfrage ist formal kaputt, etwa ungültiges JSON oder ein unbekanntes Feld.
401authentication_errorSchlüssel fehlt, ist abgelaufen oder gesperrt.
403permission_errorDer Schlüssel ist gültig, darf aber diese Domain oder diesen Endpunkt nicht.
404not_foundDie angefragte Kennung gehört nicht zu diesem Konto oder existiert nicht.
409conflictDie Aktion passt nicht zum Zustand, etwa Freischalten eines abgebrochenen Liedes.
422validation_errorDie Anfrage ist formal in Ordnung, ein Wert aber unbrauchbar, etwa zu kurze Details.
429rate_limitZu viele Anfragen oder zu viele gleichzeitige Produktionen.
500api_errorFehler 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.

Limits

GrenzeWertGilt für
60 / minAnfragen pro Minute und Schlüssel über alle Endpunkte.
10Gleichzeitig laufende Produktionen. Weitere Anfragen warten in der Warteschlange.
64 KBMaximale Größe eines Anfragekörpers.
40 - 4000Zeichen im Feld details, Minimum und Maximum.
90Tage, die wir Lieder und Eingaben aufbewahren, danach werden sie gelöscht.
24 hZeitraum, 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.

http Ratelimit-Header
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.

Versionierung

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.

http Version festnageln
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.

Testmodus

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.

Rechte und Daten

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.

Support

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.

Zugang anfragen

Schlüssel werden manuell vergeben. Eine kurze Mail mit Vorhaben, erwartetem Volumen und Sprachen genügt, die Freischaltung dauert in der Regel einen Werktag.

Zugang anfragen