← 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-09-16

Zugang anfragen

Schluessel werden manuell vergeben. Eine kurze Mail mit Vorhaben, erwartetem Volumen und Sprachen genuegt, die Freischaltung dauert in der Regel einen Werktag.

Zugang anfragen

Einfuehrung

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 vollstaendiger Liedtext, danach eine produzierte Aufnahme mit Gesang, Arrangement und Mischung. Der ganze Vorgang dauert ueblicherweise fuenf bis zehn Minuten.

Alle Anfragen gehen an https://api.liederstellen.at/v1. Die API spricht ausschliesslich 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 haeufigsten Faelle sind.

Jede Domain hat ihre eigene API-Basis und ihren eigenen Preis in der jeweiligen Landeswaehrung. Ein Schluessel gilt fuer die Domain, fuer die er ausgestellt wurde. Wer mehrere Maerkte bedient, bekommt mehrere Schluessel oder einen Schluessel mit mehreren freigeschalteten Domains.

Abrechnet wird pro fertiggestelltem Lied, aktuell 29,99 €. Entwuerfe, abgebrochene Anfragen und Neugenerierungen kosten nichts.

Zugang

Es gibt bewusst keine Selbstregistrierung. Wir schalten Schluessel von Hand frei, weil hinter jedem Lied echte Produktionskosten stehen und wir wissen wollen, wofuer 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 Saetzen.
  • Ungefaehres Volumen pro Monat.
  • In welchen Sprachen die Lieder gesungen werden sollen.
  • Ob du Webhooks empfangen kannst oder lieber pollst.

Du bekommst dann zwei Schluessel: einen Testschluessel mit dem Praefix sk_test_, der nichts kostet und feste Demo-Aufnahmen liefert, und einen Liveschluessel mit dem Praefix sk_live_. Beide funktionieren sofort, ohne weitere Freischaltung einzelner Endpunkte.

Authentifizierung

Jede Anfrage traegt den Schluessel im Authorization-Header als Bearer-Token. Anfragen ohne gueltigen Header beantwortet die API mit 401 und dem Fehlertyp authentication_error.

bash Vollstaendige Anfrage mit Header
curl https://api.liederstellen.at/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 Schluessel wie ein Passwort: nur serverseitig verwenden, nie in Frontend-Code, nie in ein oeffentliches Repository. Wenn ein Schluessel abhandenkommt, schreib uns, wir sperren ihn sofort und stellen einen neuen aus. Ein Konto darf mehrere aktive Schluessel haben, damit sich ein Wechsel ohne Ausfall fahren laesst.

Testschluessel und Liveschluessel 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 enthaelt 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.at/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 Fuenf-Sekunden-Takt. Fuer den Produktivbetrieb sind Webhooks der bessere Weg, weil sie die offene Verbindung und die Wartezeit sparen. Beides ist unterstuetzt, Webhooks sind weiter unten beschrieben.

Das wichtigste Feld ist details. Dort stehen die konkreten Dinge ueber die Person: der Spitzname, die Marotte, der Urlaub, der schiefging. Allgemeine Saetze wie "sie ist ein herzlicher Mensch" ergeben allgemeine Zeilen. Drei bis fuenf konkrete Details reichen und machen den Unterschied zwischen nett und wirklich persoenlich.

Endpunkte im Ueberblick

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 fuer Vorschau oder vollstaendige Aufnahme.
POST/v1/songs/{id}/regenerateKostenlose Neugenerierung anstossen.
POST/v1/songs/{id}/checkoutBezahlseite fuer den Endkunden erzeugen.
POST/v1/songs/{id}/unlockLied direkt freischalten und ueber das Konto abrechnen.
GET/v1/optionsAlle gueltigen Werte fuer 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 gewaehlt.

