Endpointy

Każda trasa API integracji wtyczek v1 — co zwraca, kiedy jej użyć, jakie uprawnienie wymaga.

Kanonicznym kontraktem jest specyfikacja OpenAPI 3.1 (YAML) — tam znajdziesz pełne schematy i wszystkie odpowiedzi błędów. Ta strona podsumowuje każdą trasę w pigułce. Jeśli dopiero zaczynasz, przejdź najpierw główne procesy.

Zmiana niezgodna wstecz (maj 2026). POST /jobs i POST /jobs/batch nie przyjmują już dawnego body pojedynczego zadania. Wysyłasz teraz sesję — jedną session_config (modelka, sceneria, styl, proporcje, sugestie) plus listę subjects[], gdzie każdy produkt rozwija się w images_count zadań generowania. Zobacz notkę migracyjną na końcu strony.

Tożsamość

GET /me

Zwraca dane Twojej instalacji i konta sprzedawcy: stan kredytów, plan, limit zapytań, efektywne uprawnienia oraz aktualną listę subprocesorów.

Uprawnienie: dowolny ważny klucz.

Zadania

POST /jobs

Zamów jedną sesję zdjęciową. Body: {job_type?, session_config, subjects[]} jedna wspólna konfiguracja dla wszystkich produktów; serwer tworzy images_count zadań na każdy produkt. Odpowiedź: {order_id, status, subjects: [{product_ref, job_ids: [...]}]}.

Samouczki: sesja z gotowego packshota, packshot ze zdjęcia, parametry sesji.

Uprawnienie: plugin.jobs:create. Idempotencja: obsługiwana (nagłówek Idempotency-Key, okno 24 h).

Wymóg zaakceptowanego packshota

Sesja zdjęciowa (job_type pominięty lub photo_shoot) wymaga, by każdy produkt miał zaakceptowany packshot:

  • Gdy pominiesz subjects[].packshot_asset_id, serwer sam wybierze najnowszy zaakceptowany packshot produktu wskazanego przez product_ref.
  • Gdy podasz packshot_asset_id jawnie, musi on wskazywać zaakceptowany packshot tego samego produktu.
  • Gdy produkt nie ma zaakceptowanego packshota, całe wywołanie zwraca 422 packshot_not_approved — nic nie zostaje utworzone i żadne kredyty nie są pobierane.

Jak doprowadzić produkt do zaakceptowanego packshota — krok po kroku w samouczku „Packshot ze zdjęcia".

Generowanie packshotów

Z job_type: "packshot" zamawiasz propozycje packshota ze zwykłego zdjęcia. Każdy produkt w sesji musi wtedy mieć packshot_asset_id (zdjęcie wejściowe) oraz auto_register_packshot: true (wygenerowana propozycja trafia do katalogu produktu). Propozycje nie są akceptowane automatycznie — wybraną zatwierdzasz przez POST /jobs/{id}/accept.

POST /jobs/batch

Zamów do 100 sesji w jednym wywołaniu. Body: {batches: [...]} — każdy wpis to niezależna sesja. Limity: 100 sesji i 5000 zdjęć łącznie na wywołanie. Odpowiedź to HTTP 207 z wynikiem per sesja. Samouczek: sesje hurtowo.

Uprawnienie: plugin.jobs:create. Idempotencja: brak w v1 — nieudane sesje ponawiaj pojedynczo przez POST /jobs z własnym Idempotency-Key.

GET /jobs

Zwraca listę Twoich zadań generowania, od najnowszych. Parametry: status, created_after, created_before, limit (domyślnie 50, maks. 200), cursor (stronicowanie).

Uprawnienie: plugin.jobs:read.

GET /jobs/{id}

Zwraca jedno zadanie: status, dane produktu (product_label, product_ref, packshot_asset_id), ocenę (voting, voting_at) i — dla zadań ukończonych — listę outputs[] z adresami do pobrania zdjęć (ważne co najmniej 7 dni). Samouczek: odbieranie wyników.

Uprawnienie: plugin.jobs:read.

POST /jobs/{id}/accept

Zapisuje akceptację ukończonego zadania. Skutek zależy od typu zadania:

  • zadanie packshot — wygenerowany packshot staje się zaakceptowanym packshotem produktu i odblokowuje sesje zdjęciowe (zobacz wymóg zaakceptowanego packshota),
  • zadanie photo_shoot — wyłącznie informacja zwrotna; nie zmienia kredytów, plików ani katalogu.

