Dokumentacja partnerów
Wszystko, czego potrzebujesz, aby publikować ogłoszenia sprzedaży i odkupu na QuizzBuy oraz powiadamiać nas o zamówieniach przypisanych do naszego ruchu.
1. Uzyskanie klucza API
Skontaktuj się ze swoim opiekunem QuizzBuy (lub formularzem kontaktowym). Generujemy dla Ciebie klucz w formacie zzb_live_… — jest on przekazywany tylko raz, przechowuj go w bezpiecznym miejscu. Dołączaj go do każdego żądania w nagłówku HTTP:
Authorization: Bearer zzb_live_VOTRE_CLE2. Weryfikacja klucza
curl https://quizzbuy.com/api/v1/me \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"
# Réponse
{
"company": { "id": "…", "name": "Votre société", "slug": "votre-societe" },
"commission_rate": 0.05,
"click_param": "zzb_click"
}3. Publikowanie ogłoszeń
Ogłoszenie to albo oferta odkupu (BUYBACK — odkupujesz urządzenie po danej cenie), albo oferta sprzedaży (SALE — sprzedajesz produkt odnowiony). Wysyłka działa jak upsert: ponowne wysłanie tego samego externalId aktualizuje ogłoszenie.
curl -X POST https://quizzbuy.com/api/v1/listings \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{
"externalId": "ref-interne-123",
"type": "BUYBACK",
"title": "Reprise iPhone 15 Pro 256 Go",
"brand": "Apple",
"model": "iPhone 15 Pro",
"category": "SMARTPHONE",
"storage": "256 GB",
"condition": "GOOD",
"priceCents": 52000,
"currency": "EUR",
"url": "https://votre-site.fr/reprise/iphone-15-pro",
"country": "FR"
}'category: SMARTPHONE, LAPTOP, SMARTWATCH, AUDIO lub GAMING.condition: LIKE_NEW, EXCELLENT, GOOD, FAIR lub BROKEN.priceCents: cena w centach (52000 = 520 €).- Każde nowe ogłoszenie (lub zmiana) przechodzi moderację przed publikacją.
Aktualizacja, listowanie lub dezaktywacja:
# Lister vos annonces
curl "https://quizzbuy.com/api/v1/listings?type=BUYBACK&status=APPROVED" \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"
# Mise à jour partielle
curl -X PATCH https://quizzbuy.com/api/v1/listings/ID_ANNONCE \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "priceCents": 49000 }'
# Désactiver (soft delete)
curl -X DELETE https://quizzbuy.com/api/v1/listings/ID_ANNONCE \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"4. Śledzenie kliknięć
Gdy odwiedzający QuizzBuy kliknie w link do Twojej witryny, docelowy URL zawiera identyfikator kliknięcia:
https://votre-site.fr/vendre?zzb_click=6f1e0c9a-3b2d-4e8f-9a10-abcdef123456Zapisz tę wartość (cookie lub sesja po stronie Twojej witryny, zalecany czas przechowywania: 45 dni). To dzięki niej możliwe będzie przypisanie zamówienia. Nazwa parametru (domyślnie zzb_click) jest konfigurowalna na życzenie.
5. Powiadomienie o zamówieniu (postback S2S)
Gdy tylko klient złoży zamówienie (zakup lub zatwierdzony wniosek o odkup) i posiadasz zzb_click, wywołaj nasz postback z poziomu swojego serwera:
curl -X POST https://quizzbuy.com/api/v1/postback \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{
"click_id": "6f1e0c9a-3b2d-4e8f-9a10-abcdef123456",
"type": "BUYBACK",
"amount_cents": 52000,
"currency": "EUR",
"order_ref": "CMD-2026-000123"
}'
# Réponse 201
{ "conversion_id": "…", "status": "TO_INVOICE", "commission_cents": 2600 }- Okno atrybucji: 45 dni od kliknięcia; po tym czasie odpowiedź
422 attribution_window_expired. order_refmusi być unikalny: duplikat zwraca409 duplicate_order_ref(idempotencja — możesz bezpiecznie ponowić próbę).type:SALEdla zakupu,BUYBACKdla odkupu.currency: wyłącznie EUR — każda inna waluta jest odrzucana (422 unsupported_currency).
6. Testowanie w środowisku sandbox
Dodaj "test": true do postbacku: żądanie jest w pełni walidowane (klucz, click_id, okno 45 dni), ale żadna konwersja nie jest zapisywana ani rozliczana.
{ "click_id": "…", "type": "SALE", "amount_cents": 10000, "order_ref": "TEST-1", "test": true }
# → 200 { "test": true, "valid": true, "commission_cents": 500 }7. Kody błędów
| Kod | Błąd | Wyjaśnienie |
|---|---|---|
| 400 | invalid_input | Nieprawidłowe ciało żądania (szczegóły w odpowiedzi). |
| 401 | unauthorized | Brak klucza API, klucz odwołany lub nieprawidłowy. |
| 404 | click_not_found / not_found | Nieznany click_id lub ogłoszenie (lub nie Twoje). |
| 409 | duplicate_order_ref | Zamówienie już zgłoszone. |
| 422 | attribution_window_expired | Kliknięcie starsze niż 45 dni. |
| 429 | rate_limited | Zbyt wiele żądań — spróbuj ponownie za minutę. |
8. Rozliczenia
Każda przypisana konwersja generuje prowizję (stawka umowna, widoczna przez /api/v1/me). QuizzBuy przesyła Ci okresową fakturę zbiorczą za zatwierdzone konwersje. W razie pytań: skontaktuj się z nami.
9. Marketplace — sprzedaż na QuizzBuy
Ogłoszenia SALE z quantity > 0 są sprzedawane bezpośrednio na QuizzBuy (płatność klienta u nas, wypłata kwoty netto po odjęciu prowizji). Dodatkowe pola: quantity (stan magazynowy), color, grade (A/B/C), batteryHealth (%), warrantyMonths. Ogłoszenie jest automatycznie przypisywane do odpowiedniej karty produktu (marka + model + pojemność + kolor).
# Mettre à jour le stock (sans re-modération)
curl -X PATCH https://quizzbuy.com/api/v1/listings/ID_ANNONCE/stock \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "quantity": 12 }'
# Ajouter une photo (multipart, max 5 × 5 Mo, jpeg/png/webp)
curl -X POST https://quizzbuy.com/api/v1/listings/ID_ANNONCE/images \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-F "file=@photo.jpg"10. Webhooki — powiadomienia o sprzedaży
Zarejestruj punkt końcowy HTTPS; powiadamiamy Cię na każdym etapie zamówienia zawierającego Twoje produkty (order.created, order.paid, order.cancelled). Sekret jest zwracany tylko przy tworzeniu — zapisz go.
curl -X POST https://quizzbuy.com/api/v1/webhooks \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "url": "https://votre-site.fr/webhooks/quizzbuy", "events": ["order.paid"] }'
# Réponse (secret affiché une seule fois)
{ "webhook": { "id": "…", "secret": "whsec_…", "events": ["order.paid"] } }
# Tester
curl -X POST https://quizzbuy.com/api/v1/webhooks/ID_WEBHOOK/test \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"Każda dostawa jest podpisana. Zweryfikuj nagłówek X-ZZbuy-Signature (t=timestamp,v1=hex):
// Node.js
const [t, v1] = signature.split(",").map((p) => p.split("=")[1]);
const expected = crypto
.createHmac("sha256", WEBHOOK_SECRET)
.update(`${t}.${rawBody}`)
.digest("hex");
const valid =
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1)) &&
Math.abs(Date.now() / 1000 - Number(t)) < 300; // anti-replay 5 minW przypadku niepowodzenia (≠ 2xx) ponawiamy próby z opóźnieniem: 1 min, 5 min, 30 min, 2 godz., 12 godz. Otrzymujesz również e-mail z powiadomieniem o sprzedaży.
11. Obsługa zamówień
Wyświetl listę pozycji zamówienia, potwierdź odbiór, a następnie wyślij z numerem śledzenia (klient jest powiadamiany automatycznie). Adres dostawy jest widoczny dopiero po dokonaniu płatności.
# Lister les commandes à traiter
curl "https://quizzbuy.com/api/v1/orders?status=PENDING" \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"
# Accuser réception
curl -X POST https://quizzbuy.com/api/v1/orders/ID_LIGNE/ack \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"
# Expédier
curl -X POST https://quizzbuy.com/api/v1/orders/ID_LIGNE/ship \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "carrier": "Colissimo", "trackingNumber": "6A123456789FR" }'12. Reprise gérée (zorganizowany odkup)
Zorganizowany odkup idzie dalej niż zwykły odkup przez przekierowanie: osoba prywatna zgłasza swoje urządzenie z poziomu QuizzBuy, a Ty zarządzasz całą sprawą przez API (akceptacja, odbiór, kontroferta, płatność). Cena wyświetlana klientowi jest zablokowana w momencie zgłoszenia na podstawie Twojego cennika odkupu (patrz §14); możesz ją obniżyć dopiero po odbiorze, poprzez uzasadnioną kontrofertę.
Wszystkie punkty końcowe uwierzytelniają się Twoim kluczem API (Authorization: Bearer zzb_live_…) i zwracają wyłącznie Twoje sprawy.
Cykl życia
SUBMITTED → ACCEPTED → SHIPPED → RECEIVED → PAID. Dwie rozgałęzienia: REJECTED (odmowa przed wysyłką) i COUNTER_OFFER (kontroferta po inspekcji, którą osoba prywatna akceptuje — wtedy PAID — lub odrzuca — zwrot urządzenia, CANCELLED).
| Status | Znaczenie |
|---|---|
| SUBMITTED | Wniosek utworzony przez osobę prywatną, oczekuje na Twoją decyzję. |
| ACCEPTED | Potwierdziłeś odkup; klient musi wysłać urządzenie. |
| SHIPPED | Osoba prywatna podała numer śledzenia przesyłki. |
| RECEIVED | Odebrałeś urządzenie; trwa inspekcja. |
| COUNTER_OFFER | Po inspekcji proponujesz zmienioną (niższą) kwotę. |
| PAID | Płatność dla osoby prywatnej wykonana — sprawa zamknięta. |
| REJECTED | Wniosek odrzucony przed wysyłką (brak kwalifikacji, oszustwo…). |
| CANCELLED | Anulowane (odmowa kontroferty, zwrot urządzenia). |
Listowanie i przeglądanie
# Lister vos reprises (plus récentes d'abord)
curl "https://quizzbuy.com/api/v1/trade-ins?status=SUBMITTED&limit=50&offset=0" \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"
# Réponse
{
"total": 3,
"trade_ins": [
{
"trade_in_id": "…",
"reference": "TI-2026-000042",
"status": "SUBMITTED",
"device": {
"brand": "Apple", "category": "SMARTPHONE", "model": "iPhone 15 Pro",
"storage": "256 GB", "condition": "GOOD",
"functional_status": "FULLY_WORKING", "battery_health": 92, "imei": "…"
},
"offer_cents": 52000,
"currency": "EUR",
"price_locked_until": "2026-08-05T12:00:00.000Z",
"country": "FR",
"customer": { "email": "…", "first_name": "…", "last_name": "…", "locale": "fr" },
"comment": null,
"counter_offer_cents": null, "counter_reason": null,
"tracking_carrier": null, "tracking_number": null,
"shipping_label_url": null, "payout_ref": null,
"accepted_at": null, "shipped_at": null, "received_at": null,
"paid_at": null, "cancelled_at": null,
"created_at": "2026-07-21T12:00:00.000Z"
}
]
}
# Détail d'une reprise
curl https://quizzbuy.com/api/v1/trade-ins/ID_REPRISE \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"
# → { "trade_in": { … } }status(filtr opcjonalny): jedna z wartości z powyższej tabeli — w przeciwnym razie400 invalid_status.limit: maks. 200 (domyślnie 50);offsetdo paginacji.customer(kontakt osoby prywatnej) jest widoczny wyłącznie w tym API partnerskim, nigdy w webhookach.
Przejścia
Każda akcja to POST i zwraca { "ok": true, "trade_in": { … } }. Przejście z niekompatybilnego statusu zwraca 409 invalid_status (z rzeczywistym current). Osoba prywatna jest powiadamiana e-mailem na każdym etapie.
# 1. Accepter (depuis SUBMITTED) — shippingLabelUrl facultatif (étiquette prépayée)
curl -X POST https://quizzbuy.com/api/v1/trade-ins/ID_REPRISE/accept \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "shippingLabelUrl": "https://votre-site.fr/labels/ti-42.pdf" }'
# 2. Réceptionner l'appareil (depuis SHIPPED ou ACCEPTED)
curl -X POST https://quizzbuy.com/api/v1/trade-ins/ID_REPRISE/receive \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"
# 3a. Payer le montant garanti (depuis RECEIVED) — clôt la reprise
curl -X POST https://quizzbuy.com/api/v1/trade-ins/ID_REPRISE/pay \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "payoutRef": "VIR-2026-000123" }'
# 3b. …ou contre-offrer après inspection (depuis RECEIVED) — montant < offre garantie
curl -X POST https://quizzbuy.com/api/v1/trade-ins/ID_REPRISE/counter \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{ "amountCents": 42000, "reason": "Rayures écran non déclarées" }'
# Refuser avant envoi (depuis SUBMITTED uniquement)
curl -X POST https://quizzbuy.com/api/v1/trade-ins/ID_REPRISE/reject \
-H "Authorization: Bearer zzb_live_VOTRE_CLE"- accept: tylko z
SUBMITTED.shippingLabelUrlopcjonalne (URL, ≤ 500 znaków). - receive: z
SHIPPEDlubACCEPTED(wysyłka/nadanie niezgłoszone przez klienta). - counter: z
RECEIVED.amountCentsmusi być ściśle niższe niżoffer_cents, w przeciwnym razie400 counter_not_lower;reasonobowiązkowe (1–500 znaków). Następnie to osoba prywatna akceptuje lub odrzuca ofertę ze swojej strony śledzenia. - pay: z
RECEIVED.payoutRefobowiązkowe (referencja przelewu, 1–120 znaków). - reject: tylko z
SUBMITTED— brak wymaganego ciała żądania.
13. Webhooki odkupu (trade_in.*)
Te same webhooki (§10, identyczna sygnatura X-ZZbuy-Signature) obejmują zorganizowany odkup. Zapisz się na dowolne lub wszystkie zdarzenia trade_in.* przy tworzeniu punktu końcowego:
curl -X POST https://quizzbuy.com/api/v1/webhooks \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{
"url": "https://votre-site.fr/webhooks/quizzbuy",
"events": ["trade_in.created", "trade_in.shipped", "trade_in.counter_accepted"]
}'| Zdarzenie | Wyzwalacz |
|---|---|
| trade_in.created | Nowy wniosek złożony przez osobę prywatną (status SUBMITTED). |
| trade_in.shipped | Osoba prywatna podała swój numer śledzenia przesyłki. |
| trade_in.counter_accepted | Osoba prywatna zaakceptowała Twoją kontrofertę. |
| trade_in.counter_declined | Osoba prywatna odrzuciła Twoją kontrofertę (zwrot urządzenia). |
| trade_in.cancelled | Odkup anulowany. |
Treść dostawy (kontakt osoby prywatnej nie jest w niej zawarty — pobierz go przez GET /api/v1/trade-ins/:id):
{
"trade_in_id": "…",
"reference": "TI-2026-000042",
"status": "SHIPPED",
"device": {
"brand": "Apple", "category": "SMARTPHONE", "model": "iPhone 15 Pro",
"storage": "256 GB", "condition": "GOOD",
"functional_status": "FULLY_WORKING", "battery_health": 92, "imei": "…"
},
"offer_cents": 52000,
"currency": "EUR",
"price_locked_until": "2026-08-05T12:00:00.000Z",
"country": "FR"
}14. Przesyłanie cennika odkupu
Alternatywa typu „push” dla przepływu CSV pobieranego przez nas: prześlij bezpośrednio swój cennik odkupu. Każdy wiersz zawiera 4 kwoty w zależności od stanu urządzenia. Ceny zasilają tę samą tabelę co automatyczna synchronizacja — pojawiają się więc natychmiast w porównywarce oraz służą jako cena zablokowana dla zorganizowanego odkupu (§12). Operacja to upsert według (marka, kategoria, model, pojemność).
curl -X PUT https://quizzbuy.com/api/v1/buyback/prices \
-H "Authorization: Bearer zzb_live_VOTRE_CLE" \
-H "Content-Type: application/json" \
-d '{
"prices": [
{
"brand": "Apple",
"category": "SMARTPHONE",
"model": "iPhone 15 Pro",
"storage": "256 GB",
"priceNewCents": 60000,
"priceGoodCents": 52000,
"priceFairCents": 40000,
"priceBrokenCents": 15000,
"currency": "EUR",
"url": "https://votre-site.fr/reprise/iphone-15-pro"
}
]
}'
# Réponse
{ "ok": true, "upserted": 1 }prices: od 1 do 2000 wierszy na żądanie.category: SMARTPHONE, TABLET, LAPTOP, SMARTWATCH, AUDIO lub GAMING.priceNewCents(nowy),priceGoodCents(dobry),priceFairCents(używany),priceBrokenCents(uszkodzony) — w centach, ≥ 0.storageiurlopcjonalne; pojemność jest normalizowana automatycznie (np. „256go” → „256 GB”).