Partner API guide

Catalog with your prices and stock and, if enabled, orders. Full field and response reference: the openapi.yaml specification file (OpenAPI 3.0; opens in Swagger Editor, Postman, Insomnia), attached to this guide. Error message texts are in Russian; rely on code.

1. Quick start

  1. Open the bot's mini app → Profile → API and create a token: name, expiry, access ("catalog only" or "catalog and orders"), and a channel when offered (warehouse + currency, same as bot directions). The section is visible only if a manager has enabled API access for you.
  2. A general token covers every channel the manager allowed. A narrow token is limited to one channel: catalog and orders use only that warehouse and currency.
  3. The token is shown once. Keep it in a secrets store; never put it in a repository or client-side code. If it leaks, revoke it there and issue a new one.
  4. Send the token with every request: Authorization: Bearer fcp_….
export FC_API="https://api.unimtrn.com/api/partner"
curl -H "Authorization: Bearer $FC_TOKEN" "$FC_API/schedule"

API base URL: https://api.unimtrn.com/api/partner. The API is server-to-server: browser requests (CORS) are not supported, call it from your backend.

2. General rules

  • Price is what you see in the bot (price type, markup, currency from your client card). You never send a price: the server sets it, including quantity tiers.
  • Warehouses and currency come from the token's channels (client card ∩ manager policy ∩ issue choice). With a single warehouse you may omit warehouse. A narrow single-currency token returns prices only in that currency.
  • Working hours. The bot has a schedule: it accepts orders only during working hours. You can get today's hours with GET /schedule (it always answers, including when the bot is closed); your manager will also tell you the hours.
    • Order changes (add an item, change quantity, remove a line, cancel the order) are not accepted outside working hours: the response is 423 bot_closed. This always applies.
    • The catalog (/catalog, /brands, /categories) is closed outside working hours only if your manager has enabled schedule compliance for you; then it also returns 423 bot_closed. If it is not enabled, the catalog is available around the clock.
    • 423 bot_closed is not a request error. Retry it during working hours; use the same Idempotency-Key on the retry: a schedule rejection is not stored, and the action will be executed afresh.
    • When today's working time is known, it comes right in the response, in error.details: the opening and closing times and the time zone they are given in. If it is only known that the bot is not accepting requests right now, the response has no details field. Example:
      HTTP 423
      {
        "error": {
          "code": "bot_closed",
          "message": "Бот закрыт. Сегодня работает с 10:00 до 18:00 (Asia/Dubai)",
          "details": { "opensAt": "10:00", "closesAt": "18:00", "timezone": "Asia/Dubai" }
        }
      }
  • Rate limits are set by your manager. Exceeding them returns 429 rate_limited: wait and retry. Many invalid tokens in a row from one IP also lead to 429.
  • There is no version in the path. Incompatible changes are shipped as new fields and endpoints: ignore unknown response fields.

3. Error format

HTTP 403
{ "error": { "code": "scope_missing", "message": "…" } }

Rely on code, not the message text. Main groups:

HTTPCodesWhat to do
400bad_request, idempotency_key_required, idempotency_key_invalidFix the request
401token_missing, token_invalid, token_revoked, token_expiredCheck or reissue the token
403api_disabled, client_not_allowed, scope_missing, orders_disabled, forbidden, ip_not_allowedAction unavailable: contact your manager
404not_foundNo such item or order
409request_in_progress, order_closed, line_changed, last_line_use_cancelSee "Orders"
422order_rejected, onec_error, qty_limit_exceeded, qty_increase_unavailable, serial_line_qty_fixed, idempotency_key_reusedRequest understood but not accepted; reason in message
423bot_closedBot is closed by schedule; retry during working hours
429rate_limitedSlow down and retry
503order_busy, onec_unavailableTemporary failure; retry with the same Idempotency-Key

4. Catalog

RequestReturns
GET /scheduleWhether the bot is open now and today's working hours
GET /brandsBrands in stock
GET /categories?brand=…Categories of a brand
GET /catalogItems with prices. Filters: brand, category, warehouse; paging: limit (up to 1000, default 200) and cursor
GET /catalog/{itemCode}One item, including the quantity price tiers (tiers)

