Bicops Partner APIv1

Integrationsschnittstelle für Händler und Unternehmenspartner.

Überblick

Produkt-, Bestands- und Preisdaten werden über diese API an Bicops gesendet. Bestell- und Finanzdaten werden über dieselbe API abgerufen. Massenanfragen werden aus einer Warteschlange verarbeitet; die Antwort ist 202 mit einer Batch-Kennung (batchId).

Version: /v1. Feldnamen ändern sich nicht. Antwortmeldungen sind auf Englisch; das Feld code ist stabil.

  • JSON, UTF-8, ISO-8601 (UTC)
  • Jede Antwort enthält den Header X-Request-Id
  • Ungültige Datensätze werden abgelehnt, gültige verarbeitet
  • Ein Datensatz mit derselben sourceId wird aktualisiert
GET /v1/me
POST /v1/catalog/products
PATCH /v1/catalog/stock · /v1/catalog/prices
DELETE /v1/catalog/products/{sourceId}
POST /v1/catalog/imports → /{batchId}/complete
GET /v1/catalog/products · /v1/catalog/batches/{id} · /v1/logs/requests

Authentifizierung

Jede Anfrage enthält die Header X-Api-Key und X-Api-Secret. Der Schlüssel wird von Bicops ausgestellt; das Secret wird nur bei der Erstellung angezeigt.

Die Händleridentität ergibt sich aus dem Schlüssel. Im Anfragekörper wird keine Händlerkennung gesendet. Ein Schlüssel greift nur auf das eigene Konto zu. Berechtigungen werden über Scopes definiert (catalog:read, catalog:write, orders:read).

IP-Allowlist und Ablaufdatum können gesetzt werden. Bei der Rotation können zwei Schlüssel aktiv sein.

X-Api-Key: 2c1d5c7e-2a1b-4c1e-9d7a-2b6f0e3c9a11
X-Api-Secret: 4Qb…(base64url, 43 chars)
Content-Type: application/json
X-Request-Id: optional-your-correlation-id

Verbindungstest: GET /v1/me. Die Antwort enthält Scopes und Limits des Schlüssels.

Schlüsseltypen

Es gibt zwei Schlüsseltypen mit unterschiedlicher Reichweite. Ein Dienst, der mit dem falschen Typ aufgerufen wird, antwortet mit 403.

VerkäuferschlüsselKatalog, Bestellungen, Retouren, Rechnungen, Finanzen, Berichte, Batches, Webhooks. An ein Verkäuferkonto gebunden.
FirmenschlüsselKundenkonten, Kontoauszüge, Zahlungsbelege, Verkaufsrechnungen, Vertreterzuordnungen. An eine Unternehmensfiliale gebunden.
BeideGET /v1/me, GET /v1/logs/requests, Webhook-Abonnements und GET /v1/events.

Erste Schritte

1. Verbindungstest

curl -s https://partner.bicops.tr/v1/me \
  -H "X-Api-Key: 2c1d5c7e-2a1b-4c1e-9d7a-2b6f0e3c9a11" \
  -H "X-Api-Secret: <your-secret>"

2. Produkte übermitteln (bis zu 1.000 Datensätze). Antwort: 202 und batchId.

curl -s -X POST https://partner.bicops.tr/v1/catalog/products \
  -H "X-Api-Key: <key>" -H "X-Api-Secret: <secret>" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [{
      "sourceId": "SACHS 317 572",
      "name": "AMORTISOR ON AUDI A3 / GOLF V",
      "brand": "SACHS",
      "producerCode": "317 572",
      "oemCodes": ["1T0413031CN", "1T0413031CK"],
      "equivalentCodes": ["FEBI 106124"],
      "price": 3869.60, "currency": "TRY", "pricesIncludeVat": false,
      "stock": 12,
      "warehouses": [{ "code": "ANK", "stock": 8 }, { "code": "IZM", "stock": 4 }],
      "minOrder": 1, "packageAmount": 1, "unit": "AD", "desi": 3.2,
      "images": ["https://cdn.example.com/317572.jpg"],
      "status": 1
    }]
  }'
HTTP/1.1 202 Accepted
X-Request-Id: 7c0e1c5a-…
{
  "batchId": 1042, "status": "queued",
  "received": 1, "accepted": 1, "rejected": 0, "warnings": 0,
  "chunks": 1, "dryRun": false, "issues": [], "requestId": "7c0e1c5a-…"
}

