Catalogue
Categories and field sets, product upload, price and stock, sale status, incremental sync and batch results.
The endpoints on this page exist only for Çarşı businesses (vertical: store); calling them with a restaurant key returns 404 not_available_for_vertical. Bulk writes (product creation, price and stock, sale status) return 202 and a batchId; the outcome is read with GET /batches/{id}. The response itself is not the result.
Each row links to the full definition in the API reference — fields, response codes and the try-it console.
1. Fetch the categories first
/categoriesThis endpoint answers two questions at once: which category a product may attach to, and which fields that category requires. The tree is the platform catalogue and does not vary by business. The list is not paged; nextCursor is always null.
{
"items": [
{
"id": "cm_ornek_kategori", "name": "Örnek Kategori", "parentId": "cm_ornek_ust", "level": 3,
"leaf": true, // products attach only to leaves
"attributes": [
{ "id": "garanti_suresi", "required": true, "type": "sayisal", "unit": "ay",
"min": 24, "max": null, "values": null, "variantAxis": false,
"allowCustomValue": false, "inheritedFrom": "cm_ornek_ust" }
]
}
],
"nextCursor": null
}inheritedFrom gives the identifier of the source category when inherited, and is null when the category declares the attribute itself. attributes is filled only on leaf categories.2. Upload the products
/productsThis endpoint creates; it does not update. A product already registered in the business returns already_exists on that item; use PUT /products/price-and-stock for price and stock and PUT /products/status for sale status. Item fields are validated one by one on the server; an error on one item does not stop the others.
| Alan | Tip | Açıklama |
|---|---|---|
namezorunlu | string | Product name. |
pricezorunlu | number | A number greater than zero. Strings are rejected. |
taxRatezorunlu | 1 | 10 | 20 | VAT rate. The business determines the rate of its product; a missing rate is rejected with tax_rate_required. |
barcode | string | 8–14 digits (spaces and hyphens are removed). Never put a model code here. Required if sku is absent. |
sku | string | A permanent stock code specific to the seller; used for products without a barcode. Required if barcode is absent. |
clientReferenceId | string | The product identifier in the source system: at most 64 characters; letters, digits, _ and -. It must be unique within the business (duplicate_reference). You match order lines with it. |
stock | integer | If sent, stock tracking is turned on; if omitted, the product is treated as always available. |
categoryId | string | A category with leaf: true in the GET /categories response (invalid_category). |
attributes | object | The category's required attributes. If a required attribute is missing the product is saved but not put on sale (missing_attribute). Attribute values are not stored through this endpoint; only the absence is checked. |
brand · unit · weight · description | string | Optional product information. |
image | string | Not accepted. The product image is uploaded from the business console. If an image with an external address is sent, the item is written and an image_ignored warning is returned (message in Turkish: Görsel adresi kabul edilmedi; ürün görseli işletme panelinden yüklenir.). |
curl -X POST "https://api.supergelsin.com/api/partner/v1/products" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01" \
-H "Idempotency-Key: ornek-gonderim-0001" \
-H "Content-Type: application/json" \
-d '{"items":[
{"clientReferenceId":"POS-1042",
"barcode":"8690000000017",
"name":"Örnek Süt 1 L",
"price":42.5,
"stock":18,
"taxRate":1,
"categoryId":"cm_ornek_kategori"}
]}'{ "batchId": "cm_ornek_is", "status": "QUEUED", "totalItems": 1,
"expiresAt": "2026-02-07T10:00:00.000Z" }batchId of the first job is returned with 200 and idempotent: true. The same key with another operation or a different body returns 422 idempotency_key_reuse. A key longer than 128 characters is not rejected; the value is cut to its first 128 characters and leading and trailing spaces are removed: two keys with the same first 128 characters count as the same key. A job that became FAILED because of a system fault is resent with a new key; the same key returns the same FAILED job for 24 hours.barcode or sku. With neither, the item is rejected with missing_identity: a product without a permanent identity would be recreated on every submission. clientReferenceId does not fill this gap.3. Read the result
/batches/{id}{
"batchId": "cm_ornek_is", "status": "COMPLETED_WITH_ERRORS", "operation": "product_create",
"createdAt": "2026-01-31T10:00:00.000Z", "startedAt": "2026-01-31T10:00:02.000Z",
"finishedAt": "2026-01-31T10:00:09.000Z", "expiresAt": "2026-02-07T10:00:00.000Z",
"summary": { "totalItems": 6, "successCount": 4, "errorCount": 1, "pendingCount": 1 },
"errors": [
{ "clientReferenceId": "POS-1042", "barcode": "8690000000017", "errorCode": "already_exists",
"message": "..." }
],
"pending": [
{ "clientReferenceId": "POS-77", "barcode": null, "pendingReason": "missing_attribute", "message": "..." }
],
"warnings": [
{ "clientReferenceId": "POS-88", "barcode": null, "code": "image_ignored", "message": "..." }
]
}| Alan | Tip | Açıklama |
|---|---|---|
status | enum | QUEUED, PROCESSING, COMPLETED, COMPLETED_WITH_ERRORS, FAILED. If you see COMPLETED_WITH_ERRORS, read the errors[] array. FAILED: no item was processed (failureReason gives the cause). |
operation | enum | product_create · price_stock · product_status |
errors[] | array | Failed items (errorCode, message). Only problem items are stored; successful items are not listed. |
pending[] | array | Not an error: items saved but not put on sale. pendingReason gives the cause: new_master_review (new product record under review), missing_attribute (a required attribute is missing), restricted_product (under review on suspicion of a restricted product). The fix is not to resend the same product. |
warnings[] | array | Successful but flagged items (for example image_ignored). They are not added to the counters; a flagged successful item is already in successCount. |
Matching uses clientReferenceId (and barcode if present), never the array order. Results are kept for 7 days (expiresAt); after that 404 not_found is returned. A job of another business or another key also returns 404. All error and warning codes are on the Error codes page.
4. Day-to-day: price and stock
/products/price-and-stock{ "items": [
{ "barcode": "8690000000017", "price": 44.9, "stock": 12 },
{ "sku": "ORNEK-DOMATES", "stock": 0 } // the product becomes sold out
] }- An item is matched by
barcode,skuorclientReferenceId(at least one is needed; if several are sent they must all point to the same product). At least one ofpriceandstockis needed. - When stock is
0the product becomes sold out with the reasonout_of_stock. A stock increase does not reopen a product the business closed by hand. An item that sends stock turns stock tracking on. The change is reflected in search. - In the same business, later price, stock and status jobs wait until a product-creation job opened earlier has finished.
not_found; use POST /products for a new product. An identifier that matches several products, or identifiers that contradict each other, return ambiguous_identity. An item with neither price nor stock is rejected with empty_update.5. Taking a product off sale requires a reason code
/products/status{ "items": [
{ "barcode": "8690000000017", "onSale": false, "reason": "seasonal" },
{ "sku": "ORNEK-DOMATES", "onSale": true }
] }It also works on a product with stock tracking off. A closed product shows as closed on the storefront, in orders and in search. reason is required for onSale: false; the reason is cleared when reopening.
| Alan | Tip | Açıklama |
|---|---|---|
merchant_out_of_stock | enum | The business has run out. |
seasonal | enum | Seasonal product. |
supplier | enum | Supply problem. |
price | enum | Awaiting a price update. |
discontinued | enum | The product is discontinued. |
6. Incremental sync
/productscurl "https://api.supergelsin.com/api/partner/v1/products?updatedSince=2026-01-31T00:00:00Z&limit=200" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01"
# response -> { "items": [...], "nextCursor": "MTc4..." }
curl "https://api.supergelsin.com/api/partner/v1/products?cursor=MTc4...&limit=200" \
-H "Authorization: Basic $(printf '%s:%s' "$API_KEY" "$API_SECRET" | base64)" \
-H "X-Integrator: Ornek POS" \
-H "X-Operator: kasiyer_01"| Alan | Tip | Açıklama |
|---|---|---|
limit | integer | Page size, 1–500; default 100. |
updatedSince | ISO 8601 | Time zone required. Returns products changed at or after this moment (the boundary is included). |
cursor | string | The nextCursor from the previous response. If nextCursor is null, the end of the stream has been reached. |
Ordering is by updatedAt ascending, then id ascending. The cursor advances over this pair, so no record is skipped between pages. A broken cursor is not an error; it restarts the stream. An archived product does not drop out of the stream; it stays with status: ARCHIVED. If stock tracking is off, stock is null; it must not be confused with 0.
| Alan | Tip | Açıklama |
|---|---|---|
status | enum | Priority order: ARCHIVED, REJECTED, PENDING_REVIEW, then OFF_SALE for inactive or not-on-sale products, otherwise ACTIVE. PENDING_REVIEW and REJECTED products are fixed in the business console. |
onSale | boolean | Whether it is on sale to customers right now. |
offSaleReason | string | null | The off-sale reason (for example out_of_stock, merchant_out_of_stock, seasonal, supplier, price, discontinued, moderation). |
trackStock | boolean | Whether stock tracking is on. |