Storefront data refreshes every 30–60 seconds; polling more often is pointless. In the examples on the right the base URL is already filled in; send the token in the Authorization header.

Filters and paging are listed under Query params on «Item list». Pass names with spaces via --data-urlencode.

GET https://api.unimtrn.com/api/partner/schedule

Today's working hours

Always answers, including when the bot is closed. Only a valid token is required.

FieldMeaning
opentrue if the bot is accepting requests now
timezoneTime zone for the working hours
today.opensAt, today.closesAtToday's open and close times as HH:MM
todaynull if there are no hours today (day off) or they are unset. Then rely on open.

Hours for other days are not returned by this request.

GET https://api.unimtrn.com/api/partner/brands

Brands

Brands available to you on the storefront.

GET https://api.unimtrn.com/api/partner/categories

Brand categories

Without brand — 400 bad_request.

Query params

ParamRequiredTypeDescription
brandyesstringBrand from the brands list. Case-insensitive
GET https://api.unimtrn.com/api/partner/catalog

Item list

List items carry a single price; tiers only on the item card. Non-null nextCursor means another page. The cursor is opaque.

Query params

ParamRequiredTypeDescription
brandnostringFilter by brand (one value, case-insensitive)
categorynostringFilter by category (one value). Multiple categories — separate requests
warehousenostringWarehouse code; default is all your warehouses
limitnointegerPage size: 1–1000, default 200
cursornostringnextCursor from the previous response. Opaque string
GET https://api.unimtrn.com/api/partner/catalog/{itemCode}

Item card

Path params

ParamRequiredTypeDescription
itemCodeyesstringItem code

items is an array. tiers reads as: “from qty units the unit price is price”. Steps above available stock are hidden. Markdown items have no tiers. Missing/unavailable item → 404 not_found.

GET https://api.unimtrn.com/api/partner/catalog/{itemCode}

Stock

Stock comes in the available field of GET /catalog and GET /catalog/{itemCode}. There is no separate stock endpoint.

Showing stock is enabled by your manager. If it is not enabled, available is absent; catalog and orders still work.

Stock changes with every order. On add, the server re-checks quantity: if stock was short, the response includes addedQty and capped: true.

Catalog item fields

FieldMeaning
itemCodeItem code (sent when ordering)
name, brand, categoryName, brand, category
warehouseWarehouse code
currency, priceCurrency and your unit price
availableStock. Absent if stock is not shown to you
tiersPrice scale: only on the card and only when enabled
markdown, serial, commentMarkdown: flag, serial, comment
warehouseNameWarehouse name (only if allowed)

5. Orders

Available only if your manager enabled orders and the token was issued with “catalog and orders” access. An order is the same document as the bot / mini-app cart.

RequestAction
POST /orders/linesAdd an item to the order
GET /orders/currentOpen order in the current trading session
GET /orders, GET /orders/{id}History and one order with status
PATCH /orders/{id}/lines/{lineId}Change line quantity
DELETE /orders/{id}/lines/{lineId}Remove a line
POST /orders/{id}/cancelCancel the order

Your manager may disable individual actions (change qty, remove line, cancel) — then the API returns 403 forbidden.

POST https://api.unimtrn.com/api/partner/orders/lines

Add an item

If stock or per-customer limit was short: "capped": true and actual addedQty. If nothing can be added — 422 order_rejected. Same item, serial and price — quantities merge; otherwise a new line. Success is always 200; created means a new order was opened.

Headers

HeaderRequiredDescription
AuthorizationyesBearer <token>
Idempotency-KeyyesUnique action key (8–128 chars A-Za-z0-9_.:-). Retry with the same key
Content-Typeyesapplication/json

Body (JSON)

FieldRequiredTypeDescription
itemCodeyesstringItem code from the catalog
qtyyesintegerQuantity, integer ≥ 1. With serial (markdown) — must be 1
warehouseconditionalstringWarehouse code. Required if several warehouses; otherwise the only one is used
serialconditionalstringSerial number. Required for markdown items