3. Batch-Datensatz abfragen: Status, Zähler, Zeilenfehler.

curl -s https://partner.bicops.tr/v1/catalog/batches/1042 -H "X-Api-Key: <key>" -H "X-Api-Secret: <secret>"
curl -s https://partner.bicops.tr/v1/catalog/batches/1042/errors.csv -H "X-Api-Key: <key>" -H "X-Api-Secret: <secret>" -o errors.csv

4. Bestand und Preise aktualisieren (bis zu 5.000 Datensätze).

curl -s -X PATCH https://partner.bicops.tr/v1/catalog/stock \
  -H "X-Api-Key: <key>" -H "X-Api-Secret: <secret>" -H "Content-Type: application/json" \
  -d '{"items":[{"sourceId":"SACHS 317 572","stock":9,"warehouses":[{"code":"ANK","stock":5},{"code":"IZM","stock":4}]}]}'

Katalog

POST /v1/catalog/products legt Datensätze anhand der sourceId an oder aktualisiert sie. Nur geänderte Datensätze werden verarbeitet.

Felder

FeldTypBeschreibung
sourceIdstring (≤200)Pflicht. Artikelnummer des Händlers. Bis zu 200 Zeichen.
namestring (≤4000)Pflicht für aktive Produkte.
brandstring (≤200)Markenname.
producerCode, previousCodestring (≤200)Herstellernummer und Vorgängernummer.
oemCodes[]string[] (≤200 items, each ≤100)OEM-Nummern als Array. Nummern werden nicht zusammengefügt.
equivalentCodes[]string[] (≤200 items)Vergleichsnummern („MARKE NUMMER“).
price, currency, pricesIncludeVatdecimal · string(3) · booleanListenpreis. TRY, USD oder EUR.
stock, warehouses[]decimal · object[] {code: string, stock: decimal}Gesamtbestand und Aufteilung je Lager [{code, stock}].
minOrder, packageAmount, boxAmount, unitinteger · integer · integer · string(≤16)Bestellregeln.
desi, weightdecimal · decimalVolumengewicht und Gewicht (kg).
images[]string[] (URL, ≤10)Bild-URLs (https).
statusinteger (0 | 1)1 aktiv, 0 inaktiv.

PATCH /v1/catalog/stock und PATCH /v1/catalog/prices aktualisieren nur Bestand und Preise. Verarbeitung in der Prioritätswarteschlange.

Deaktivierung: DELETE /v1/catalog/products/{sourceId} oder POST /v1/catalog/products/deactivate.

GET /v1/catalog/products liefert den Zustand der Datensätze auf Bicops-Seite.

Dateiimport

Vollständige Kataloge werden als NDJSON-Datei gesendet (ein Datensatz pro Zeile). gzip wird empfohlen. Die Datei wird direkt in den Speicher hochgeladen.

  1. POST /v1/catalog/imports: uploadUrl und batchId abrufen
  2. Datei per HTTP PUT an uploadUrl hochladen
  3. POST /v1/catalog/imports/{batchId}/complete: Verarbeitung starten
  4. GET /v1/catalog/batches/{batchId}: Fortschritt verfolgen
# 1
curl -s -X POST https://partner.bicops.tr/v1/catalog/imports -H "X-Api-Key: <key>" -H "X-Api-Secret: <secret>" \
  -H "Content-Type: application/json" -d '{"format":"ndjson","gzip":true}'
# → {"batchId":1043,"uploadUrl":"https://files.bicops.tr/partner-raw/…","expiresInSec":900}
# 2
curl -s -X PUT "<uploadUrl>" -H "Content-Type: application/octet-stream" --data-binary @catalog.ndjson.gz
# 3
curl -s -X POST https://partner.bicops.tr/v1/catalog/imports/1043/complete -H "X-Api-Key: <key>" -H "X-Api-Secret: <secret>"