Zwraca 204. 404, gdy zadanie należy do innej instalacji; 409 job_not_completed, gdy zadanie się nie zakończyło. Ponowna ocena nadpisuje poprzednią.

Uprawnienie: plugin.jobs:read.

POST /jobs/{id}/reject

Zapisuje odrzucenie ukończonego zadania. Ten sam kontrakt co accept w tym skutek katalogowy dla zadań packshot: odrzucona propozycja nie będzie używana w sesjach zdjęciowych.

Uprawnienie: plugin.jobs:read.

POST /jobs/{id}/refresh-url

Zwraca świeże adresy pobrania dla ukończonego zadania — użyj, gdy poprzednie wygasły (po 7 dniach). 409 job_not_completed, gdy zadanie wciąż trwa; 410, gdy pliki zostały już usunięte zgodnie z polityką przechowywania.

Uprawnienie: plugin.jobs:read.

DELETE /jobs/{id}

Anuluje zadanie, które jeszcze nie ruszyło, i zwalnia rezerwację kredytów. 409 job_not_cancelable, gdy zadanie już się wykonuje lub zakończyło.

Uprawnienie: plugin.jobs:cancel.

Sesje (zamówienia)

GET /orders/{id}

Zwraca całą sesję: konfigurację (session_config), stan per produkt (jobs_total, jobs_completed, jobs_failed), wygenerowane zdjęcia oraz podsumowanie kredytów (summary). Sesje innych instalacji zwracają 404.

Uprawnienie: plugin.jobs:read.

POST /orders/{id}/clone

Tworzy nową sesję z konfiguracją i produktami sesji źródłowej. Puste body powiela produkty 1:1; body z subjects[] to pełne zastąpienie listy — klonowane są tylko wymienione produkty, każdy z nową images_count. Oceny nie przechodzą; kredyty naliczane są od nowa. Samouczek: ponowna sesja.

Uprawnienie: plugin.jobs:create. Idempotencja: wymagana nagłówek Idempotency-Key jest obowiązkowy.

Pliki

POST /assets/upload

Zwraca tymczasowy adres do wgrania pliku (zdjęcia produktu). Body: {mode: "presigned", filename, content_type, size_bytes} (maks. 50 MB). Wyślij bajty na zwrócony upload_url metodą PUT w ciągu 2 godzin. Zwrócony asset_id wskażesz przy rejestracji zdjęcia lub packshota.

Uprawnienie: plugin.assets:upload.

Style (presety)

GET /presets

Zwraca listę stylów dostępnych dla sprzedawcy — z nazwą, opisem, miniaturą, galerią przykładów, kosztem w kredytach i wskazówkami co do zdjęć wejściowych. Samouczek: parametry sesji.

Uprawnienie: plugin.catalog:read lub plugin.jobs:read (starsze instalacje zachowują dostęp).

Dane katalogowe

Z tych endpointów zbudujesz ekran wyboru parametrów sesji — zobacz samouczek o parametrach. Wszystkie wymagają uprawnienia plugin.catalog:read.

GET /models

Zwraca modelki dostępne dla sprzedawcy — własne konta i z katalogu Qamera. Każdy wpis: id, name, thumbnail, source ('account' / 'marketplace'). Pozycje odrzucone i zarchiwizowane są odfiltrowane.

GET /sceneries

Scenerie — ten sam kształt i reguły co /models.

GET /ai-models

Zwraca modele AI, których konto sprzedawcy może użyć (lista zależy od planu). Każdy wpis: id ("provider/model" — trafia do subjects[].ai_model), output_type, supported_aspect_ratios[], base_credit_cost. Każdy zwrócony wpis przejdzie w POST /jobs.

Buforuj tylko prywatnie: Cache-Control: private, max-age=300, Vary: X-Api-Key.

GET /aspect-ratios

Zwraca obsługiwane proporcje obrazu — dokładnie jedna ma default: true. Buforuj śmiało: Cache-Control: public, max-age=3600.

GET /pricing

Zwraca cennik kredytowy per (job_type, provider, model) — wpis model: "*" to cena domyślna dostawcy. Spójny z base_credit_cost z /ai-models. Buforowanie: Cache-Control: public, max-age=300.

Katalog produktów