Do not send a price — the server sets it.

GET https://api.unimtrn.com/api/partner/orders/current

Current order

If there is no open order in the current trading session: { "order": null }.

You can change or cancel only the current order while it is open. Otherwise 409 order_closed.

Query params

ParamRequiredTypeDescription
warehousenostringWarehouse code. With a single warehouse you may omit it
GET https://api.unimtrn.com/api/partner/orders

Order list

Response: { "items": [ … ], "nextCursor": "…" | null }.

Query params

ParamRequiredTypeDescription
limitnointegerPage size: 1–100, default 20
cursornostringnextCursor from the previous response

One order

Same object as order on the current order. Foreign or missing → 404.

Path params

ParamRequiredTypeDescription
order_idyesstringOrder id
GET https://api.unimtrn.com/api/partner/orders/{order_id}

Order fields

FieldMeaning
id, numberId; document number (empty until assigned)
statusStatus (e.g. created; cancelled → «Отменён»)
currency, warehouse, totalCurrency, warehouse, total
cancelled, readyToShipCancelled; ready to ship
editable, closedReasonWhether it can be changed; if not — reason
lines[]lineId, itemCode, name, brand, qty, price, sum, currency, serial, addedAt

Line id: lineId

lineId addresses a line in PATCH and DELETE. The server creates it — take it from the response (lines[].lineId).

  • Opaque string: do not parse or invent it.
  • Depends on line content and changes with price. After PATCH, take the new one from the response.
  • Identical lines are not merged; duplicates get a ~2 suffix — send it whole.
  • Stale lineId → 409 line_changed with the current order; retry with a new key.
PATCH https://api.unimtrn.com/api/partner/orders/{order_id}/lines/{line_id}

Change line quantity

Price is recalculated from the scale, so lineId may change. Short stock → "capped": true. Serial lines cannot be changed — 422 serial_line_qty_fixed.

Headers

HeaderRequiredDescription
AuthorizationyesBearer <token>
Idempotency-KeyyesUnique action key (8–128 chars A-Za-z0-9_.:-). Retry with the same key
Content-Typeyesapplication/json

Path params

ParamRequiredTypeDescription
order_idyesstringCurrent order id
line_idyesstringLine id from an API response (do not invent it)

Body (JSON)

FieldRequiredTypeDescription
qtyyesintegerNew line quantity, integer ≥ 1. To remove a line use DELETE
DELETE https://api.unimtrn.com/api/partner/orders/{order_id}/lines/{line_id}

Remove a line

The last line cannot be removed (409 last_line_use_cancel) — cancel the order. No request body.

Headers

HeaderRequiredDescription
AuthorizationyesBearer <token>
Idempotency-KeyyesUnique action key (8–128 chars A-Za-z0-9_.:-). Retry with the same key

Path params

ParamRequiredTypeDescription
order_idyesstringCurrent order id
line_idyesstringLine id from an API response (do not invent it)
POST https://api.unimtrn.com/api/partner/orders/{order_id}/cancel

Cancel the order

Afterwards cancelled: true, editable: false.

Headers

HeaderRequiredDescription
AuthorizationyesBearer <token>
Idempotency-KeyyesUnique action key (8–128 chars A-Za-z0-9_.:-). Retry with the same key

Path params

ParamRequiredTypeDescription
order_idyesstringCurrent order id

No request body.

Order error examples

Stale lineId:

HTTP 409
{
  "error": { "code": "line_changed", "message": "Строка заказа изменилась, перечитайте заказ" },
  "order": { "id": "6ae9aefdd12dd7057d4bf68e", "lines": [ "…" ] }
}

No stock:

HTTP 422
{ "error": { "code": "order_rejected", "message": "Товар недоступен в нужном количестве" } }

Action disabled by manager:

HTTP 403
{ "error": { "code": "forbidden", "message": "Удаление строк заказа через API отключено для этого клиента" } }

Numbers, item codes, prices and ids in examples are illustrative.

