Dokumentace pro partnery

Vše potřebné k publikování vašich nabídek prodeje a výkupu na QuizzBuy a k oznamování objednávek přiřazených naší návštěvnosti.

1. Získání API klíče

Kontaktujte svého kontaktního partnera QuizzBuy (nebo kontaktní formulář). Vygenerujeme pro vás klíč ve formátu zzb_live_… — je vám sdělen pouze jednou, uchovejte jej na bezpečném místě. Předávejte jej u každého požadavku v HTTP hlavičce:

Authorization: Bearer zzb_live_VOTRE_CLE

2. Ověření vašeho klíče

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. Publikování vašich nabídek

Nabídka je buď nabídka výkupu (BUYBACK — vykoupíte zařízení za danou cenu), nebo nabídka prodeje (SALE — repasovaný produkt, který prodáváte). Odeslání funguje jako upsert: opětovné odeslání stejného externalId nabídku aktualizuje.

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 nebo GAMING.
  • condition: LIKE_NEW, EXCELLENT, GOOD, FAIR nebo BROKEN.
  • priceCents: cena v centech (52000 = 520 €).
  • Každá nová nabídka (nebo úprava) prochází před zveřejněním moderací.

Aktualizace, výpis nebo deaktivace:

# 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. Sledování kliknutí

Když návštěvník QuizzBuy klikne na odkaz na váš web, cílová URL obsahuje identifikátor kliknutí:

https://votre-site.fr/vendre?zzb_click=6f1e0c9a-3b2d-4e8f-9a10-abcdef123456

Uložte si tuto hodnotu (cookie nebo session na straně vašeho webu, doporučená délka: 45 dní). Právě ona umožní přiřadit objednávku. Název parametru (zzb_click ve výchozím nastavení) lze na vyžádání nakonfigurovat.

5. Oznámení objednávky (postback S2S)

Jakmile zákazník zadá objednávku (nákup nebo potvrzená žádost o výkup) a máte k dispozici zzb_click, zavolejte náš postback ze svého serveru:

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 }
  • Atribuční okno: 45 dní od kliknutí; po jeho uplynutí odpověď 422 attribution_window_expired.
  • order_ref musí být jedinečný: duplicita vrací 409 duplicate_order_ref (idempotence — můžete bez rizika zkusit znovu).
  • type: SALE pro nákup, BUYBACK pro výkup.
  • currency: pouze EUR — jakákoli jiná měna je odmítnuta (422 unsupported_currency).

6. Testování v sandboxu

Přidejte "test": true do postbacku: požadavek je zcela validován (klíč, click_id, 45denní okno), ale žádná konverze není zaznamenána ani fakturována.

{ "click_id": "…", "type": "SALE", "amount_cents": 10000, "order_ref": "TEST-1", "test": true }
# → 200 { "test": true, "valid": true, "commission_cents": 500 }

7. Chybové kódy

KódChybaVysvětlení
400invalid_inputNeplatné tělo požadavku (podrobnosti v odpovědi).
401unauthorizedAPI klíč chybí, byl zrušen nebo je neplatný.
404click_not_found / not_foundclick_id nebo nabídka neznámá (nebo není vaše).
409duplicate_order_refObjednávka již byla oznámena.
422attribution_window_expiredKliknutí starší 45 dní.
429rate_limitedPříliš mnoho požadavků — zkuste to znovu za minutu.

8. Fakturace

Každá přiřazená konverze generuje provizi (smluvní sazba, viditelná přes /api/v1/me). QuizzBuy vám zasílá pravidelnou souhrnnou fakturu za potvrzené konverze. V případě dotazů: kontaktujte nás.

9. Marketplace — prodej na QuizzBuy

Nabídky SALE s quantity > 0 se prodávají přímo na QuizzBuy (platba zákazníka probíhá u nás, výplata čisté částky po odečtení provize). Doplňková pole: quantity (sklad), color, grade (A/B/C), batteryHealth (%), warrantyMonths. Nabídka je automaticky přiřazena k odpovídající produktové kartě (značka + model + kapacita + barva).

# 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. Webhooky — upozornění na prodeje

Zaregistrujte HTTPS endpoint; oznámíme vám každou fázi objednávky obsahující vaše produkty (order.created, order.paid, order.cancelled). Secret je vrácen pouze při vytvoření — uložte si jej.

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ždé doručení je podepsáno. Ověřte hlavičku 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 min

V případě selhání (≠ 2xx) opakujeme pokusy s prodlevou: 1 min, 5 min, 30 min, 2 h, 12 h. Obdržíte také e-mail s oznámením o prodeji.

11. Zpracování vašich objednávek

