Bicops Partner APIv1

Interface d’intégration pour les vendeurs et partenaires entreprises.

Aperçu

Les données de produits, de stock et de prix sont envoyées à Bicops par cette API. Les données de commandes et de finance sont récupérées par la même API. Les requêtes en masse sont traitées depuis une file ; la réponse est 202 avec un identifiant de lot (batchId).

Version : /v1. Les noms de champs ne changent pas. Les messages de réponse sont en anglais ; le champ code est stable.

  • JSON, UTF-8, ISO-8601 (UTC)
  • Chaque réponse contient l’en-tête X-Request-Id
  • Les enregistrements invalides sont rejetés, les valides traités
  • Un enregistrement envoyé avec le même sourceId est mis à jour
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

Authentification

Chaque requête contient les en-têtes X-Api-Key et X-Api-Secret. La clé est émise par Bicops ; le secret n’est affiché qu’à la création.

L’identité du vendeur est déduite de la clé. Aucun identifiant vendeur n’est envoyé dans le corps. Une clé n’accède qu’à son propre compte. Les droits sont définis par des scopes (catalog:read, catalog:write, orders:read).

Une liste d’IP autorisées et une date d’expiration peuvent être définies. Deux clés peuvent être actives pendant une rotation.

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

Test de connexion : GET /v1/me. La réponse liste les scopes et limites de la clé.

Types de clé

Il existe deux types de clé avec des portées différentes. Un service appelé avec le mauvais type renvoie 403.

Clé vendeurCatalogue, commandes, retours, factures, finance, rapports, lots, webhooks. Rattachée à un compte vendeur.
Clé entrepriseComptes clients, relevés, reçus d’encaissement, factures de vente, affectations de représentants. Rattachée à une agence de la société.
Les deuxGET /v1/me, GET /v1/logs/requests, abonnements webhook et GET /v1/events.

Premiers pas

1. Test de connexion

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

2. Envoi des produits (jusqu’à 1 000 enregistrements). Réponse : 202 et 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. Consultation de l’enregistrement de lot : statut, compteurs, erreurs de ligne.

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. Mise à jour des stocks et des prix (jusqu’à 5 000 enregistrements).

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}]}]}'

Catalogue

POST /v1/catalog/products crée ou met à jour les enregistrements via sourceId. Seuls les enregistrements modifiés sont traités.

Champs

ChampTypeDescription
sourceIdstring (≤200)Obligatoire. Référence du vendeur. 200 caractères max.
namestring (≤4000)Obligatoire pour un produit actif.
brandstring (≤200)Nom de la marque.
producerCode, previousCodestring (≤200)Référence fabricant et référence précédente.
oemCodes[]string[] (≤200 items, each ≤100)Références OEM en tableau. Les références ne sont pas concaténées.
equivalentCodes[]string[] (≤200 items)Références équivalentes (« MARQUE RÉFÉRENCE »).
price, currency, pricesIncludeVatdecimal · string(3) · booleanPrix catalogue. TRY, USD ou EUR.
stock, warehouses[]decimal · object[] {code: string, stock: decimal}Stock total et ventilation par entrepôt [{code, stock}].
minOrder, packageAmount, boxAmount, unitinteger · integer · integer · string(≤16)Règles de commande.
desi, weightdecimal · decimalPoids volumétrique et poids (kg).
images[]string[] (URL, ≤10)URL des images (https).
statusinteger (0 | 1)1 actif, 0 inactif.

PATCH /v1/catalog/stock et PATCH /v1/catalog/prices ne mettent à jour que les stocks et les prix. Traités dans la file prioritaire.

Désactivation : DELETE /v1/catalog/products/{sourceId} ou POST /v1/catalog/products/deactivate.

GET /v1/catalog/products renvoie l’état des enregistrements côté Bicops.

Import par fichier

Le catalogue complet est envoyé sous forme de fichier NDJSON (un enregistrement par ligne). gzip est recommandé. Le fichier est téléversé directement dans le stockage.

  1. POST /v1/catalog/imports : obtenir uploadUrl et batchId
  2. Téléverser le fichier en HTTP PUT vers uploadUrl
  3. POST /v1/catalog/imports/{batchId}/complete : lancement du traitement
  4. GET /v1/catalog/batches/{batchId} : suivi
# 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>"

Format du fichier

  • Chaque ligne est un objet JSON autonome. Il n’y a ni virgule ni crochet entre les lignes.
  • Le fichier est encodé en UTF-8 et les lignes se terminent par \n. Les lignes vides sont ignorées.
  • Le seul champ obligatoire est sourceId (votre code de stock). Un champ non transmis conserve sa valeur actuelle.
  • Une ligne mal formée est rejetée seule et le reste du fichier est traité. Les motifs figurent dans GET /v1/catalog/batches/{id}/errors.
  • Si stock et warehouses sont envoyés ensemble, stock doit être égal à la somme des quantités par dépôt.
  • Les produits absents du fichier ne sont pas supprimés. Pour désactiver un produit, envoyez-le avec status: 0.

Fichier d’exemple

