Partner-Dokumentation

Alles, was Sie brauchen, um Ihre Verkaufs- und Rückkaufangebote auf QuizzBuy zu veröffentlichen und uns die unserem Traffic zugeordneten Bestellungen zu melden.

1. API-Schlüssel erhalten

Kontaktieren Sie Ihren QuizzBuy-Ansprechpartner (oder das Kontaktformular). Wir generieren für Sie einen Schlüssel im Format zzb_live_… — er wird Ihnen nur einmal mitgeteilt, bewahren Sie ihn sicher auf. Übergeben Sie ihn bei jeder Anfrage im HTTP-Header:

Authorization: Bearer zzb_live_VOTRE_CLE

2. Ihren Schlüssel überprüfen

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. Ihre Angebote veröffentlichen

Ein Angebot ist entweder ein Rückkaufangebot (BUYBACK — Sie kaufen ein Gerät zu einem bestimmten Preis zurück) oder ein Verkaufsangebot (SALE — ein generalüberholtes Produkt, das Sie verkaufen). Das Senden ist ein Upsert: erneutes Senden derselben externalId aktualisiert das Angebot.

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 oder GAMING.
  • condition: LIKE_NEW, EXCELLENT, GOOD, FAIR oder BROKEN.
  • priceCents: Preis in Cent (52000 = 520 €).
  • Jedes neue Angebot (oder jede Änderung) durchläuft vor der Veröffentlichung eine Moderation.

Aktualisieren, auflisten oder deaktivieren:

# 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. Klick-Tracking

Wenn ein QuizzBuy-Besucher auf Ihre Website klickt, enthält die Ziel-URL eine Klick-Kennung:

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

Speichern Sie diesen Wert (Cookie oder Session auf Ihrer Website, empfohlene Dauer: 45 Tage). Er ermöglicht die Zuordnung der Bestellung. Der Name des Parameters (zzb_click standardmäßig) ist auf Anfrage konfigurierbar.

5. Eine Bestellung melden (S2S-Postback)

Sobald ein Kunde eine Bestellung aufgibt (Kauf oder bestätigte Rückkaufanfrage) und Sie über einen zzb_click verfügen, rufen Sie unser Postback von Ihrem Server aus auf:

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 }
  • Zuordnungsfenster: 45 Tage nach dem Klick; danach Antwort 422 attribution_window_expired.
  • order_ref muss eindeutig sein: ein Duplikat liefert 409 duplicate_order_ref (Idempotenz — Sie können gefahrlos erneut versuchen).
  • type: SALE für einen Kauf, BUYBACK für einen Rückkauf.
  • currency: ausschließlich EUR — jede andere Währung wird abgelehnt (422 unsupported_currency).

6. In der Sandbox testen

Fügen Sie "test": true zum Postback hinzu: die Anfrage wird vollständig validiert (Schlüssel, click_id, 45-Tage-Fenster), aber es wird keine Conversion erfasst oder abgerechnet.

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

7. Fehlercodes

CodeFehlerErklärung
400invalid_inputUngültiger Anfragekörper (Details in der Antwort).
401unauthorizedAPI-Schlüssel fehlt, wurde widerrufen oder ist ungültig.
404click_not_found / not_foundclick_id oder Angebot unbekannt (oder nicht Ihres).
409duplicate_order_refBestellung bereits gemeldet.
422attribution_window_expiredKlick älter als 45 Tage.
429rate_limitedZu viele Anfragen — versuchen Sie es in einer Minute erneut.

8. Abrechnung

Jede zugeordnete Conversion generiert eine Provision (vertraglicher Satz, einsehbar über /api/v1/me). QuizzBuy stellt Ihnen periodisch eine zusammenfassende Rechnung der validierten Conversions aus. Bei Fragen: kontaktieren Sie uns.

9. Marketplace — auf QuizzBuy verkaufen

Angebote vom Typ SALE mit quantity > 0 werden direkt auf QuizzBuy verkauft (Kundenzahlung bei uns, Auszahlung des Nettobetrags nach Provision). Zusätzliche Felder: quantity (Bestand), color, grade (A/B/C), batteryHealth (%), warrantyMonths. Das Angebot wird automatisch der entsprechenden Produktseite zugeordnet (Marke + Modell + Speicherkapazität + Farbe).

# 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. Webhooks — über Verkäufe informiert werden

Registrieren Sie einen HTTPS-Endpunkt; wir benachrichtigen Sie bei jedem Schritt einer Bestellung, die Ihre Produkte enthält (order.created, order.paid, order.cancelled). Das Secret wird nur bei der Erstellung zurückgegeben — speichern Sie es.

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"

Jede Zustellung ist signiert. Überprüfen Sie den Header 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

Bei Fehlschlag (≠ 2xx) versuchen wir es mit Backoff erneut: 1 Min., 5 Min., 30 Min., 2 Std., 12 Std. Sie erhalten außerdem eine E-Mail-Benachrichtigung über den Verkauf.

11. Ihre Bestellungen bearbeiten

Listen Sie Ihre Bestellpositionen auf, bestätigen Sie den Eingang und versenden Sie dann mit einer Sendungsverfolgungsnummer (der Kunde wird automatisch benachrichtigt). Die Lieferadresse ist erst nach der Zahlung sichtbar.