Trwały katalog produktów sprzedawcy, ich zdjęć źródłowych i packshotów. Rekordy identyfikujesz własnymi, stabilnymi identyfikatorami (external_ref) — to one wiążą Twój sklep z Qamera AI. Endpointy zbiorcze przyjmują do 100 elementów na wywołanie. Rekordy innych instalacji zwracają 404.

POST /images

Rejestruje zdjęcia źródłowe produktów (wgrane wcześniej przez /assets/upload). Tworzy produkt automatycznie, gdy product_ref jest nowy i podasz product_metadata.display_name. Ponowne wywołanie z tym samym external_ref zwraca istniejący wiersz (status: "existing"). Samouczek: packshot ze zdjęcia.

Uprawnienie: plugin.catalog:write.

POST /packshots

Rejestruje gotowe packshoty. Packshoty wgrane tą drogą są akceptowane automatycznie — od razu spełniają wymóg dla sesji zdjęciowych. source_image_ref (opcjonalny) wiąże packshot ze zdjęciem źródłowym. Samouczek: sesja z gotowego packshota.

Uprawnienie: plugin.catalog:write.

GET /products

Zwraca listę Twoich produktów (stronicowanie kursorem): id, external_ref, display_name, sku, image_count, packshot_count. Produkty usunięte są domyślnie pominięte.

Uprawnienie: plugin.catalog:read.

GET /products/{id_or_ref}

Zwraca jeden produkt z osadzonymi zdjęciami i packshotami (do 100 każdych; flagi images_truncated / packshots_truncated sygnalizują, że jest ich więcej). W ścieżce podasz UUID albo własny external_ref. Każdy osadzony packshot zawiera też swoją ocenę (voting, voting_at) — te same pola co w GET /packshots.

Uprawnienie: plugin.catalog:read.

DELETE /products/{id_or_ref}

Usuwa produkt (miękko — zdjęcia i packshoty zostają). Ten sam external_ref możesz potem zarejestrować ponownie jako nowy produkt.

Uprawnienie: plugin.catalog:write.

GET /packshots

Zwraca listę Twoich packshotów (stronicowanie kursorem). Parametr product_ref zawęża do jednego produktu. Każdy packshot zawiera swoją ocenę: voting (pending, accepted albo rejected) oraz voting_at (moment decyzji). Packshot z voting: "accepted" spełnia wymóg zaakceptowanego packshota — sprawdzisz tu, który packshot odblokowuje sesje zdjęciowe produktu. Packshoty zarejestrowane przez POST /packshots są zaakceptowane od razu.

Uprawnienie: plugin.catalog:read.

DELETE /packshots/{id_or_ref}

Usuwa wpis packshota z katalogu. Sam plik pozostaje — mogą się do niego odwoływać inne rekordy.

Uprawnienie: plugin.catalog:write.

Instalacja

POST /installations/{id}/rotate-hmac

Wymienia sekret HMAC do podpisywania webhooków. Poprzedni sekret działa jeszcze 48 godzin, więc powiadomienia w drodze nie przepadną. Nowy sekret jest w odpowiedzi — pokazujemy go tylko raz.

Uprawnienie: plugin.installations.manage.

Webhooki

POST /webhooks/{delivery_id}/replay

Ponownie wysyła powiadomienie webhook — użyj, gdy Twój endpoint nie działał w oknie automatycznych ponowień. Samouczek: odbieranie wyników.

Uprawnienie: plugin.webhooks:manage.

Migracja z poprzedniego kształtu v1

Dawne body POST /jobs ({job_type, provider, model, unit_cost, settings}) oraz dawne body POST /jobs/batch ({jobs: [...]}) nie są już obsługiwane i zwracają 400 invalid_input.

Przejście na kształt sesyjny:

  1. Owiń dotychczasowe parametry pojedynczego zadania w jeden wpis subjects[]: {packshot_asset_id, product_label, product_ref, images_count, ai_model: "provider/model"}.
  2. Wynieś modelkę/scenerię/styl/proporcje do session_config. Pole ai_model zastępuje dawne trio provider/model/unit_cost — koszt liczony jest po stronie serwera.
  3. W wywołaniach batch zmień jobs na batches — każdy wpis to jedna pełna sesja.
  4. Powiadomienia webhook zawierają teraz dodatkowe pola (packshot_asset_id, product_label, product_ref, voting, voting_at) — możesz je ignorować, jeśli ich nie potrzebujesz.