{"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}

Télécharger le fichier NDJSON d’exemple

dryRun=true valide le fichier sans écriture. Le premier import de 1 000 000 d’enregistrements prend environ 15 minutes.

Enregistrements de lot

Chaque requête en masse crée un enregistrement de lot. GET /v1/catalog/batches/{id} renvoie statut, compteurs et durées. /errors renvoie les erreurs de ligne ; /errors.csv la même liste en CSV.

queuedEn file
awaiting_uploadEn attente du téléversement
processingEn traitement
syncingMise à jour du catalogue et de l’index de recherche
doneTerminé
partialTerminé, certains enregistrements rejetés
failedÉchec

Compteurs : received, accepted, rejected, changed. Le renvoi de données identiques donne changed = 0.

Points d’accès

Tous les points d’accès sont sous /v1. Les écritures exigent le scope correspondant.

Commandes

Point d’accèsDescription
GET /ordersListe des commandes (status, updatedSince)
GET /orders/{id}Détail de commande
POST /orders/{id}/approveApprouver la commande
POST /orders/{id}/statusMettre à jour le statut {status}
POST /orders/{id}/erp-referenceEnregistrer la référence ERP {reference}
GET /orders/{id}/messagesMessages de commande
GET /orders/{id}/documentsDocuments de commande

Expédition

Point d’accèsDescription
POST /orders/{id}/shipmentsDéclarer votre expédition {trackNumber, cargoId?}
POST /orders/{id}/shipments/createCréer une expédition avec un transporteur Bicops
GET /orders/{id}/shipments/labelÉtiquette d’expédition (PDF, base64)
GET /orders/carriersListe des transporteurs

Retours et annulations

Point d’accèsDescription
GET /returnsDemandes de retour
GET /returns/{id}Détail du retour
POST /returns/{id}/decisionDécision de retour {action: approve|reject}
GET /cancellationsCommandes annulées

Factures

Point d’accèsDescription
GET /orders/{id}/invoicesFichiers de facture liés à la commande
POST /orders/{id}/invoiceJoindre votre facture {fileBase64|fileUrl}
GET /invoicesDocuments émis par Bicops

Finance

Point d’accèsDescription
GET /finance/settlementsRèglement par commande
GET /finance/statementRelevé mensuel
GET /finance/paymentsPaiements par carte

Webhooks et événements

Point d’accèsDescription
GET /webhooksListe des webhooks
POST /webhooksEnregistrer un webhook {url, events[]}
DELETE /webhooks/{id}Désactiver un webhook
POST /webhooks/{id}/testEnvoyer un événement de test
GET /webhooks/deliveriesJournal de livraison
GET /eventsFile d’événements (cursor)

Rapports

Point d’accèsDescription
GET /reports/salesRapport des ventes (groupBy=day|month|product|brand)
GET /reports/returnsTaux de retour
GET /reports/catalogÉtat du catalogue
GET /reports/demandDemande et produits en rupture

Entreprise (clé d’agence)

Point d’accèsDescription
GET /customersComptes clients
GET /customers/{id}/statementRelevé et solde client
GET /accounting/receiptsReçus d’encaissement
GET /accounting/invoicesFactures de vente de l’agence
GET /salesmenAffectations des commerciaux

Codes d’erreur

Réponse d’erreur : { code, message, details[], requestId }. code est stable ; message est une description en anglais.

{
  "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-…"
}

Codes de statut HTTP

UNAUTHORIZED (401)Clé invalide ou absente
FORBIDDEN_SCOPE (403)Scope insuffisant
SELLER_KEY_REQUIRED (403)Le service exige une clé vendeur ; une clé entreprise a été utilisée
CORPORATE_KEY_REQUIRED (403)Le service exige une clé entreprise ; une clé vendeur a été utilisée
SANDBOX_READ_ONLY (403)Une clé bac à sable ne peut pas modifier les commandes, retours ou factures ; les requêtes catalogue sont seulement validées
IP_NOT_ALLOWED (403)IP hors liste autorisée
VALIDATION_FAILED (422)Schéma du corps invalide
PAYLOAD_TOO_LARGE (413)Limite d’enregistrements dépassée
QUEUE_BUSY (429)Limite de lots en attente dépassée ; voir l’en-tête Retry-After
RATE_LIMITED (429)Cadence de requêtes dépassée
NOT_FOUND (404)Enregistrement introuvable
STORAGE_UNAVAILABLE (503)Stockage temporairement indisponible

Codes d’enregistrement (rapport d’erreurs du lot)

SOURCEID_REQUIREDsourceId vide
NAME_REQUIREDNom manquant pour un produit actif
PRICE_NEGATIVE, STOCK_NEGATIVEValeur négative ou non numérique
CURRENCY_INVALIDDevise autre que TRY, USD ou EUR
STATUS_INVALIDstatus différent de 0 ou 1
UNKNOWN_SOURCEIDProduit non défini
INVALID_JSONLigne JSON non valide
OEM_TOO_SHORT (avertissement)Référence de moins de trois caractères ignorée
WAREHOUSE_STOCK_MISMATCH (avertissement)Total des entrepôts utilisé
DUPLICATE_SOURCEID (avertissement)Dernier enregistrement utilisé

Limites

  • Produits : 1 000 enregistrements par requête. Stocks et prix : 5 000 enregistrements par requête. Corps : 6 Mo.
  • Cadence : 600 requêtes par minute et par clé. Au-delà : 429.
  • Lots en attente : 10 par vendeur. Au-delà : 429.
  • Fichier : sans limite d’enregistrements, 2 Go max. (gzip).
  • L’URL de téléversement est valable 15 minutes.

Journal des requêtes

GET /v1/logs/requests renvoie les requêtes des 30 derniers jours : point d’accès, statut, durée, requestId, batchId.

Référence