# 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. Verwaltete Rücknahme (Trade-in)

Die verwaltete Rücknahme geht über den einfachen Rückkauf per Weiterleitung hinaus: die Privatperson reicht ihr Gerät über QuizzBuy ein, und Sie steuern den gesamten Vorgang über die API (Annahme, Empfang, Gegenangebot, Zahlung). Der dem Kunden angezeigte Preis wird bei der Einreichung anhand Ihrer Rückkauf-Preistabelle festgeschrieben (siehe §14); Sie können ihn erst nach Erhalt und nur über ein begründetes Gegenangebot nach unten korrigieren.

Alle Endpunkte authentifizieren sich mit Ihrem API-Schlüssel (Authorization: Bearer zzb_live_…) und geben nur Ihre Vorgänge zurück.

Lebenszyklus

SUBMITTEDACCEPTEDSHIPPEDRECEIVEDPAID. Zwei Abzweigungen: REJECTED (Ablehnung vor Versand) und COUNTER_OFFER (Gegenangebot nach Prüfung, das die Privatperson annimmt — dann PAID — oder ablehnt — Geräterückgabe, CANCELLED).

StatusBedeutung
SUBMITTEDAnfrage von der Privatperson erstellt, wartet auf Ihre Entscheidung.
ACCEPTEDSie haben die Rücknahme bestätigt; der Kunde muss das Gerät versenden.
SHIPPEDDie Privatperson hat ihre Sendungsverfolgungsnummer angegeben.
RECEIVEDSie haben das Gerät erhalten; Prüfung läuft.
COUNTER_OFFERNach der Prüfung schlagen Sie einen revidierten (niedrigeren) Betrag vor.
PAIDZahlung an die Privatperson erfolgt — Vorgang abgeschlossen.
REJECTEDAnfrage vor Versand abgelehnt (nicht berechtigt, Betrug …).
CANCELLEDStorniert (Ablehnung eines Gegenangebots, Geräterückgabe).

Auflisten & einsehen

# 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 (optionaler Filter): ein Wert aus der obigen Tabelle — sonst 400 invalid_status.
  • limit: max. 200 (Standard 50); offset für die Paginierung.
  • Der customer (Kontakt der Privatperson) ist nur über diese Partner-API sichtbar, niemals in den Webhooks.

Übergänge

Jede Aktion ist ein POST und liefert { "ok": true, "trade_in": { … } }. Ein Übergang von einem inkompatiblen Status liefert 409 invalid_status (mit dem tatsächlichen current). Die Privatperson wird bei jedem Schritt per E-Mail benachrichtigt.

# 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: nur ab SUBMITTED. shippingLabelUrl optional (URL, ≤ 500 Zeichen).
  • receive: ab SHIPPED oder ACCEPTED (vom Kunden nicht gemeldeter Versand/Abgabe).
  • counter: ab RECEIVED. amountCents muss strikt niedriger als offer_cents sein, sonst 400 counter_not_lower; reason erforderlich (1–500 Zeichen). Anschließend nimmt die Privatperson über ihre Tracking-Seite an oder lehnt ab.
  • pay: ab RECEIVED. payoutRef erforderlich (Überweisungsreferenz, 1–120 Zeichen).
  • reject: nur ab SUBMITTED — kein Body erforderlich.

13. Rücknahme-Webhooks (trade_in.*)

Dieselben Webhooks (§10, identische Signatur X-ZZbuy-Signature) decken die verwaltete Rücknahme ab. Abonnieren Sie bei der Erstellung eines Endpunkts alle oder einen Teil der Ereignisse 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"]
  }'
EreignisAuslöser
trade_in.createdNeue Anfrage von einer Privatperson eingereicht (Status SUBMITTED).
trade_in.shippedDie Privatperson hat ihre Sendungsverfolgung angegeben.
trade_in.counter_acceptedDie Privatperson hat Ihr Gegenangebot angenommen.
trade_in.counter_declinedDie Privatperson hat Ihr Gegenangebot abgelehnt (Geräterückgabe).
trade_in.cancelledRücknahme storniert.

Body der Zustellung (der Kontakt der Privatperson erscheint hier nicht — rufen Sie ihn über GET /api/v1/trade-ins/:id ab):

{
  "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. Ihre Rückkauf-Preistabelle übertragen

Alternative „Push“-Methode zum von uns gezogenen CSV-Flow: senden Sie Ihre Rückkauf-Preistabelle direkt. Jede Zeile enthält die 4 Beträge je nach Gerätezustand. Die Preise fließen in dieselbe Tabelle wie die automatische Synchronisation ein — sie erscheinen also sofort im Vergleichstool und dienen als festgeschriebener Preis für die verwaltete Rücknahme (§12). Der Vorgang ist ein Upsert nach (Marke, Kategorie, Modell, Speicherkapazität).

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 bis 2000 Zeilen pro Anfrage.
  • category: SMARTPHONE, TABLET, LAPTOP, SMARTWATCH, AUDIO oder GAMING.
  • priceNewCents (neu), priceGoodCents (gut), priceFairCents (gebraucht), priceBrokenCents (defekt) — in Cent, ≥ 0.
  • storage und url optional; die Speicherkapazität wird automatisch normalisiert (z. B. „256go“ → „256 GB“).