6. Shipments

Delivery notes for your orders. Available when orders are enabled for you. The list only includes orders that have a delivery note number (deliveryNumber).

RequestReturns
GET /shipmentsShipment list (paging: limit up to 100, cursor)
GET /shipments/{deliveryNumber}Note by number: JSON (default) or PDF (format=pdf)
GET /orders/{id}/shipmentSame note, by order id

JSON lines include price/sum (your unit price from the order) and serials from the note. Order total is total. Missing/unavailable note → 404 / 422 shipment_unavailable.

GET https://api.unimtrn.com/api/partner/shipments

Shipment list

Only orders that have a delivery note number. Paged via nextCursor.

Query params

ParamRequiredTypeDescription
limitnointegerPage size: 1–100, default 20
cursornostringnextCursor from the previous response
GET https://api.unimtrn.com/api/partner/shipments/{deliveryNumber}

Note by delivery number

Path params

ParamRequiredTypeDescription
deliveryNumberyesstringDelivery note number

JSON by default, with line items and serials.

Query params

ParamRequiredTypeDescription
formatnostringjson (default) or pdf — binary note file

Note by order

Same document by order id. Not shipped yet → 404. Same query params (format).

Path params

ParamRequiredTypeDescription
order_idyesstringOrder id
GET https://api.unimtrn.com/api/partner/orders/{order_id}/shipment

7. Status webhooks

These are outgoing notifications: we POST to your HTTPS URL when an order status changes. This is not a Partner API endpoint — the URL is set in the policy (manager in admin, or you in the mini app → Profile → API if self-issue is allowed).

Notifications cover all of the client's orders (bot, mini app, API), except test and referral ones. The same status for one order is not sent twice.

statusWhen
registeredOrder created / registered
cancelledOrder cancelled
shippedDelivery note number appeared
  • URL must be https.
  • Headers: Content-Type: application/json, User-Agent: FC-Partner-Webhook/1.0, X-FC-Delivery-Id (delivery uuid).
  • If a secret is set (8–256 chars) — also X-FC-Signature: sha256=<hex>: HMAC-SHA256 of the raw body.
  • Respond quickly with 2xx. On network/5xx/429 we retry up to 3 times; other 4xx are not retried.

Notification body

event is always order.status. deliveryNumber is present only for shipped.

Verify the signature (Node.js): HMAC-SHA256 of the raw body with your secret, compare to X-FC-Signature (sha256=…) in constant time.

const crypto = require('crypto');
function ok(secret, rawBody, header) {
  const want = 'sha256=' + crypto
    .createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(want);
  const b = Buffer.from(String(header || ''));
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

8. Idempotency-Key

Why. If the response is lost, a blind retry is unsafe. The key guarantees a retry with the same key returns the first response instead of running the action twice.

Where. All mutating order requests: POST /orders/lines, PATCH, DELETE, POST …/cancel. Without it — 400 idempotency_key_required. Not needed for GET.

Who creates it. Your system, before the request (e.g. UUID v4). New action — new key. Keep the key until you get a response.

KEY=$(uuidgen)
curl -sS -X PATCH "https://api.unimtrn.com/api/partner/orders/$ORDER/lines/$LINE" \
  -H "Authorization: Bearer $FC_TOKEN" \
  -H "Idempotency-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"qty": 5}'
# no response — retry with the same $KEY
# → 200 and Idempotent-Replay: true
  • One key — one action. 8–128 chars: A-Za-z0-9_.:-.
  • Same key with a different request — 422 idempotency_key_reused.
  • While the first request is still running — 409 request_in_progress; wait and retry.
  • Business failures (409, 422) are stored. Temporary ones (423, 429, 503) are not.

9. FAQ

  • 403 api_disabled / orders_disabled. API or orders are not enabled for you by the manager.
  • 422 order_rejected. No stock, quota exhausted, or item unavailable — reason in message.
  • 422 onec_error. The accounting system rejected the change. Contact your manager if it repeats.
  • Token stopped working. Check expiry and revocation in Profile → API; the 401 code says what happened.