Overview
Product, stock and price data is sent to Bicops through this API. Order and finance data is retrieved through the same API. Bulk requests are processed from a queue; the response is 202 with a batch identifier (batchId).
Version: /v1. Field names do not change. Response messages are in English; the code field is stable.
- JSON, UTF-8, ISO-8601 (UTC)
- Every response includes the X-Request-Id header
- Invalid rows are rejected, valid rows are processed
- A record sent with the same sourceId is updated
/v1/me/v1/catalog/products/v1/catalog/stock · /v1/catalog/prices/v1/catalog/products/{sourceId}/v1/catalog/imports → /{batchId}/complete/v1/catalog/products · /v1/catalog/batches/{id} · /v1/logs/requestsAuthentication
Every request carries the X-Api-Key and X-Api-Secret headers. The key is issued by Bicops; the secret is shown only at creation.
The seller identity comes from the key. No seller identifier is sent in the body. A key accesses only its own account. Permissions are defined by scopes (catalog:read, catalog:write, orders:read).
An IP allowlist and an expiry date can be set. Two keys can be active during 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-idConnectivity test: GET /v1/me. The response lists the scopes and limits of the key.
Key types
There are two key types with different reach. Calling a service with the wrong type returns 403.
Seller key | Catalog, orders, returns, invoices, finance, reports, batches, webhooks. Bound to a seller account. |
Corporate key | Customer accounts, statements, collection receipts, sales invoices, sales representative assignments. Bound to a company branch. |
Both | GET /v1/me, GET /v1/logs/requests, webhook subscriptions and GET /v1/events. |
Getting started
1. Connectivity test
curl -s https://partner.bicops.tr/v1/me \
-H "X-Api-Key: 2c1d5c7e-2a1b-4c1e-9d7a-2b6f0e3c9a11" \
-H "X-Api-Secret: <your-secret>"
2. Submit products (up to 1,000 records). Response: 202 and 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. Query the batch record: status, counts, row errors.
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. Update stock and prices (up to 5,000 records).
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}]}]}'Catalog
POST /v1/catalog/products inserts or updates records by sourceId. Only changed records are processed.
Fields
| Field | Type | Description |
|---|---|---|
sourceId | string (≤200) | Required. Seller stock code. Up to 200 characters. |
name | string (≤4000) | Required for active products. |
brand | string (≤200) | Brand name. |
producerCode, previousCode | string (≤200) | Manufacturer part number and superseded number. |
oemCodes[] | string[] (≤200 items, each ≤100) | OEM numbers as an array. Numbers are not concatenated. |
equivalentCodes[] | string[] (≤200 items) | Cross-reference numbers ("BRAND NUMBER"). |
price, currency, pricesIncludeVat | decimal · string(3) · boolean | List price. TRY, USD or EUR. |
stock, warehouses[] | decimal · object[] {code: string, stock: decimal} | Total stock and per-warehouse breakdown [{code, stock}]. |
minOrder, packageAmount, boxAmount, unit | integer · integer · integer · string(≤16) | Ordering rules. |
desi, weight | decimal · decimal | Volumetric weight and weight (kg). |
images[] | string[] (URL, ≤10) | Image URLs (https). |
status | integer (0 | 1) | 1 active, 0 inactive. |
PATCH /v1/catalog/stock and PATCH /v1/catalog/prices update stock and prices only. Processed on the priority queue.
Deactivation: DELETE /v1/catalog/products/{sourceId} or POST /v1/catalog/products/deactivate.
GET /v1/catalog/products returns the state of the records on the Bicops side.
File import
Full catalogs are sent as an NDJSON file (one record per line). gzip is recommended. The file is uploaded directly to storage.
- POST /v1/catalog/imports: obtain uploadUrl and batchId
- Upload the file with HTTP PUT to uploadUrl
- POST /v1/catalog/imports/{batchId}/complete: processing starts
- GET /v1/catalog/batches/{batchId}: track progress
# 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>"
File format
- Each line is a standalone JSON object. There are no commas or square brackets between lines.
- The file is UTF-8 encoded and lines end with \n. Blank lines are skipped.
- Only sourceId (your stock code) is required. A field you omit keeps its current value.
- A malformed line is rejected on its own and the rest of the file is processed. Reasons are listed at GET /v1/catalog/batches/{id}/errors.
- If stock and warehouses are both sent, stock must equal the sum of the warehouse quantities.
- Products missing from the file are not deleted. Send that product with status: 0 to deactivate it.
Sample file
{"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}
Download the sample NDJSON file
dryRun=true validates the file without writing. The first import of 1,000,000 records takes about 15 minutes.
Batch records
Every bulk request creates a batch record. GET /v1/catalog/batches/{id} returns status, counts and durations. /errors returns row errors; /errors.csv returns the same list as CSV.
queued | Queued |
awaiting_upload | Waiting for file upload |
processing | Processing |
syncing | Updating catalog and search index |
done | Completed |
partial | Completed, some records rejected |
failed | Failed |
Counts: received, accepted, rejected, changed. Resending identical data yields changed = 0.
Endpoints
All endpoints are under /v1. Write endpoints require the corresponding scope.
Orders
| Endpoint | Description |
|---|---|
GET /orders | Order list (status, updatedSince) |
GET /orders/{id} | Order detail |
POST /orders/{id}/approve | Approve the order |
POST /orders/{id}/status | Update status {status} |
POST /orders/{id}/erp-reference | Store ERP reference {reference} |
GET /orders/{id}/messages | Order messages |
GET /orders/{id}/documents | Order documents |
Shipping
| Endpoint | Description |
|---|---|
POST /orders/{id}/shipments | Register your own shipment {trackNumber, cargoId?} |
POST /orders/{id}/shipments/create | Create a shipment with a Bicops carrier |
GET /orders/{id}/shipments/label | Shipment label (PDF, base64) |
GET /orders/carriers | Carrier list |
Returns and cancellations
| Endpoint | Description |
|---|---|
GET /returns | Return requests |
GET /returns/{id} | Return detail |
POST /returns/{id}/decision | Return decision {action: approve|reject} |
GET /cancellations | Cancelled orders |
Invoices
| Endpoint | Description |
|---|---|
GET /orders/{id}/invoices | Invoice files attached to the order |
POST /orders/{id}/invoice | Attach your invoice {fileBase64|fileUrl} |
GET /invoices | Documents issued to you by Bicops |
Finance
| Endpoint | Description |
|---|---|
GET /finance/settlements | Per-order settlement |
GET /finance/statement | Monthly statement |
GET /finance/payments | Card payments |
Webhooks and events
| Endpoint | Description |
|---|---|
GET /webhooks | Webhook list |
POST /webhooks | Register a webhook {url, events[]} |
DELETE /webhooks/{id} | Disable a webhook |
POST /webhooks/{id}/test | Send a test event |
GET /webhooks/deliveries | Delivery log |
GET /events | Event queue (cursor) |
Reports
| Endpoint | Description |
|---|---|
GET /reports/sales | Sales report (groupBy=day|month|product|brand) |
GET /reports/returns | Return rate |
GET /reports/catalog | Catalog health |
GET /reports/demand | Demand and out-of-stock products |
Corporate (branch key)
| Endpoint | Description |
|---|---|
GET /customers | Customer accounts |
GET /customers/{id}/statement | Customer statement and balance |
GET /accounting/receipts | Collection receipts |
GET /accounting/invoices | Branch sales invoices |
GET /salesmen | Sales representative assignments |
Error codes
Error response: { code, message, details[], requestId }. code is stable; message is an English description.
{
"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 status codes
UNAUTHORIZED (401) | Key invalid or missing |
FORBIDDEN_SCOPE (403) | Insufficient scope |
SELLER_KEY_REQUIRED (403) | The service needs a seller key; a corporate key was used |
CORPORATE_KEY_REQUIRED (403) | The service needs a corporate key; a seller key was used |
SANDBOX_READ_ONLY (403) | A sandbox key cannot modify orders, returns or invoices; catalog requests are only validated |
IP_NOT_ALLOWED (403) | IP not in the allowlist |
VALIDATION_FAILED (422) | Invalid body schema |
PAYLOAD_TOO_LARGE (413) | Record limit exceeded |
QUEUE_BUSY (429) | Pending batch limit exceeded; see the Retry-After header |
RATE_LIMITED (429) | Request rate exceeded |
NOT_FOUND (404) | Record not found |
STORAGE_UNAVAILABLE (503) | Storage temporarily unavailable |
Record codes (batch error report)
SOURCEID_REQUIRED | sourceId is empty |
NAME_REQUIRED | Name missing for an active product |
PRICE_NEGATIVE, STOCK_NEGATIVE | Negative or non-numeric value |
CURRENCY_INVALID | Currency is not TRY, USD or EUR |
STATUS_INVALID | status is not 0 or 1 |
UNKNOWN_SOURCEID | Product not defined |
INVALID_JSON | Line is not valid JSON |
OEM_TOO_SHORT (warning) | Number shorter than three characters skipped |
WAREHOUSE_STOCK_MISMATCH (warning) | Warehouse total used |
DUPLICATE_SOURCEID (warning) | Last record used |
Limits
- Products: 1,000 records per request. Stock and prices: 5,000 records per request. Body: 6 MB.
- Request rate: 600 requests per minute per key. 429 when exceeded.
- Pending batches: 10 per seller. 429 when exceeded.
- File: no record limit, up to 2 GB (gzip).
- The upload URL is valid for 15 minutes.
Request log
GET /v1/logs/requests returns the requests of the last 30 days: endpoint, status, duration, requestId, batchId.
Reference
- Swagger UI
- OpenAPI 3 schema (JSON)
- Postman collection (all endpoints, sample bodies)
- Support: support@bicops.tr. Include requestId and batchId.