LockStock docs

Push API

Send catalog changes from your server — products, price and stock, categories, pickup points, full reconciliation.

Experimental

The push API works end to end, but keys are issued by your LockStock contact until the dashboard opens, and details may change before the general release.

Use it instead of, or together with, a YML feed when you want changes to reach search within seconds — typically price and stock.

Ready-to-copy clients for Node.js and PHP with batching, safe retries and job polling: Push API examples.

Basics

  • Base URL: https://api.lockstock.example (your exact host is shown in the dashboard).
  • Auth: Authorization: Bearer sk_… — your secret key. Server to server only; never put it in a page.
  • Idempotency: every request except POST /sync-sessions carries an Idempotency-Key header, unique per change. Repeating a request with the same key and the same body replays the first answer (header Idempotent-Replayed: true); the same key with a different body is 422. A repeat that arrives while the first is still running gets 409 — retry it. Keys live 24 hours.
  • Asynchronous: writes answer 202 { "jobId": "…" }; check the result with GET /v1/catalog/jobs/{jobId} within minutes.
  • Limits: request body up to 20 MB; batch sizes are in the table below.
  • Money in major units, at most 2 decimals, in your store's currency.

Endpoints

RequestBodyLimitWhat it does
PUT /v1/catalog/categories{ "categories": [...] }10,000Upsert the category tree
PUT /v1/catalog/outlets{ "outlets": [...] }1,000Upsert pickup points
PUT /v1/catalog/products{ "products": [...] }1,000Upsert products
PATCH /v1/catalog/offers{ "offers": [...] }5,000Price, old price, availability and stock only — the fast path
DELETE /v1/catalog/products/{externalId}——Remove a product from sale
POST /v1/catalog/sync-sessions——Start a full reconciliation
PUT /v1/catalog/sync-sessions/{id}/products{ "products": [...] }1,000Add a batch to the session
POST /v1/catalog/sync-sessions/{id}/commit——Apply the session
GET /v1/catalog/jobs/{jobId}——Job status
Update price and stock
curl -X PATCH https://api.lockstock.example/v1/catalog/offers \
  -H "Authorization: Bearer sk_live_…" \
  -H "Idempotency-Key: 6f1c2a04-price-2026-10-05T14:05" \
  -H "Content-Type: application/json" \
  -d '{"offers":[{"id":"1204581","price":47990,"oldPrice":56990,"available":true,
       "stock":[{"outletId":"derbent-1","qty":2}],"updatedAt":"2026-10-05T14:05:00Z"}]}'

Product

FieldTypeNotes
idstring, requiredYour product ID (externalId)
groupIdstringVariants of one product share it
namestring, requiredUp to 1,000 characters
descriptionstringUp to 50,000 characters; HTML is stripped
urlstring, requiredAbsolute http(s) link to the product page
imagesstring[]Up to 20 absolute http(s) links
categoryIdstringA category you sent
vendor, modelstringBrand and model
pricenumber, requiredMajor units
oldPricenumberThe price before a discount
currencystring, requiredISO 4217, must be your store's currency
availablebooleanDefault true
params{ name, value, unit? }[]Up to 200 specs
stock{ outletId, qty }[]Stock per pickup point
updatedAtISO 8601, requiredWhen the product changed in your system

Order of updates. An update older than what we already have (by updatedAt) is skipped, so retries and out-of-order deliveries never overwrite fresher data.

Whole products. PUT /products and a full reconciliation replace a product as a whole: a field you leave out, such as oldPrice, is cleared. To change only price, old price, availability or stock, use PATCH /offers: fields you leave out there keep their values.

PATCH /offers items take id, updatedAt and any of price, oldPrice, available, stock. Categories take id, parentId, name. Pickup points take id, name and optional city, address, hours, lat, lon.

Jobs

GET /v1/catalog/jobs/{jobId} answers { jobId, status, stats, errors, error }, where status is queued, running, succeeded, rejected or failed.

Errors come in two layers. A malformed request — wrong types, a missing field, a batch over the limit — is a 400 for the whole request. Problems with single items — another currency, more than 2 decimals, an unknown product in PATCH /offers or DELETE — do not fail the batch: they are listed in errors as { id, reason } and counted in stats.

Job history keeps the last 1,000 finished jobs: poll within minutes, not days.

Full reconciliation

When you want our catalog to match yours exactly — including removals — send a snapshot:

  1. POST /v1/catalog/sync-sessions → { sessionId, expiresAt }. A session lives 6 hours.
  2. PUT /v1/catalog/sync-sessions/{sessionId}/products with every product, in batches of up to 1,000.
  3. POST /v1/catalog/sync-sessions/{sessionId}/commit. Products not in the snapshot are removed from search.

The 30% safeguard applies: a commit that would remove more than 30% of your active products ends rejected. A session can be committed once; a second commit or a batch after it is 409.

Knowledge documents

The consultant answers questions about delivery, payment, returns, warranty and store addresses only from your own pages. Push them as Markdown with the same secret key:

PUT /v1/knowledge/documents/delivery
Authorization: Bearer sk_live_…
Content-Type: application/json

{
  "title": "Доставка",
  "content": "# Доставка\n\n## Курьером по городу\n\nМахачкала: 300 ₽, при заказе от 5 000 ₽ — бесплатно.",
  "sourceUrl": "https://shop.ru/delivery"
}

Unlike catalog writes this call is synchronous: it answers 200 { "slug", "title", "status": "published", "chunks", "updatedAt" } once the document is indexed and the consultant can quote it. A second PUT with the same slug replaces the document; DELETE /v1/knowledge/documents/{slug} removes it (204). Limits: slug is lowercase latin letters, digits and dashes (up to 100 characters), title up to 200 characters, content not empty and up to 200 000 characters. If indexing fails (503), the text is saved and a retry runs in the background; sending the same document again indexes it at once. Headings matter: every passage the consultant retrieves carries its heading path, so «## Курьером по городу» under «# Доставка» stays understandable on its own. sourceUrl lets the consultant point the shopper to the page. Pages can also be imported from their URL in the dashboard under Knowledge base.

On this page