API MojaMelodia tworzy spersonalizowane piosenki programowo: na wejściu okazja i kilka szczegółów, na wyjściu gotowy tekst i wyprodukowane nagranie. Wyłącznie HTTPS i JSON, bez obowiązkowego SDK.
Zaktualizowano: 2026-09-16
Klucze wydajemy ręcznie. Wystarczy krótka wiadomość z opisem projektu, przewidywanym wolumenem i językami, a odblokowanie trwa zwykle jeden dzień roboczy.
API robi dokładnie to samo co strona. Przesyłasz okazję, imię osoby, o której jest piosenka, i kilka konkretnych szczegółów. Powstaje z tego najpierw gotowy tekst, a potem wyprodukowane nagranie z wokalem, aranżacją i miksem. Całość trwa zwykle od pięciu do dziesięciu minut.
Wszystkie zapytania idą na https://api.mojamelodia.pl/v1. API mówi wyłącznie po HTTPS, przyjmuje JSON i odpowiada JSON-em. Nie ma obowiązkowego SDK: wystarczy dowolny język, który umie HTTP. Przykłady na tej stronie używają curl, Pythona i Node, bo to trzy najczęstsze przypadki.
Każda domena ma własną bazę API i własną cenę w lokalnej walucie. Klucz działa dla domeny, dla której został wydany. Kto obsługuje kilka rynków, dostaje kilka kluczy albo jeden klucz otwarty na kilka domen.
Rozliczenie następuje za gotową piosenkę, obecnie 59 zł. Szkice, anulowane zlecenia i ponowne generowania nic nie kosztują.
Świadomie nie ma automatycznej rejestracji. Klucze wydajemy ręcznie, bo za każdą piosenką stoją realne koszty produkcji i chcemy wiedzieć, do czego służy integracja. W praktyce to krótka wiadomość i jeden dzień roboczy.
Napisz na songs@maxkuch.com i podaj cztery rzeczy:
Dostaniesz dwa klucze: testowy z przedrostkiem sk_test_, bezpłatny, który zwraca stałe nagrania demonstracyjne, oraz produkcyjny z przedrostkiem sk_live_. Oba działają od razu, bez odblokowywania pojedynczych punktów końcowych.
Każde zapytanie niesie klucz w nagłówku Authorization jako token bearer. Zapytania bez poprawnego nagłówka dostają 401 i typ błędu authentication_error.
curl https://api.mojamelodia.pl/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"occasion": "birthday",
"recipient_name": "Anna",
"relationship": "sister",
"language": "pl",
"mood": "happy",
"style": "pop",
"voice": "female",
"details": "Climbs every weekend, always ten minutes late, calls everyone chef.",
"callback_url": "https://example.com/hooks/songs"
}'
Traktuj klucz jak hasło: tylko po stronie serwera, nigdy w kodzie frontendu, nigdy w publicznym repozytorium. Jeśli klucz wycieknie, napisz do nas: blokujemy go natychmiast i wydajemy nowy. Konto może mieć kilka aktywnych kluczy, więc wymiana odbywa się bez przerwy w działaniu.
Klucze testowe i produkcyjne korzystają z tych samych punktów końcowych. To, czy zapytanie poszło w trybie testowym, pokazuje pole livemode w każdym obiekcie.
Utworzenie piosenki to jedno wywołanie. Odpowiedź przychodzi od razu i zawiera identyfikator ze statusem queued. Cała reszta dzieje się w tle.
import os, time, requests
API = "https://api.mojamelodia.pl/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": "pl",
"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"])
Dla prostoty przykład odpytuje co pięć sekund. Na produkcji lepszą drogą są webhooki, bo oszczędzają i otwarte połączenie, i czekanie. Obie drogi są obsługiwane, webhooki opisujemy niżej.
Decydujące pole to details. Tam trafiają konkrety o osobie: przezwisko, dziwactwo, wakacje, które poszły nie tak. Ogólne zdania w rodzaju "to ciepła osoba" dają ogólne wersy. Wystarczą trzy do pięciu konkretnych szczegółów i to one decydują, czy piosenka jest po prostu miła, czy naprawdę o kimś.
| Metoda | Ścieżka | Do czego służy |
|---|---|---|
| POST | /v1/songs | Zamówić nową piosenkę. |
| GET | /v1/songs/{id} | Pobrać piosenkę ze wszystkimi aktualnymi polami. |
| GET | /v1/songs | Wylistować piosenki konta, z filtrami i stronicowaniem. |
| GET | /v1/songs/{id}/lyrics | Pobrać sam tekst jako zwykły tekst. |
| GET | /v1/songs/{id}/audio | Podpisany link do pobrania zapowiedzi albo całego nagrania. |
| POST | /v1/songs/{id}/regenerate | Uruchomić bezpłatne ponowne generowanie. |
| POST | /v1/songs/{id}/checkout | Utworzyć stronę płatności dla klienta końcowego. |
| POST | /v1/songs/{id}/unlock | Odblokować piosenkę bezpośrednio i obciążyć konto. |
| GET | /v1/options | Wszystkie dopuszczalne wartości okazji, nastroju, stylu, głosu i języka. |
| GET | /v1/account | Saldo, limity i otwarte domeny. |
| DELETE | /v1/songs/{id} | Anulować piosenkę, która nie jest jeszcze gotowa. |
POST /v1/songs przyjmuje brief i startuje od razu. Obowiązkowe są tylko trzy pola, pozostałe mają rozsądne wartości domyślne albo są dobierane do okazji.
| Pole | Typ | Opis |
|---|---|---|
| string | wymagane | Okazja. Dopuszczalne wartości pochodzą z /v1/options. |
| string | wymagane | Imię osoby, o której jest piosenka. Jest używane w tekście. |
| string | wymagane | Konkretne szczegóły o osobie, od 40 do 4000 znaków. To pole decyduje o jakości. |
| string | opcjonalne | Relacja między zamawiającym a obdarowanym, na przykład siostra, kolega, partnerka. |
| string | opcjonalne | Język, w którym się śpiewa. Wartość domyślna to pl. |
| string | opcjonalne | Podstawowy nastrój. Bez wskazania dobieramy pasujący do okazji. |
| string | opcjonalne | Styl muzyczny. Bez wskazania dobieramy pasujący do okazji i nastroju. |
| string | opcjonalne | Głos wokalisty. Bez wskazania dobieramy pasujący do okazji. |
| string | opcjonalne | Przesłanie, które ma pojawić się w piosence. |
| string | opcjonalne | Dowolny tekst na wszystko, co nie mieści się gdzie indziej, na przykład życzenia co do tempa. |
| string | opcjonalne | Adres HTTPS, na który mają iść zdarzenia. |
| object | opcjonalne | Dowolne pary klucz-wartość, najwyżej 20. Wracają bez zmian. |
const res = await fetch("https://api.mojamelodia.pl/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: "pl",
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);
Wywołanie nic nie kosztuje. Płatność następuje dopiero przy odblokowaniu przez /unlock albo zakończoną sesję płatności.
Każdy punkt końcowy zwracający pojedynczą piosenkę zwraca ten sam obiekt. Pola, których jeszcze nie ma, mają wartość null i wypełniają się w trakcie produkcji.
{
"id": "sng_3n8Kd2ZpQv",
"object": "song",
"status": "queued",
"created_at": "2026-09-16T09:41:02Z",
"occasion": "birthday",
"recipient_name": "Anna",
"relationship": "sister",
"language": "pl",
"mood": "happy",
"style": "pop",
"voice": "female",
"lyrics": null,
"preview_url": null,
"audio_url": null,
"duration_seconds": null,
"paid": false,
"price": { "amount": 2999, "currency": "PLN" },
"metadata": {},
"livemode": true
}
| Pole | Typ | Opis |
|---|---|---|
| string | opcjonalne | Unikalny identyfikator, zawsze zaczyna się od sng_. |
| string | opcjonalne | Aktualny stan produkcji, patrz następny rozdział. |
| string | opcjonalne | Pełny tekst ze znacznikami zwrotek i refrenu. Bezpłatny, także bez płatności. |
| string | opcjonalne | Pierwsze 45 sekund w MP3. Zawsze dostępne, bez płatności. |
| string | opcjonalne | Całe nagranie w MP3, podpisane i ważne 24 godziny. Wypełnia się dopiero po płatności. |
| integer | opcjonalne | Długość gotowego nagrania w sekundach, zwykle między 120 a 240. |
| boolean | opcjonalne | Czy piosenka jest odblokowana. |
| object | opcjonalne | Kwota w najmniejszej jednostce waluty plus kod waluty, tu 59 zł. |
| object | opcjonalne | To, co przekazałeś przy tworzeniu, bez zmian. |
| boolean | opcjonalne | false, jeśli zapytanie poszło kluczem testowym. |
{
"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.mojamelodia.pl/preview/sng_3n8Kd2ZpQv.mp3",
"audio_url": "https://cdn.mojamelodia.pl/full/sng_3n8Kd2ZpQv.mp3?expires=1789412855&sig=...",
"duration_seconds": 184,
"paid": true,
"price": { "amount": 2999, "currency": "PLN" },
"metadata": { "order_id": "A-10423" },
"livemode": true
}
Piosenka przechodzi przez stany w tej kolejności. Nigdy się nie cofa, a complete, failed i cancelled to stany końcowe.
| Status | Wartość | Znaczenie |
|---|---|---|
| queued | Przyjęta, czeka na wolne miejsce w produkcji. Zwykle kilka sekund. | |
| writing_lyrics | Trwa pisanie tekstu. | |
| lyrics_ready | Tekst jest gotowy i można go pobrać. Zwykle po jednej, dwóch minutach. | |
| generating_audio | Wokal, aranżacja i miks są w produkcji. | |
| preview_ready | Pierwsze 45 sekund jest dostępne, a cały plik gotowy. | |
| complete | Opłacona i dostarczona w całości. | |
| failed | Produkcja ostatecznie się nie powiodła. Nic nie obciążamy, pole error podaje powód. | |
| cancelled | Anulowana przed ukończeniem. |
Pojedyncza nieudana próba produkcji nie prowadzi od razu do failed. Wewnętrznie ponawiamy kilka razy i poddajemy się dopiero, gdy zawiodą wszystkie próby. Dlatego failed zdarza się rzadko i naprawdę znaczy: ta piosenka nie przyjdzie.
GET /v1/songs/{id} zwraca aktualny stan piosenki. Punkt końcowy jest lekki i znosi odpytywanie co sekundę, o ile mieścisz się w limicie częstotliwości.
curl -G https://api.mojamelodia.pl/v1/songs \
-H "Authorization: Bearer $SONG_API_KEY" \
-d status=complete \
-d limit=20 \
-d starting_after=sng_3n8Kd2ZpQv
Listy działają na kursorze. Dostajesz najwyżej limit pozycji, domyślnie 20 i maksymalnie 100, od najnowszych. Jeśli has_more jest prawdą, przekazujesz next_cursor jako starting_after w kolejnym wywołaniu. Filtrować możesz po status, occasion, language, paid oraz created_after i 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"
}
Tekst jest bezpłatny i kompletny, to nie fragment. GET /v1/songs/{id}/lyrics zwraca go jako text/plain, ze znacznikami zwrotek i refrenu. Ten sam tekst stoi w polu lyrics obiektu piosenki.
Przy dźwięku są dwa poziomy. Zapowiedź to pierwsze 45 sekund gotowego nagrania, a nie osobne demo: ten sam głos, ta sama aranżacja, ten sam tekst. Jest dostępna bez płatności i taka pozostaje. Cały plik wydaje GET /v1/songs/{id}/audio dopiero po odblokowaniu.
Oba adresy są podpisane i ważne 24 godziny. Służą do pobrania, nie do trwałego linkowania. Jeśli potrzebujesz pliku dłużej, pobierz go raz i przechowaj u siebie. Ponowne wywołanie punktu końcowego daje w każdej chwili świeży adres.
Format to zawsze MP3 320 kbit/s. Kto potrzebuje WAV, dodaje ?format=wav, dostępne dla kont z opcją studyjną.
Jeśli wynik nie przekonuje, ponowne generowanie nic nie kosztuje. POST /v1/songs/{id}/regenerate tworzy nową wersję pod tym samym identyfikatorem i ustawia status z powrotem na queued. Poprzednia wersja zostaje pod previous_versions.
curl https://api.mojamelodia.pl/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."
}'
Przy keep_lyrics: true tekst zostaje i powstaje tylko nowe nagranie. To właściwa droga, gdy tekst siedzi, a zawiódł tylko głos albo tempo. Przy false przepisujemy również tekst.
Pole note trafia wprost do ponownego generowania, więc konkretne zdanie się opłaca. "Niższy męski głos, wolniej" działa, "zrób lepiej" nie. Trzy ponowne generowania na piosenkę są bezpłatne, powyżej tego napisz do nas.
Są dwa sposoby odblokowania piosenki, zależnie od tego, kto płaci.
POST /v1/songs/{id}/checkout tworzy u nas stronę płatności w walucie domeny, z metodami płatności typowymi dla danego kraju. Wysyłasz tam klienta i dostajesz zdarzenie song.paid, gdy płatność dojdzie do skutku.
curl https://api.mojamelodia.pl/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.mojamelodia.pl/c/cs_live_8Hd2Kq...",
"amount": 2999,
"currency": "PLN",
"expires_at": "2026-09-16T11:41:02Z"
}
Na kontach z fakturą zbiorczą POST /v1/songs/{id}/unlock odblokowuje piosenkę od razu i obciąża konto kwotą 59 zł. Bez objazdu przez stronę płatności, wygodne, gdy masz własną kasę.
curl https://api.mojamelodia.pl/v1/songs/sng_3n8Kd2ZpQv/unlock \
-H "Authorization: Bearer $SONG_API_KEY" \
-X POST
W obu przypadkach obowiązuje to samo prawo do korzystania: niewyłączne, ale wyraźnie komercyjne. Gotową piosenkę możesz przekazywać dalej, sprzedawać i publikować w ramach swojej oferty.
Listy okazji, nastrojów, stylów, głosów i języków zmieniają się od czasu do czasu. Zamiast wpisywać je na sztywno, odpytaj GET /v1/options i trzymaj odpowiedź w pamięci podręcznej przez kilka godzin.
{
"object": "options",
"language": "pl",
"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"]
}
Każdą z tych wartości można też pominąć. Wartość surprise_me nie jest wypełniaczem, tylko prawdziwą instrukcją: wtedy świadomie dobieramy coś, co pasuje do okazji i szczegółów.
Podaj przy tworzeniu callback_url, a wyślemy tam każde zdarzenie metodą POST. To zalecana droga, bo oszczędza odpytywanie i czekanie.
| Zdarzenie | Typ | Wyzwalane, gdy |
|---|---|---|
| song.lyrics_ready | Tekst jest gotowy. | |
| song.preview_ready | Zapowiedź na 45 sekund jest dostępna. | |
| song.completed | Całe nagranie zostało dostarczone. | |
| song.failed | Produkcja ostatecznie się nie powiodła. | |
| song.regenerated | Ponowne generowanie jest gotowe. | |
| song.paid | Płatność wpłynęła, piosenka jest odblokowana. |
{
"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.mojamelodia.pl/full/sng_3n8Kd2ZpQv.mp3?expires=1789412855&sig=...",
"...": "..."
}
}
}
Każda dostawa niesie nagłówek ze znacznikiem czasu i HMAC-SHA256 po znaczniku czasu, kropce i surowym ciele. Sprawdź go, zanim zaufasz treści, i odrzuć wszystko starsze niż pięć minut.
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
Oczekujemy odpowiedzi 2xx w ciągu dziesięciu sekund. Jeśli jej nie ma, ponawiamy osiem razy w ciągu 24 godzin z rosnącymi odstępami. Dostawy mogą się więc powtarzać, a rzadko przyjść nie po kolei: zrób swój punkt końcowy idempotentnym i ufaj polu created_at, a nie godzinie nadejścia.
Każdy POST przyjmuje nagłówek Idempotency-Key z dowolną unikalną wartością, zwykle UUID. Jeśli ten sam klucz wróci w ciągu 24 godzin, zwracamy pierwotną odpowiedź zamiast tworzyć drugą piosenkę.
curl https://api.mojamelodia.pl/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": "pl", "details": "..." }'
To dokładnie ta ochrona, której trzeba przy błędach sieci: jeśli odpowiedź zginie, a twój kod powtórzy zapytanie, i tak powstanie jedna piosenka. Jeśli wyślesz ten sam klucz z innym ciałem, odpowiemy 409 z typem błędu conflict.
Błędy przychodzą zawsze w tej samej formie, z czytelnymi maszynowo type i code, czytelnym komunikatem oraz, gdy to istotne, wskazaniem pola. Dołącz request_id do każdego zgłoszenia, wtedy znajdziemy wywołanie w logach.
{
"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 | Znaczenie |
|---|---|---|
| 400 | invalid_request | Zapytanie jest formalnie zepsute, na przykład nieprawidłowy JSON albo nieznane pole. |
| 401 | authentication_error | Klucza brak, wygasł albo jest zablokowany. |
| 403 | permission_error | Klucz jest ważny, ale nie otwarty dla tej domeny albo tego punktu końcowego. |
| 404 | not_found | Żądany identyfikator nie należy do tego konta albo nie istnieje. |
| 409 | conflict | Działanie nie pasuje do stanu, na przykład odblokowanie anulowanej piosenki. |
| 422 | validation_error | Zapytanie jest formalnie poprawne, ale wartość jest nie do użycia, na przykład zbyt krótkie szczegóły. |
| 429 | rate_limit | Zbyt wiele zapytań albo zbyt wiele równoczesnych produkcji. |
| 500 | api_error | Błąd po naszej stronie. Ponów z rosnącymi odstępami. |
Przy 429 i 5xx ponawianie ma sens, najlepiej z wykładniczo rosnącymi odstępami i odrobiną losowości. Przy 4xx innym niż 429 nie ma: to samo zapytanie znowu zawiedzie.
| Limit | Wartość | Dotyczy |
|---|---|---|
| 60 / min | Zapytania na minutę i klucz we wszystkich punktach końcowych. | |
| 10 | Równoczesne produkcje. Kolejne zapytania czekają w kolejce. | |
| 64 KB | Największy dopuszczalny rozmiar ciała zapytania. | |
| 40 - 4000 | Znaki w polu details, minimum i maksimum. | |
| 90 | Dni, przez które trzymamy piosenki i dane wejściowe, potem są usuwane. | |
| 24 h | Czas, przez który klucz idempotencji zwraca starą odpowiedź. |
Każda odpowiedź niesie aktualny stan w nagłówkach, więc nie musisz zgadywać.
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1789412880
X-Concurrent-Limit: 10
X-Concurrent-Running: 3
Wyższe limity nie są problemem, po prostu nie są ustawieniem startowym. Gdy wolumen rośnie, napisz dwa zdania, a je podniesiemy.
Wersja główna stoi w ścieżce i pozostaje stabilna. Wewnątrz v1 pojawiają się tylko zmiany dodające: nowe pola, nowe wartości w listach, nowe punkty końcowe. Istniejące pola nie znikają i nie zmieniają znaczenia.
Dla większej pewności możesz przypiąć datę w nagłówku. Bez nagłówka obowiązuje zawsze najnowsze zachowanie.
X-Song-Version: 2026-09-01
Twój kod powinien ignorować nieznane pola w odpowiedziach, a nie się na nich wykładać. To jedyne założenie, jakie robimy wobec klientów.
Klucze z przedrostkiem sk_test_ przechodzą przez dokładnie te same punkty końcowe, ale nie uruchamiają prawdziwej produkcji i nic nie kosztują. Po kilku sekundach dostajesz stały tekst demonstracyjny i nagranie demonstracyjne, a każdy obiekt niesie livemode: false.
Dzięki temu da się przećwiczyć również przypadki nieprzyjemne. Pewne imiona w polu recipient_name wymuszają określony wynik: test_fail prowadzi do failed, test_slow do produkcji trwającej około dziesięciu minut, test_ratelimit do odpowiedzi 429. Obsługę błędów możesz więc przetestować, nie czekając na prawdziwą awarię.
Webhooki działają także w trybie testowym, z tym samym mechanizmem podpisu i własnym sekretem.
Wraz z odblokowaniem dostajesz niewyłączne, ale wyraźnie komercyjne prawo do korzystania z gotowej piosenki. Możesz ją przekazywać, sprzedawać, wykonywać publicznie i wbudować w swój produkt. Niewyłączne znaczy, że zachowujemy prawo do korzystania z nagrania również sami, na przykład jako z przykładu.
Co do praw autorskich do muzyki tworzonej przez sztuczną inteligencję wiele porządków prawnych nie ma jeszcze ostatecznej odpowiedzi. Prawo do korzystania gwarantujemy umownie, ale nie możemy zapewnić, że do nagrania powstaje odrębne prawo autorskie skuteczne wobec osób trzecich. Kto jest od tego zależny, powinien sprawdzić to wcześniej.
Dane wejściowe i gotowe piosenki trzymamy 90 dni, potem są usuwane. Do wcześniejszego usunięcia pojedynczej piosenki służy DELETE /v1/songs/{id}. Informacji z details używamy wyłącznie do wyprodukowania tej jednej piosenki i nigdy do trenowania własnych modeli.
Jeśli przekazujesz nam dane swoich klientów, to ty jesteś administratorem, a my podmiotem przetwarzającym. Umowa powierzenia jest dostępna na życzenie.
Pytania, wyższe limity, umowa powierzenia, przypadki szczególne: songs@maxkuch.com. Przy problemach technicznych podaj request_id z odpowiedzi błędu, wtedy znajdziemy wywołanie od razu.
Dla integracji przez agentów sztucznej inteligencji jest dodatkowo serwer Model Context Protocol, opisany na /mcp/, korzystający z tych samych kluczy co REST API.
Klucze wydajemy ręcznie. Wystarczy krótka wiadomość z opisem projektu, przewidywanym wolumenem i językami, a odblokowanie trwa zwykle jeden dzień roboczy.