Dokumentáció: REST API v1
Fejlesztői dokumentáció
Partner REST API (v1)
A FotóAI stabil, verziózott REST API-ja: OAuth 2.1 partnereknek, személyes API-kulcs, végpontok, feltöltés, webhookok.
Alapok
- Alapcím
https://fotoai.hu- Formátum
- Csak JSON, UTF-8. Az idő ISO 8601 UTC. A pénz egész szám millikreditben (1 kredit = 1000 mc).
- Hitelesítés
Authorization: Bearer fai_oat_…(OAuth) vagyBearer fai_live_…(személyes API-kulcs). Böngészős munkamenet itt nem azonosít.- Verzió
- v1 – a stabil, nyilvános szerződés. Új integrációhoz ezt használd; az MCP-eszközök alakja az MCP-kliensek igényeit követi.
Az API, az MCP-szerver és a CLI ugyanazzal a kóddal áraz és generál, mint a web, ezért soha nem mondanak mást egy árról vagy egy csomagkorlátról.
OAuth 2.1 partnereknek
A FotóAI az engedélyezési szerver, a partner bizalmas (titkos kulccsal rendelkező) kliens. Metaadatok: https://fotoai.hu/.well-known/oauth-authorization-server (RFC 8414). Kliensregisztráció nálunk történik – dinamikus regisztráció nincs; írj, ha partneralkalmazást építesz.
- Engedélyezés. Irányítsd a felhasználót ide. A PKCE (S256) kötelező, a titkos kulccsal rendelkező kliensnek is.
- Jóváhagyás. A felhasználó belép (Google vagy e-mailes link), és a magyar nyelvű jóváhagyó képernyőn engedélyez. Ha már van érvényes, a kért jogokat lefedő engedélye, a képernyő kimarad.
- Visszairányítás.
redirect_uri?code=fai_oac_…&state=…, elutasításkorerror=access_denied. - Token. A kódot (egyszer használható, 60 mp) a token-végponton váltod be.
https://fotoai.hu/oauth/authorize?response_type=code
&client_id=<client_id>
&redirect_uri=<pontosan a regisztrált cím>
&scope=profile%20read%20generate
&state=<véletlen>
&code_challenge=<base64url(SHA-256(verifier))>
&code_challenge_method=S256curl -s https://fotoai.hu/oauth/token \
-u "<client_id>:<client_secret>" \
-d grant_type=authorization_code -d code=fai_oac_… \
-d redirect_uri=<ugyanaz> -d code_verifier=<verifier>{ "access_token": "fai_oat_…", "token_type": "Bearer", "expires_in": 3600,
"refresh_token": "fai_ort_…", "scope": "profile read generate" }| Token / művelet | Szabály |
|---|---|
| Hozzáférési token | fai_oat_…, 1 óra |
| Frissítő token | fai_ort_…, 90 nap, minden használatkor cserélődik; egy már lecserélt token újbóli bemutatása a teljes engedélyt visszavonja. |
| Frissítés | grant_type=refresh_token&refresh_token=fai_ort_… – a scope szűkíthető, nem bővíthető. |
| Visszavonás | POST /oauth/revoke (RFC 7009) bármelyik tokennel: a teljes engedély megszűnik. |
| Kliens-hitelesítés | client_secret_basic vagy client_secret_post – egyszerre csak az egyik. |
A felhasználó a kapcsolatot a Beállítások → Kapcsolt alkalmazások oldalon bármikor leválaszthatja; a tokenek azonnal érvénytelenné válnak.
Jogosultságok (scope)
| Scope | Mit enged |
|---|---|
profile | E-mail és név (GET /api/v1/me). |
read | Egyenleg, modellek, stílusok, árajánlatok, generálások és kimenetek. |
generate | Generálás és lemondás, feltöltés – kreditet költ. |
A személyes API-kulcs read és generate jogú, és a /api/v1/me-nél profile-nak is számít. A böngészőhöz kötött útvonalak (számlázás, fiók, API-kulcsok, kapcsolt alkalmazások) tokennel 403 FORBIDDEN (session_only) választ adnak.
Végpontok
| Metódus | Útvonal | Scope | Leírás |
|---|---|---|---|
| GET | /api/v1/me | profile és/vagy read | Fiók: e-mail, név (profile), egyenleg (read). |
| GET | /api/v1/models?category=image|video|audio|tool | read | Modellek módokkal, paraméterekkel és ártáblával. |
| GET | /api/v1/styles | read | Stílusok és fotócsomagok. |
| POST | /api/v1/quote | read vagy generate | Árajánlat, 10 percig tárolva (quote_id). |
| POST | /api/v1/generations | generate | Generálás indítása (202). |
| GET | /api/v1/generations?cursor=&limit= | read | A legutóbbi generálások, minden forrásból. |
| GET | /api/v1/generations/:id | read | Állapot és kimenetek (:id lehet csomagfuttatás group_id-ja is). |
| DELETE | /api/v1/generations/:id | generate | Lemondás, a lefoglalt kredit felszabadul. |
| POST | /api/v1/uploads | generate | Előre aláírt PUT-cím feltöltéshez. |
| POST | /api/v1/uploads/:id/complete | generate | Feltöltés lezárása → asset_id. |
Árajánlat és generálás
Előbb kérj árat. A quote_id 10 percig érvényes, és felső korlátként kötöd a generáláshoz: a szerver újra áraz, és ha az ár a korlát fölé menne, 409 PRICE_CHANGED a válasz, és semmi nem indul el.
curl -s https://fotoai.hu/api/v1/quote \
-H "Authorization: Bearer $FOTOAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"image.seedream-5-lite","params":{"aspect":"3:4"},"prompt":"portré egy kávézóban"}'{ "millicredits": 1000, "credits": 1, "breakdown": [{ "label": "…", "millicredits": 1000 }],
"quote_id": "uuid", "expires_at": "…", "catalog_hash": "…", "estimated": false,
"insufficient": false, "available_millicredits": 3000 }curl -s https://fotoai.hu/api/v1/generations \
-H "Authorization: Bearer $FOTOAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"image.seedream-5-lite","params":{"aspect":"3:4"},"prompt":"portré egy kávézóban",
"quote_id":"<a quote_id>","idempotency_key":"'"$(uuidgen)"'"}'{ "id": "jobId", "status": "running", "estimated_seconds": 12,
"reserved_millicredits": 1000, "client_reference": null }quote_idvagymax_millicreditskötelező (vagy mindkettő – ilyenkor a kisebbik a korlát).idempotency_keykötelező: ugyanazzal a kulccsal ismételt kérés ugyanazt a feladatot adja vissza200-zal, és nem foglal le kétszer kreditet.- Bemenetek:
inputs.reference_asset_ids,start_asset_id,end_asset_id,reference_video_asset_ids,script; stílus:style_id. Hangmodellnél aprompta felolvasandó szöveg, ha nincsinputs.script. - Fotócsomag-stílusnál a generálás csomagfuttatás:
pack_sizedarab kép, képenkénti áron, egygroup_idalatt. Ha az egyenleg nem fedezi az összeset,402 INSUFFICIENT_CREDITS, és egy sem indul.
Állapot lekérdezése
GET /api/v1/generations/:id – a kész kimenetek url-je hitelesítés nélkül letölthető (nyilvános cím, vagy 6 óráig érvényes aláírt cím url_expires_at-tel).
{ "id": "…", "status": "completed", "model": "image.seedream-5-lite", "mode": "t2i",
"source": "api", "reserved_millicredits": 1000, "charged_millicredits": 1000,
"outputs": [{ "asset_id": "…", "kind": "image", "url": "https://media.fotoai.hu/…",
"mime": "image/png", "width": 1024, "height": 1024 }] }Feltöltés
Referenciaképet, kezdő- és zárókockát bájtokként töltesz fel – URL-ről a szerver nem tölt le. Korlát: 120 feltöltés 10 percenként felhasználónként (a webbel közösen).
# 1. PUT-cím kérése
curl -s https://fotoai.hu/api/v1/uploads -H "Authorization: Bearer $FOTOAI_API_KEY" \
-H "Content-Type: application/json" -d '{"kind":"image","mime":"image/jpeg","bytes":482113}'
# → { "upload_id": "…", "put_url": "https://…", "headers": { "Content-Type": "image/jpeg" }, "expires_at": "…" }
# 2. a fájl feltöltése pontosan ezekkel a fejlécekkel
curl -s -X PUT "<put_url>" -H "Content-Type: image/jpeg" --data-binary @szelfi.jpg
# 3. lezárás
curl -s -X POST https://fotoai.hu/api/v1/uploads/<upload_id>/complete -H "Authorization: Bearer $FOTOAI_API_KEY"
# → { "asset_id": "…" }Webhookok
Ha egy partnerként (OAuth) indított feladat végállapotba ér, a FotóAI a kliens regisztrált webhookcímére POST-ol (soha nem kérésből kapott címre). Események: generation.completed, generation.failed, generation.cancelled. A törzs a GET /api/v1/generations/:id válasza, kiegészítve az event, event_id és client_reference mezőkkel.
- FotoAI-Signature
t=<unix idő>,v1=<hex hmac_sha256(webhookSecret, t + "." + rawBody)>- FotoAI-Event-Id
evt_…– feladatonként és eseményenként állandó; erre deduplikálj.- Kézbesítés
- Azonnal (5 mp időkorlát), majd újrapróbálás 1 p, 5 p, 15 p, 1 ó, 3 ó, 6 ó és 12 ó után (8 kísérlet, ~24 óra). Bármely 2xx siker; átirányítást nem követünk.
const [t, v1] = header.split(",").map((p) => p.split("=")[1]);
const ok =
Math.abs(Date.now() / 1000 - Number(t)) <= 300 &&
crypto.timingSafeEqual(
Buffer.from(v1),
Buffer.from(crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"))
);A webhook kényelmi funkció
Legjobb szándékkal kézbesítjük; a megbízható forrás mindig a GET /api/v1/generations/:id lekérdezés. A személyes API-kulccsal indított feladatokhoz nincs webhook.