FeldTypBeschreibung
stringPflichtAnlass. Gueltige Werte liefert /v1/options.
stringPflichtName der Person, fuer die das Lied ist. Wird im Text verwendet.
stringPflichtKonkrete Details ueber die Person, 40 bis 4000 Zeichen. Das Feld bestimmt die Qualitaet des Ergebnisses.
stringoptionalVerhaeltnis der bestellenden zur beschenkten Person, etwa Schwester, Kollege, Partnerin.
stringoptionalSprache, in der gesungen wird. Vorgabe ist de.
stringoptionalGrundstimmung. Ohne Angabe waehlen wir sie passend zum Anlass.
stringoptionalMusikstil. Ohne Angabe waehlen wir ihn passend zu Anlass und Stimmung.
stringoptionalGesangsstimme. Ohne Angabe waehlen wir sie passend zum Anlass.
stringoptionalEine Botschaft, die im Lied vorkommen soll.
stringoptionalFreitext fuer alles, was sonst nirgends passt, etwa Wuensche zum Tempo.
stringoptionalHTTPS-Adresse, an die Ereignisse geschickt werden.
objectoptionalFrei belegbare Schluessel-Wert-Paare, maximal 20. Kommen unveraendert zurueck.
javascript Erstellen mit Idempotenzschluessel (Node)
const res = await fetch("https://api.liederstellen.at/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 ueber /unlock oder eine bezahlte Checkout-Sitzung freigeschaltet wird.

Das Song-Objekt

Jeder Endpunkt, der ein einzelnes Lied zurueckgibt, liefert dasselbe Objekt. Felder, die noch nicht feststehen, sind null und fuellen 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 naechster Abschnitt.
stringoptionalVollstaendiger Liedtext mit Strophen- und Refrainmarkierungen. Kostenlos, auch ohne Zahlung.
stringoptionalDie ersten 45 Sekunden als MP3. Dauerhaft abrufbar, keine Zahlung noetig.
stringoptionalVollstaendige Aufnahme als MP3, signiert und 24 Stunden gueltig. Erst nach Zahlung gesetzt.
integeroptionalLaenge der fertigen Aufnahme in Sekunden, ueblicherweise zwischen 120 und 240.
booleanoptionalOb das Lied freigeschaltet ist.
objectoptionalBetrag in kleinster Waehrungseinheit plus Waehrungscode, hier 29,99 €.
objectoptionalWas du beim Erstellen mitgegeben hast, unveraendert.
booleanoptionalfalse, wenn die Anfrage mit einem Testschluessel 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.at/preview/sng_3n8Kd2ZpQv.mp3",
  "audio_url": "https://cdn.liederstellen.at/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 durchlaeuft die Zustaende in dieser Reihenfolge. Es springt nie zurueck, und complete, failed sowie cancelled sind Endzustaende.

StatusWertBedeutung
queuedAngenommen, wartet auf einen freien Produktionsplatz. Normalerweise wenige Sekunden.
writing_lyricsDer Liedtext entsteht.
lyrics_readyDer Text steht vollstaendig und ist abrufbar. Meist nach ein bis zwei Minuten erreicht.
generating_audioGesang, Arrangement und Mischung werden produziert.
preview_readyDie ersten 45 Sekunden sind abrufbar, die vollstaendige Datei liegt bereit.
completeBezahlt und vollstaendig ausgeliefert.
failedProduktion endgueltig gescheitert. Es wird nichts berechnet, das Feld error nennt den Grund.
cancelledVor Fertigstellung abgebrochen.

Ein einzelner fehlgeschlagener Produktionsversuch fuehrt nicht sofort zu failed. Wir wiederholen intern mehrfach und geben erst auf, wenn alle Versuche scheitern. Der Status failed ist deshalb selten und heisst wirklich: dieses Lied kommt nicht.

Abrufen und auflisten

GET /v1/songs/{id} liefert den aktuellen Stand eines Liedes. Der Endpunkt ist guenstig und darf im Sekundentakt abgefragt werden, solange das Ratelimit eingehalten wird.

bash Auflisten mit Filter und Seitenzeiger
curl -G https://api.liederstellen.at/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 Eintraege, standardmaessig 20 und hoechstens 100, absteigend nach Erstellungszeit. Ist has_more wahr, reichst du next_cursor beim naechsten 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 vollstaendig, nicht nur ausschnittsweise. GET /v1/songs/{id}/lyrics gibt ihn als text/plain zurueck, mit Markierungen fuer 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 vollstaendige Datei liefert GET /v1/songs/{id}/audio erst nach Freischaltung.

Beide Adressen sind signiert und 24 Stunden gueltig. Sie sind zum Herunterladen gedacht, nicht zum dauerhaften Verlinken. Wenn du eine Datei laenger 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, haengt ?format=wav an, das steht Konten mit Studio-Freischaltung zur Verfuegung.

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 zurueck auf queued. Die bisherige Fassung bleibt unter previous_versions erhalten.

bash Neugenerierung mit Begruendung
curl https://api.liederstellen.at/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 unveraendert 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 Maennerstimme, langsamer" wirkt, "besser machen" nicht. Drei Neugenerierungen pro Lied sind frei, 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 Waehrung der Domain, inklusive der im jeweiligen Land ueblichen Zahlungsarten. Du leitest den Kunden dorthin weiter und bekommst nach erfolgreicher Zahlung das Ereignis song.paid.

bash Bezahlseite erzeugen
curl https://api.liederstellen.at/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.at/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 ueber eine Bezahlseite, sinnvoll fuer eigene Kassensysteme.

bash Direkt freischalten
curl https://api.liederstellen.at/v1/songs/sng_3n8Kd2ZpQv/unlock \
  -H "Authorization: Bearer $SONG_API_KEY" \
  -X POST

In beiden Faellen gilt dasselbe Nutzungsrecht: nicht exklusiv, aber ausdruecklich kommerziell verwendbar. Du darfst das fertige Lied im Rahmen deines Angebots weitergeben, verkaufen und veroeffentlichen.

Gueltige Werte

Die Aufzaehlungen fuer Anlass, Stimmung, Stil, Stimme und Sprache aendern 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 waehlen 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.

EreignisTypAusgeloest wenn
song.lyrics_readyDer Liedtext steht vollstaendig.
song.preview_readyDie 45-Sekunden-Vorschau ist abrufbar.
song.completedDie vollstaendige Aufnahme ist ausgeliefert.
song.failedDie Produktion ist endgueltig 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.at/full/sng_3n8Kd2ZpQv.mp3?expires=1789412855&sig=...",
      "...": "..."
    }
  }
}