Dateiformat

  • Jede Zeile ist ein eigenständiges JSON-Objekt. Zwischen den Zeilen stehen keine Kommas und keine eckigen Klammern.
  • Die Datei ist UTF-8-kodiert, Zeilenende \n. Leere Zeilen werden übersprungen.
  • Pflichtfeld ist nur sourceId (Ihr Lagercode). Ein nicht gesendetes Feld behält seinen aktuellen Wert.
  • Eine fehlerhafte Zeile wird einzeln abgelehnt, der Rest der Datei wird verarbeitet. Gründe unter GET /v1/catalog/batches/{id}/errors.
  • Werden stock und warehouses zusammen gesendet, muss stock der Summe der Lagerbestände entsprechen.
  • Produkte, die in der Datei fehlen, werden nicht gelöscht. Zum Deaktivieren das Produkt mit status: 0 senden.

Beispieldatei

{"sourceId":"SACHS 317 572","name":"AMORTISOR ON AUDI A3 / GOLF V","brand":"SACHS","producerCode":"317 572","previousCode":"317 571","oemCodes":["1T0413031CN","1T0413031CK"],"equivalentCodes":["FEBI 106124"],"barcodes":["4054228012345"],"price":3869.6,"currency":"TRY","pricesIncludeVat":false,"stock":12,"warehouses":[{"code":"ANK","stock":8},{"code":"IST","stock":4}],"minOrder":1,"packageAmount":1,"boxAmount":2,"unit":"AD","desi":3.2,"weight":1.25,"images":["https://cdn.satici.com/317572.jpg"],"categoryHint":"Amortisor","vehicleHint":"VW Golf V 2003-2008","status":1}
{"sourceId":"MANN W 712/95","name":"YAG FILTRESI","brand":"MANN","oemCodes":["W 712/95","1109AY"],"price":210.5,"currency":"TRY","stock":0,"status":1}
{"sourceId":"BOSCH 0986495255","name":"FREN BALATASI ON","brand":"BOSCH","oemCodes":["0986495255"],"price":1250,"currency":"TRY","stock":6,"warehouses":[{"code":"IZM","stock":6}],"status":1}
{"sourceId":"SACHS 317 571","status":0}

Beispiel-NDJSON-Datei herunterladen

dryRun=true prüft die Datei ohne Schreibvorgang. Der Erstimport von 1.000.000 Datensätzen dauert etwa 15 Minuten.

Batch-Datensätze

Jede Massenanfrage erzeugt einen Batch-Datensatz. GET /v1/catalog/batches/{id} liefert Status, Zähler und Dauern. /errors liefert Zeilenfehler; /errors.csv dieselbe Liste als CSV.

queuedIn Warteschlange
awaiting_uploadWarten auf Datei-Upload
processingIn Verarbeitung
syncingKatalog und Suchindex werden aktualisiert
doneAbgeschlossen
partialAbgeschlossen, einige Datensätze abgelehnt
failedFehlgeschlagen

Zähler: received, accepted, rejected, changed. Bei erneuter Übermittlung identischer Daten ist changed = 0.

Endpunkte

Alle Endpunkte liegen unter /v1. Schreibende Endpunkte erfordern den entsprechenden Scope.

Bestellungen

EndpunktBeschreibung
GET /ordersBestellliste (status, updatedSince)
GET /orders/{id}Bestelldetail
POST /orders/{id}/approveBestellung freigeben
POST /orders/{id}/statusStatus aktualisieren {status}
POST /orders/{id}/erp-referenceERP-Referenz speichern {reference}
GET /orders/{id}/messagesBestellnachrichten
GET /orders/{id}/documentsBestelldokumente

Versand

EndpunktBeschreibung
POST /orders/{id}/shipmentsEigene Sendung melden {trackNumber, cargoId?}
POST /orders/{id}/shipments/createSendung mit Bicops-Carrier erstellen
GET /orders/{id}/shipments/labelVersandlabel (PDF, base64)
GET /orders/carriersCarrier-Liste

Retouren und Stornierungen

EndpunktBeschreibung
GET /returnsRetourenanfragen
GET /returns/{id}Retourendetail
POST /returns/{id}/decisionRetourenentscheidung {action: approve|reject}
GET /cancellationsStornierte Bestellungen

Rechnungen

EndpunktBeschreibung
GET /orders/{id}/invoicesRechnungsdateien der Bestellung
POST /orders/{id}/invoiceEigene Rechnung anhängen {fileBase64|fileUrl}
GET /invoicesVon Bicops an Sie ausgestellte Belege

Finanzen