Zobrazte si své položky objednávek, potvrďte přijetí a poté odešlete se sledovacím číslem (zákazník je automaticky upozorněn). Dodací adresa je viditelná až po zaplacení.

# 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. Řízený výkup (trade-in)

Řízený výkup jde dál než jednoduchý výkup přesměrováním: fyzická osoba odešle své zařízení přes QuizzBuy a vy celý případ řídíte přes API (přijetí, převzetí, protinabídka, platba). Cena zobrazená zákazníkovi je při odeslání uzamčena podle vašeho ceníku výkupu (viz §14); revidovat ji směrem dolů můžete až po převzetí prostřednictvím odůvodněné protinabídky.

Všechny endpointy se autentizují vaším API klíčem (Authorization: Bearer zzb_live_…) a vrací pouze vaše případy.

Životní cyklus

SUBMITTEDACCEPTEDSHIPPEDRECEIVEDPAID. Dvě odbočky: REJECTED (odmítnutí před odesláním) a COUNTER_OFFER (protinabídka po kontrole, kterou fyzická osoba přijme — poté PAID — nebo odmítne — vrácení zařízení, CANCELLED).

StavVýznam
SUBMITTEDŽádost vytvořená fyzickou osobou, čeká na vaše rozhodnutí.
ACCEPTEDPotvrdili jste výkup; zákazník musí zařízení odeslat.
SHIPPEDFyzická osoba zadala své sledovací číslo.
RECEIVEDZařízení jste převzali; probíhá kontrola.
COUNTER_OFFERPo kontrole navrhujete revidovanou (nižší) částku.
PAIDPlatba fyzické osobě provedena — případ uzavřen.
REJECTEDŽádost odmítnuta před odesláním (nesplňuje podmínky, podvod…).
CANCELLEDZrušeno (odmítnutí protinabídky, vrácení zařízení).

Výpis a nahlížení

# 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 (volitelný filtr): hodnota z výše uvedené tabulky — jinak 400 invalid_status.
  • limit: max 200 (výchozí 50); offset pro stránkování.
  • customer (kontakt na fyzickou osobu) je viditelný pouze přes toto partnerské API, nikdy ve webhoocích.

Přechody

Každá akce je POST a vrací { "ok": true, "trade_in": { … } }. Přechod z nekompatibilního stavu vrací 409 invalid_status (se skutečným current). Fyzická osoba je při každém kroku upozorněna e-mailem.

# 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: pouze ze stavu SUBMITTED. shippingLabelUrl volitelné (URL, ≤ 500 znaků).
  • receive: ze stavu SHIPPED nebo ACCEPTED (uložení/odeslání neoznámené zákazníkem).
  • counter: ze stavu RECEIVED. amountCents musí být striktně nižší než offer_cents, jinak 400 counter_not_lower; reason povinný (1–500 znaků). Poté fyzická osoba přijme nebo odmítne ze své stránky sledování.
  • pay: ze stavu RECEIVED. payoutRef povinný (referenční číslo platby, 1–120 znaků).
  • reject: pouze ze stavu SUBMITTED — žádné tělo požadavku není potřeba.

13. Webhooky pro výkup (trade_in.*)

Stejné webhooky (§10, identický podpis X-ZZbuy-Signature) pokrývají řízený výkup. Při vytváření endpointu se přihlaste k odběru všech nebo části událostí trade_in.*:

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"]
  }'
UdálostSpouštěč
trade_in.createdNová žádost odeslaná fyzickou osobou (stav SUBMITTED).
trade_in.shippedFyzická osoba zadala sledovací číslo zásilky.
trade_in.counter_acceptedFyzická osoba přijala vaši protinabídku.
trade_in.counter_declinedFyzická osoba odmítla vaši protinabídku (vrácení zařízení).
trade_in.cancelledVýkup zrušen.

Tělo doručení (kontakt na fyzickou osobu se v něm nenachází — získejte jej přes 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. Odeslání vašeho ceníku výkupu

Alternativa typu „push“ k CSV toku staženému z naší strany: odešlete přímo svůj ceník výkupních cen. Každý řádek nese 4 částky podle stavu zařízení. Ceny se ukládají do stejné tabulky jako automatická synchronizace — projeví se tedy okamžitě ve srovnávači a zároveň slouží jako uzamčená cena pro řízený výkup (§12). Operace je upsert podle (značka, kategorie, model, kapacita).

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: 1 až 2000 řádků na požadavek.
  • category: SMARTPHONE, TABLET, LAPTOP, SMARTWATCH, AUDIO nebo GAMING.
  • priceNewCents (nový), priceGoodCents (dobrý), priceFairCents (opotřebený), priceBrokenCents (rozbitý) — v centech, ≥ 0.
  • storage a url volitelné; kapacita se automaticky normalizuje (např. „256go“ → „256 GB“).