Signatur pruefen

Jede Zustellung traegt einen Header mit Zeitstempel und HMAC-SHA256 ueber Zeitstempel, Punkt und Rohkoerper. Pruefe ihn, bevor du dem Inhalt glaubst, und verwirf alles, was aelter als fuenf Minuten ist.

http Signaturheader
X-Song-Signature: t=1789412855,v1=7f2c1d9a4b6e8035c1f7a29d4e5b0c8371a6d2f94e8b3c07a15d9e2f6b4c8a01
python Pruefung 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 ueber 24 Stunden. Zustellungen koennen sich dabei wiederholen und in seltenen Faellen 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, ueblicherweise eine UUID. Kommt derselbe Schluessel innerhalb von 24 Stunden erneut an, geben wir die urspruengliche Antwort zurueck, statt ein zweites Lied zu erzeugen.

bash Wiederholungssichere Anfrage
curl https://api.liederstellen.at/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 Schluessel mit abweichendem Koerper, 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 gehoert 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 ungueltiges JSON oder ein unbekanntes Feld.
401authentication_errorSchluessel fehlt, ist abgelaufen oder gesperrt.
403permission_errorDer Schluessel ist gueltig, darf aber diese Domain oder diesen Endpunkt nicht.
404not_foundDie angefragte Kennung gehoert 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 ausser 429 ist sie es nicht: dieselbe Anfrage wird wieder scheitern.

Limits

GrenzeWertGilt fuer
60 / minAnfragen pro Minute und Schluessel ueber alle Endpunkte.
10Gleichzeitig laufende Produktionen. Weitere Anfragen warten in der Warteschlange.
64 KBMaximale Groesse eines Anfragekoerpers.
40 - 4000Zeichen im Feld details, Minimum und Maximum.
90Tage, die wir Lieder und Eingaben aufbewahren, danach werden sie geloescht.
24 hZeitraum, in dem ein Idempotenzschluessel die alte Antwort zurueckgibt.

Jede Antwort traegt 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

Hoehere Limits sind kein Problem, sie sind nur nicht die Voreinstellung. Wenn dein Volumen waechst, schreib uns kurz, dann heben wir sie an.

Versionierung

Die Hauptversion steht im Pfad und bleibt stabil. Innerhalb von v1 kommen nur additive Aenderungen: neue Felder, neue Werte in Aufzaehlungen, neue Endpunkte. Bestehende Felder verschwinden nicht und aendern ihre Bedeutung nicht.

Wer sich zusaetzlich 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

Schluessel mit dem Praefix 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 Faelle proben. Bestimmte Namen im Feld recipient_name erzwingen einen bestimmten Ausgang: test_fail fuehrt zu failed, test_slow zu einer Produktion von etwa zehn Minuten, test_ratelimit zu einer 429-Antwort. So laesst 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 erhaeltst du ein nicht exklusives, aber ausdruecklich kommerzielles Nutzungsrecht am fertigen Lied. Du darfst es weitergeben, verkaufen, oeffentlich abspielen und in dein eigenes Produkt einbetten. Nicht exklusiv heisst: 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 abschliessende Klaerung. Wir sichern dir vertraglich die Nutzung zu, koennen 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 pruefen lassen.

Eingaben und fertige Lieder bewahren wir 90 Tage auf, danach werden sie geloescht. Ein frueheres Loeschen einzelner Lieder geht per DELETE /v1/songs/{id}. Die Angaben aus details nutzen wir ausschliesslich fuer die Produktion des jeweiligen Liedes und nicht zum Training eigener Modelle.

Wenn du Daten deiner Kunden an uns schickst, bist du dafuer der Verantwortliche und wir der Auftragsverarbeiter. Einen Auftragsverarbeitungsvertrag bekommst du auf Anfrage.

Support

Fragen, hoehere Limits, Auftragsverarbeitungsvertrag, Sonderfaelle: songs@maxkuch.com. Nenne bei technischen Problemen die request_id aus der Fehlerantwort, damit wir den Vorgang direkt finden.

Fuer Integrationen ueber KI-Agenten gibt es zusaetzlich einen Model-Context-Protocol-Server. Der ist unter /mcp/ dokumentiert und benutzt dieselben Schluessel wie die REST-API.

Zugang anfragen

Schluessel werden manuell vergeben. Eine kurze Mail mit Vorhaben, erwartetem Volumen und Sprachen genuegt, die Freischaltung dauert in der Regel einen Werktag.

Zugang anfragen