EndpunktBeschreibung
GET /finance/settlementsAbrechnung je Bestellung
GET /finance/statementMonatsauszug
GET /finance/paymentsKartenzahlungen

Webhooks und Ereignisse

EndpunktBeschreibung
GET /webhooksWebhook-Liste
POST /webhooksWebhook registrieren {url, events[]}
DELETE /webhooks/{id}Webhook deaktivieren
POST /webhooks/{id}/testTestereignis senden
GET /webhooks/deliveriesZustellprotokoll
GET /eventsEreigniswarteschlange (cursor)

Berichte

EndpunktBeschreibung
GET /reports/salesVerkaufsbericht (groupBy=day|month|product|brand)
GET /reports/returnsRetourenquote
GET /reports/catalogKatalogzustand
GET /reports/demandNachfrage und ausverkaufte Produkte

Unternehmen (Filialschlüssel)

EndpunktBeschreibung
GET /customersKundenkonten
GET /customers/{id}/statementKontoauszug und Saldo
GET /accounting/receiptsZahlungsquittungen
GET /accounting/invoicesVerkaufsrechnungen der Filiale
GET /salesmenZuordnung der Vertriebsmitarbeiter

Fehlercodes

Fehlerantwort: { code, message, details[], requestId }. code ist stabil; message ist eine englische Beschreibung.

{
  "code": "VALIDATION_FAILED",
  "message": "Request body validation failed",
  "details": [{ "field": "items.0.price", "code": "INVALID_FIELD", "message": "price must not be less than 0" }],
  "requestId": "7c0e1c5a-…"
}

HTTP-Statuscodes

UNAUTHORIZED (401)Schlüssel ungültig oder fehlend
FORBIDDEN_SCOPE (403)Scope nicht ausreichend
SELLER_KEY_REQUIRED (403)Der Dienst benötigt einen Verkäuferschlüssel; es wurde ein Firmenschlüssel verwendet
CORPORATE_KEY_REQUIRED (403)Der Dienst benötigt einen Firmenschlüssel; es wurde ein Verkäuferschlüssel verwendet
SANDBOX_READ_ONLY (403)Ein Sandbox-Schlüssel kann Bestellungen, Retouren und Rechnungen nicht ändern; Kataloganfragen werden nur geprüft
IP_NOT_ALLOWED (403)IP nicht in der Allowlist
VALIDATION_FAILED (422)Ungültiges Körperschema
PAYLOAD_TOO_LARGE (413)Datensatzlimit überschritten
QUEUE_BUSY (429)Limit wartender Batches überschritten; siehe Header Retry-After
RATE_LIMITED (429)Anfragerate überschritten
NOT_FOUND (404)Datensatz nicht gefunden
STORAGE_UNAVAILABLE (503)Speicher vorübergehend nicht verfügbar

Datensatzcodes (Batch-Fehlerbericht)

SOURCEID_REQUIREDsourceId ist leer
NAME_REQUIREDName für aktives Produkt fehlt
PRICE_NEGATIVE, STOCK_NEGATIVENegativer oder nicht numerischer Wert
CURRENCY_INVALIDWährung nicht TRY, USD oder EUR
STATUS_INVALIDstatus nicht 0 oder 1
UNKNOWN_SOURCEIDProdukt nicht definiert
INVALID_JSONZeile ist kein gültiges JSON
OEM_TOO_SHORT (Warnung)Nummer kürzer als drei Zeichen übersprungen
WAREHOUSE_STOCK_MISMATCH (Warnung)Lagersumme verwendet
DUPLICATE_SOURCEID (Warnung)Letzter Datensatz verwendet

Limits

  • Produkte: 1.000 Datensätze pro Anfrage. Bestand und Preise: 5.000 Datensätze pro Anfrage. Körper: 6 MB.
  • Anfragerate: 600 Anfragen pro Minute je Schlüssel. Bei Überschreitung 429.
  • Wartende Batches: 10 je Händler. Bei Überschreitung 429.
  • Datei: kein Datensatzlimit, bis zu 2 GB (gzip).
  • Die Upload-URL ist 15 Minuten gültig.

Anfrageprotokoll

GET /v1/logs/requests liefert die Anfragen der letzten 30 Tage: Endpunkt, Status, Dauer, requestId, batchId.

Referenz