Download OpenAPI specification:Download
Product feed and dropshipping orders for Kot w Butach partners.
DRAFT - subject to change before v1.0.0 is released.
KOT API lets dropshipping partners:
GET /products - import products into your shop (refresh at most every 15 minutes).package from the feed.POST /orders with the recipient, items and the label (or send the label later with PUT /orders/{order_id}/label).GET /orders?updated_since=... (or receive webhooks, planned) until the status is shipped.Every request needs an API key in the Authorization header:
Authorization: Bearer kot_live_xxxxxxxxxxxxxxxxxxxxxxxx
kot_live_... keys work on real orders.kot_test_... keys (sandbox) use the same URL and the same validation, but orders are never processed
or packed. Sandbox orders move through statuses automatically so you can test your integration.?feed_token=...) for tools that cannot send headers. A feed token cannot place orders.Keys are issued by Kot w Butach. Keep them secret; ask us to rotate a key if it leaks.
sku is our stable product code: uppercase letters A-Z, digits and hyphens only (e.g. KWB-CAT-GRASS),
safe to use in URLs and CSV files as is. A SKU never changes once published in the feed.
Some products come in variants (e.g. fabric patterns of a cat lounger). Every variant has its own
sku (e.g. KWB-LOUNGER-STASIU-V12) - order the variant SKU. The product SKU of such a product
(KWB-LOUNGER-STASIU) groups its variants and cannot be ordered itself (variant_required).
external_id (your order number) is unique per partner. Sending the same order again returns the
existing order (200) instead of creating a duplicate. Sending a different payload with an
external_id that already exists returns 409 duplicate_external_id.
| Status | Meaning |
|---|---|
received |
Accepted by the API, being processed (usually seconds to minutes). |
confirmed |
Stock reserved, warehouse document created. Parcel will be packed once a label is present. |
shipped |
Packed with your label and ready for carrier pickup. Final status. |
rejected |
Order could not be processed - see rejection.code. Final status. |
cancelled |
Cancelled by you before packing. Final status. |
received -> confirmed -> shipped; received -> rejected; received | confirmed -> cancelled.
Orders received with a label by 13:00 Polish time (Europe/Warsaw) on a business day are packed the same day. Later orders, and orders whose label arrives after 13:00, are packed on the next business day. Business days = Monday to Friday, except public holidays in Poland.
You book the carrier pickup for every parcel on your carrier account, once the order status is shipped
(packed and ready). The pickup address is returned by GET /me (pickup_address).
Any country. You buy the courier label on your own carrier account, so the destination and the shipping cost are yours to decide.
package from the feed (the parcel of one unit), not dimensions (the product itself). Some products
ship flat-packed in a box smaller than the assembled product. For orders with more than one item, sum the
weights and contact us for combined packing rules.confirmed and is not packed until the label arrives.Address fields are stored in our ERP with fixed lengths (see schemas). Values that are too long
are rejected with 422 validation_error (we never cut your customer's address silently).
60 requests per minute per API key. Above the limit the API returns 429 with a Retry-After header.
Every response carries X-Request-Id - quote it when contacting us.
Amounts are decimal strings with two decimal places ("10.08"), prices are net (VAT not included)
in the currency agreed with you (price.currency).
The version is part of the URL (/v1). New optional fields may be added to responses at any time -
ignore unknown fields. Breaking changes only in a new version (/v2).
Returns the partner and key type. Use it to test your connection.
{- "partner_id": 3,
- "partner_name": "Example Pets GmbH",
- "mode": "test",
- "currency": "EUR",
- "pickup_address": {
- "company": "Kot w Butach sp. z o.o. - Magazyn",
- "address1": "ul. Kolberga 9 lok. H2",
- "postcode": "25-620",
- "city": "Kielce",
- "country": "PL",
- "phone": "+48662353662"
}
}All products available to your account. The catalogue is small, so the whole feed is returned
in one response. Use updated_since to fetch only changed products.
| updated_since | string <date-time> Only items changed at or after this moment (ISO 8601, e.g. |
{- "generated_at": "2026-11-02T08:00:00Z",
- "data": [
- {
- "sku": "KWB-CAT-GRASS",
- "ean": "5900000000001",
- "name": "Organic Cat Grass",
- "description": null,
- "price": {
- "net": "3.00",
- "currency": "EUR"
}, - "availability": {
- "status": "in_stock",
- "quantity": null
}, - "dimensions": {
- "weight_g": 1150,
- "length_cm": 18,
- "width_cm": 18,
- "height_cm": 18
}, - "package": {
- "weight_g": 1150,
- "length_cm": 18,
- "width_cm": 18,
- "height_cm": 18
}, - "country_of_origin": "PL",
- "cn_code": "06029070",
- "variants": [ ],
- "updated_at": "2026-10-30T14:12:00Z"
}, - {
- "sku": "KWB-LOUNGER-STASIU",
- "ean": null,
- "name": "Cat Lounger \"Stasiu\"",
- "description": null,
- "price": {
- "net": "20.00",
- "currency": "EUR"
}, - "availability": {
- "status": "low_stock",
- "quantity": null
}, - "dimensions": {
- "weight_g": 1800,
- "length_cm": 60,
- "width_cm": 40,
- "height_cm": 15
}, - "package": {
- "weight_g": 2100,
- "length_cm": 45,
- "width_cm": 35,
- "height_cm": 10
}, - "country_of_origin": "PL",
- "cn_code": null,
- "variants": [
- {
- "sku": "KWB-LOUNGER-STASIU-V12",
- "name": "Eko Len 01",
- "availability": {
- "status": "in_stock",
- "quantity": null
}
}
], - "updated_at": "2026-10-28T09:00:00Z"
}
]
}The same feed as CSV (UTF-8, comma separated, header row). One row per orderable item -
products with variants have one row per variant (variant sku, product SKU in parent_sku). Columns:
sku, parent_sku, variant_name, ean, name, description, price_net, currency, availability, quantity, weight_g, length_cm, width_cm, height_cm, package_weight_g, package_length_cm, package_width_cm, package_height_cm, country_of_origin, cn_code, image_1, image_2, image_3, updated_at. availability = in_stock / low_stock /
out_of_stock / discontinued; quantity is always empty (exact quantities are not reported).
| updated_since | string <date-time> Only items changed at or after this moment (ISO 8601, e.g. |
{- "error": {
- "code": "string",
- "message": "string",
- "request_id": "string",
- "details": [
- {
- "field": "recipient.address1",
- "message": "Maximum 40 characters."
}
]
}
}The same feed as XML (UTF-8). One <product> element per orderable item, with child elements named
like the CSV columns (<sku>, <parent_sku>, ..., <updated_at>); empty values are empty elements.
<?xml version="1.0" encoding="UTF-8"?>
<products generated_at="2026-11-02T08:00:00Z">
<product>
<sku>KWB-CAT-GRASS</sku>
<parent_sku/>
<name>Organic Cat Grass</name>
<price_net>3.00</price_net>
<currency>EUR</currency>
...
</product>
</products>
| updated_since | string <date-time> Only items changed at or after this moment (ISO 8601, e.g. |
{- "error": {
- "code": "string",
- "message": "string",
- "request_id": "string",
- "details": [
- {
- "field": "recipient.address1",
- "message": "Maximum 40 characters."
}
]
}
}| sku required | string Product SKU or variant SKU (a variant SKU returns its product with all variants). |
{- "sku": "string",
- "ean": "string",
- "name": "string",
- "description": "string",
- "price": {
- "net": "string",
- "currency": "EUR"
}, - "availability": {
- "status": "in_stock",
- "quantity": null
}, - "dimensions": {
- "weight_g": 0,
- "length_cm": 0,
- "width_cm": 0,
- "height_cm": 0
}, - "package": {
- "weight_g": 0,
- "length_cm": 0,
- "width_cm": 0,
- "height_cm": 0
}, - "country_of_origin": "string",
- "cn_code": "string",
- "variants": [
- {
- "sku": "string",
- "name": "string",
- "availability": {
- "status": "in_stock",
- "quantity": null
}
}
], - "updated_at": "2019-08-24T14:15:22Z"
}Creates a dropshipping order. The response is returned right after validation with status received;
stock reservation happens asynchronously (poll the order or wait for the webhook).
| external_id required | string <= 64 characters Your unique order id (e.g. Shopify order id). Idempotency key. |
| reference | string or null <= 64 characters Human readable order number (e.g. Shopify |
required | object (Recipient) |
required | Array of objects (OrderItemCreate) [ 1 .. 20 ] items |
Shipping (object) or null Courier label. May be omitted and sent later with | |
| note | string or null <= 250 characters Note for our warehouse (not printed for the recipient). |
{- "external_id": "5873219443001",
- "reference": "#1042",
- "recipient": {
- "name": "Anna Schmidt",
- "company": null,
- "address1": "Hauptstrasse 12",
- "address2": "Apt. 4",
- "postcode": "10115",
- "city": "Berlin",
- "country": "DE",
- "phone": "+4915112345678",
- "email": "anna.schmidt@example.com"
}, - "items": [
- {
- "sku": "KWB-CAT-GRASS",
- "quantity": 1
}, - {
- "sku": "KWB-LOUNGER-STASIU-V12",
- "quantity": 1
}
], - "shipping": {
- "carrier": "DHL",
- "tracking_number": "00340434161234567890",
- "label_pdf_base64": "JVBERi0xLjQKJ..."
}, - "note": null
}{- "id": "ord_8K2M4Q",
- "external_id": "string",
- "reference": "string",
- "status": "received",
- "mode": "live",
- "recipient": {
- "name": "string",
- "company": "string",
- "address1": "string",
- "address2": "string",
- "postcode": "string",
- "city": "string",
- "country": "string",
- "phone": "string",
- "email": "user@example.com"
}, - "items": [
- {
- "sku": "string",
- "variant_name": "string",
- "name": "string",
- "quantity": 0,
- "price": {
- "net": "string",
- "currency": "EUR"
}
}
], - "total": {
- "net": "string",
- "currency": "EUR"
}, - "label_received": true,
- "carrier": "string",
- "tracking_number": "string",
- "tracking_url": "string",
- "rejection": {
- "code": "out_of_stock",
- "message": "string",
- "sku": "string"
}, - "note": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "confirmed_at": "2019-08-24T14:15:22Z",
- "shipped_at": "2019-08-24T14:15:22Z",
- "cancelled_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Your orders, newest change first. For synchronisation poll with updated_since set to the
updated_at of the last order you processed.
| updated_since | string <date-time> Only items changed at or after this moment (ISO 8601, e.g. |
| status | string (OrderStatus) Enum: "received" "confirmed" "shipped" "rejected" "cancelled" |
| external_id | string Find an order by your order number. |
| limit | integer [ 1 .. 100 ] Default: 50 |
| cursor | string Value of |
{- "data": [
- {
- "id": "ord_8K2M4Q",
- "external_id": "string",
- "reference": "string",
- "status": "received",
- "mode": "live",
- "recipient": {
- "name": "string",
- "company": "string",
- "address1": "string",
- "address2": "string",
- "postcode": "string",
- "city": "string",
- "country": "string",
- "phone": "string",
- "email": "user@example.com"
}, - "items": [
- {
- "sku": "string",
- "variant_name": "string",
- "name": "string",
- "quantity": 0,
- "price": {
- "net": "string",
- "currency": "EUR"
}
}
], - "total": {
- "net": "string",
- "currency": "EUR"
}, - "label_received": true,
- "carrier": "string",
- "tracking_number": "string",
- "tracking_url": "string",
- "rejection": {
- "code": "out_of_stock",
- "message": "string",
- "sku": "string"
}, - "note": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "confirmed_at": "2019-08-24T14:15:22Z",
- "shipped_at": "2019-08-24T14:15:22Z",
- "cancelled_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "next_cursor": "string"
}| order_id required | string Example: ord_8K2M4Q Order id returned by |
{- "id": "ord_8K2M4Q",
- "external_id": "5873219443001",
- "reference": "#1042",
- "status": "shipped",
- "mode": "live",
- "recipient": {
- "name": "Anna Schmidt",
- "company": null,
- "address1": "Hauptstrasse 12",
- "address2": "Apt. 4",
- "postcode": "10115",
- "city": "Berlin",
- "country": "DE",
- "phone": "+4915112345678",
- "email": "anna.schmidt@example.com"
}, - "items": [
- {
- "sku": "KWB-CAT-GRASS",
- "variant_name": null,
- "name": "Organic Cat Grass",
- "quantity": 1,
- "price": {
- "net": "3.00",
- "currency": "EUR"
}
}, - {
- "sku": "KWB-LOUNGER-STASIU-V12",
- "variant_name": "Eko Len 01",
- "name": "Cat Lounger \"Stasiu\"",
- "quantity": 1,
- "price": {
- "net": "20.00",
- "currency": "EUR"
}
}
], - "total": {
- "net": "23.00",
- "currency": "EUR"
}, - "label_received": true,
- "carrier": "DHL",
- "tracking_number": "00340434161234567890",
- "rejection": null,
- "note": null,
- "created_at": "2026-11-02T09:15:00Z",
- "confirmed_at": "2026-11-02T09:16:10Z",
- "shipped_at": "2026-11-02T11:40:00Z",
- "cancelled_at": null,
- "updated_at": "2026-11-02T11:40:00Z"
}Allowed while the order is received or confirmed. After shipped returns 409 order_locked.
| order_id required | string Example: ord_8K2M4Q Order id returned by |
| carrier required | string <= 30 characters Carrier name as printed on the label, e.g. |
| tracking_number required | string <= 64 characters |
| tracking_url | string or null <uri> <= 500 characters |
| label_pdf_base64 required | string <base64> <application/pdf> One-page PDF, 100 x 150 mm, max 2 MB before encoding. |
{- "carrier": "string",
- "tracking_number": "string",
- "label_pdf_base64": "string"
}{- "id": "ord_8K2M4Q",
- "external_id": "string",
- "reference": "string",
- "status": "received",
- "mode": "live",
- "recipient": {
- "name": "string",
- "company": "string",
- "address1": "string",
- "address2": "string",
- "postcode": "string",
- "city": "string",
- "country": "string",
- "phone": "string",
- "email": "user@example.com"
}, - "items": [
- {
- "sku": "string",
- "variant_name": "string",
- "name": "string",
- "quantity": 0,
- "price": {
- "net": "string",
- "currency": "EUR"
}
}
], - "total": {
- "net": "string",
- "currency": "EUR"
}, - "label_received": true,
- "carrier": "string",
- "tracking_number": "string",
- "tracking_url": "string",
- "rejection": {
- "code": "out_of_stock",
- "message": "string",
- "sku": "string"
}, - "note": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "confirmed_at": "2019-08-24T14:15:22Z",
- "shipped_at": "2019-08-24T14:15:22Z",
- "cancelled_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Allowed while the order is received or confirmed. After shipped returns 409 order_locked.
| order_id required | string Example: ord_8K2M4Q Order id returned by |
| reason | string <= 250 characters |
{- "reason": "string"
}{- "id": "ord_8K2M4Q",
- "external_id": "string",
- "reference": "string",
- "status": "received",
- "mode": "live",
- "recipient": {
- "name": "string",
- "company": "string",
- "address1": "string",
- "address2": "string",
- "postcode": "string",
- "city": "string",
- "country": "string",
- "phone": "string",
- "email": "user@example.com"
}, - "items": [
- {
- "sku": "string",
- "variant_name": "string",
- "name": "string",
- "quantity": 0,
- "price": {
- "net": "string",
- "currency": "EUR"
}
}
], - "total": {
- "net": "string",
- "currency": "EUR"
}, - "label_received": true,
- "carrier": "string",
- "tracking_number": "string",
- "tracking_url": "string",
- "rejection": {
- "code": "out_of_stock",
- "message": "string",
- "sku": "string"
}, - "note": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "confirmed_at": "2019-08-24T14:15:22Z",
- "shipped_at": "2019-08-24T14:15:22Z",
- "cancelled_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Sent to the URL registered for your account whenever an order changes status.
Body = the full order. Signature: header X-Kot-Signature: sha256=<hex> =
HMAC-SHA256 of the raw body with your webhook secret. Respond 2xx within 10 s;
failed deliveries are retried with backoff for 24 h. Polling GET /orders always works as a fallback.
| id required | string |
| external_id required | string |
| reference | string or null |
| status required | string (OrderStatus) Enum: "received" "confirmed" "shipped" "rejected" "cancelled" |
| mode required | string Enum: "live" "test" |
required | object (Recipient) |
required | Array of objects (OrderItem) |
required | object (Money) |
| label_received required | boolean
|
| carrier | string or null |
| tracking_number | string or null |
| tracking_url | string or null |
Rejection (object) or null | |
| note | string or null |
| created_at required | string <date-time> |
| confirmed_at | string or null <date-time> |
| shipped_at | string or null <date-time> When the parcel was packed with your label. |
| cancelled_at | string or null <date-time> |
| updated_at required | string <date-time> |
{- "id": "ord_8K2M4Q",
- "external_id": "string",
- "reference": "string",
- "status": "received",
- "mode": "live",
- "recipient": {
- "name": "string",
- "company": "string",
- "address1": "string",
- "address2": "string",
- "postcode": "string",
- "city": "string",
- "country": "string",
- "phone": "string",
- "email": "user@example.com"
}, - "items": [
- {
- "sku": "string",
- "variant_name": "string",
- "name": "string",
- "quantity": 0,
- "price": {
- "net": "string",
- "currency": "EUR"
}
}
], - "total": {
- "net": "string",
- "currency": "EUR"
}, - "label_received": true,
- "carrier": "string",
- "tracking_number": "string",
- "tracking_url": "string",
- "rejection": {
- "code": "out_of_stock",
- "message": "string",
- "sku": "string"
}, - "note": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "confirmed_at": "2019-08-24T14:15:22Z",
- "shipped_at": "2019-08-24T14:15:22Z",
- "cancelled_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}