Skip to content
P
API for partners
Connecting your application — access, authentication and endpoints
API for partners / API changelog

API changes#

Records behavioural changes that affect integrations.

Current state#

Area State
Version v1
Authentication mandatory application key X-API-Key + optional user JWT with refresh token rotation — see Authentication
Permissions enforced
Warehouse module read-only from outside
Specification covers only the auth endpoints; every operation requires apiKeyAuth

Known limitations#

Things we know about and that may change:

Limitation Note
Parameters in the URL writes included; the body is not read (except sign-in and password actions)
Two response shapes reads without an envelope, writes with one
Errors with status 200 only 400, 401, 403 and 429 are distinguished
Inconsistent error envelope sometimes three keys, sometimes four
The HTTP method is ignored GET on a delete action deletes
Owner collections get-all and get-by are denied to owners
Missing HTTP wrappers the cart, checkout, "my" listings
Silent discarding of write data the only trace is in the server log

Treat this list as the contract

The behaviour described here is what you can build on. If it changes, it appears here.

Contract changes since 1 October 2026#

What changed Impact on a client
notification: the field userId is now receiverUserId filters, sorting and reading responses must use the new name; the old alias does not exist. The value is the notification's receiver, null = shared by all administrators. The database column is unchanged
A new conditional role receiver a new kind of RBAC rule, see Permissions
response (bazaar, comcat): the action get is available to the receiver the advert's owner reads the detail of a reply to their advert; before, administrator only
response: a new field readKey a random secret key for the "Mark as read" link; set by the server, never written from outside. Older replies have it empty
response: a new internal action mark-read-by-key from the site only; no HTTP wrapper
rating: the action save-reply goes through the role receiver the owner of the rated profile replies; before, the role owner handled it
message-thread, message, message-participant: actions on one conversation are for owner and receiver no HTTP wrapper; from outside only the CRUD for an administrator remains
a new resource external-connection (/api/system/external-connection) administrator only; config holds secret keys

config of external-connection holds secret keys

Only an administrator may read and write it. Do not store the response, do not log it and do not pass it on.

Filtering notifications by userId no longer works

If your client filtered notifications by userId, the filter now fails or is dropped. Rename it to receiverUserId.

Contract changes of 2 October 2026 (afternoon and evening)#

What changed Impact on a client
response (bazaar, comcat): the currency is required only with a price (price, currencyId) a price without a currency ends with the response success: false, code: 2 (validation) and the message "Cena reakce je vyplněná, ale chybí měna." (The reply's price is filled in but the currency is missing.) A currency without a price is dropped (null is stored) and the write succeeds
response: the price's currency may only be a public monetary currency an internal or non-monetary currency (say "Kredity") ends with success: false, code: 2 and the message "Měna #… není veřejná peněžní měna …". Which currencies you may use you learn from currency: active, monetary on, internal off
a write that contains fields marked FieldAccess … Audience::None is silently trimmed the fields password and salt of user, accessToken of message-thread and cancelToken of reservation are not taken from the write body on any path. The response is successful, the field is simply not stored. A user's password changes only through the route the site uses for it
message-thread: the subject of a conversation from a reply carries the advert's name (bazaar) or the enquiry's subject (comcat) the value is raw text without a prefix; "Reakce na inzerát: …" / "Poptávka: …" is put together by the site on display. Older conversations have an empty subject
a write of a single column (update-columns) with the boolean false false is bound as the number 0; before, it failed on a server whose database runs in strict mode

The codes currencyRequired and currencyNotAllowed do not go on the wire

The server distinguishes two reasons (errorCode = currencyRequired / currencyNotAllowed), but they exist only in the operation's internal result — the API response carries them only as the message text and data is null. A client therefore decides by code: 2 and by what it sent itself, not by the message text (it may change).

Since 19 October 2026 the response carries them in data.errorCode, see Contract changes since 19 October 2026.

Send the currency only with a price

The simplest client sends currencyId together with price and leaves the currency out without a price.

Contract changes of 3 October 2026#

Requests and responses#

What changed Impact on a client
a parameter of the wrong shape returns HTTP 400 and code 2 text instead of an array (filters, orderBys, columns, data, meta, skipFields, values), missing or empty ids on update-columns, invalid ids on register-event, an unknown boolean spelling (computeTotalCount=yes) and malformed includes are no longer cast and no longer end with a 500. See Error codes
an unknown or malformed filter returns HTTP 400 before, a 500 with HTML. The extra keys inclusive and isNull do not pass in the URL (they expect a boolean)
get-all: includes=* and columns return HTTP 400 before, a 500. A single path as a string (includes=user) now works on a listing too; includes=* stays only on get
filters, ordering and columns only over fields you may read a path to a password, an IP address, another user's personal data or a non-existent field returns HTTP 400 with the message Field path "…" is not allowed in filters, orderBys or columns. See Permissions
save: text values from the URL are converted by the field type data[currencyId]=3 is stored as a number, true/false as a boolean, a date as a date; an empty string on an optional field = null. A value that cannot be converted (1.9 into an integer) returns code 604 with the field name. Before, writing numeric fields from the URL failed. See CRUD pattern
an owner's save silently drops locked fields an owner may edit their account (user/save), but cannot change credits, points, discount, membership, e-mail, username, avatar or the third-party sign-in link — the field is dropped and the database value stays. A comment, rating, advert response or post cannot be moved to another thread or advert. The user's regionId is computed from paymentRegionId. See Editing your own account
content creation quota new responses to an advert or company profile, discussion posts and reports, comments, advert reports and contact messages: 30 per hour per user and 60 per hour per IP. Above the limit success: false, code 404, HTTP 200. See Limits

Data in responses#

What changed Impact on a client
other users' personal data: phone, street, postcode, company ID, VAT ID, company name and "about me" arrive empty for another caller. Read a seller's contact from user/public-profile and user/show-phone
IP addresses on adverts, responses, reports, posts, votes, payments and orders arrive empty for another caller
another user's credits, points, discount and discount level the key is missing from the response; the owner and an administrator see them
advert and post passwords and keys, the newsletter activation key, a response's readKey, the cart key, the outgoing mail password, token hashes nobody gets them over HTTP, not even an administrator. So you will no longer find readKey in a response

Sign-in and passwords#

What changed Impact on a client
user/update-password requires currentPassword without it or with a wrong one it returns code 108; a new password shorter than 8 characters 611. Success returns a new token pair in data and revokes the account's other refresh tokens — store it. See Authentication
passwords, keys and tokens only in the POST body update-password (password, currentPassword), reset-password (email, key, password) and is-auth-valid (token, or the Authorization header) read the body — form or JSON. A value in the URL is ignored
user/send-new-password sends a link and does not change the password the link is valid for an hour; POST user/reset-password sets the new password. An invalid key = code 112
a unified sign-in error an unknown account and a wrong password both return code 110. An inactive (109) or blocked (104) account is reported only after a correct password. A new limit: 20 failed sign-ins per hour per account from all addresses
an access token stops working after blocking, deactivation or a password change before, it stayed valid until expiry (15 minutes). The client gets a 401 at once
account deletion an account pending deletion cannot sign in (code 117, data.scheduledAt = the deletion date), refreshing its token returns 102; a deleted account cannot be saved (code 120). The request and the cancellation happen only on the website
sign-in via a third-party service confirms linking by e-mail runs on the website; new codes 113–116

Removed and internal actions#

What changed Impact on a client
removed actions payment-item/update-status-for-payment (bazaar, comcat, discussion) and user-payment/update-status-for-payment they return 404. A payment's status is changed only by the payment gateway and the administration
payment/express-offers is internal only the website composes the express SMS payment offer; there is no HTTP wrapper
payment/express-execute receives SMS messages from the aggregator it answers in plain text per the aggregator's specification; not meant for integrations

Contract changes of 5 October 2026#

What changed Impact on the client
sign-in: above the account limit the password is checked only from a known device or address an external auth/login is always an unknown device (it sends no cookie); only an address with a successful sign-in of the account in the last 30 days helps it. The reply to a throttled request is unchanged (429, Retry-After). See Limits
the email after posting an advert no longer carries the password, it carries a management link the link is valid for 7 days, can be used repeatedly and stops working when the advert password is changed. The password in the outgoing mail queue is masked. Whoever proves access with the advert password sees unmasked personal data of that advert only
the path key in uploaded files is dropped in external calls an external client sends files as base64 in data; a reference to a file on the server is accepted only by internal calls from the website's forms
get-all without limit returns 50 records, limit is capped at 500 a client that relied on a complete listing in one call must page (offset, limit, computeTotalCount=1). A larger limit is not rejected, only cut. Applies to calls from outside
the response envelope has no exception field the keys are success, message, data, code. The exception field used to be always null; a client should not read it
on a technical failure message is empty, the code decides database, file and internal API errors no longer return the exception text. Validation and business-rule failures carry their message as before. See Response format

Contract changes of 6 October 2026#

The main change: every external API call must carry an application key.

What changed Impact on the client
mandatory application key in the X-API-Key header (HTTPS only) the key is issued by the website administrator in Settings → Applications with Api access and shown only once; it identifies the application, not a user. Form: coolcms_ followed by 64 hexadecimal characters. Sign-in, token refresh and sign-out require it too. See Authentication
the key and the user token apply together without Authorization: Bearer the call is evaluated as guest (what an anonymous website visitor sees); with a token, with that user's roles. An invalid or expired token still returns 401 with code 103, it does not silently fall back to guest
a missing, wrong, disabled or revoked key always the same response: HTTP 401, code 501 (API_UNAUTHORIZED), message A valid application key (X-API-Key) is required.. It does not say which case occurred. See Error codes
limits per application defaults 20 per second and 600 per minute per key, shared by all users of the application; under them a per-caller limit (the account from the token, the IP address without a token and on public actions), default 120 per minute. Windows are fixed. The website administrator can change the values per application. See Limits
an exceeded limit HTTP 429, a Retry-After header, a body with the message Too many requests., data.retryAfter and code 404 (RATE_LIMIT_EXCEEDED, not an HTTP status). The special endpoint limits still apply; the sign-in and token refresh limits still return the message Too many requests, retry in <N>s with data.retryAfter
the key has no scopes the key does not decide which data the application gets, nor does it replace signing in. What a call may do is decided by the user's roles (guest without a token)
roles allowed per application the website administrator decides which roles the application may use. Default for a new application: guest, registrated, owner, receiver; administrator roles only explicitly. An administrator through an application without the admin role acts as a regular user (403 on admin-only actions, no admin-only fields, no unmasked personal data). Without owner, even your own records cannot be edited; guest is always allowed (without it nothing could be called without a token and nobody could sign in). See Permissions
endpoints that need no key /api/system/payment/execute, /api/system/payment/delivery, /api/system/payment/express-execute and /api/system/auth/oauth-deauthorize-callback are called by third parties that cannot send a key. Partner applications do not call them
X-API-Key in CORS is an allowed preflight header; a key in an app or browser script is not secret
OpenAPI specification /api-docs.json requires apiKeyAuth on every operation together with optional bearerAuth

A client without a key gets 401

Add the X-API-Key header to every call. The earlier description of the key as a replacement for signing in on server calls no longer applies: the key is part of every request and the user token is added to it.

Contract changes of 6 October 2026 (keys with an expiry)#

What changed Impact on the client
an application can have several keys (at most 5 valid) the administrator issues another key without the current one stopping — a key replacement without an outage. See Authentication
a key can have an expiry after it the key gets the same response as an unknown key: HTTP 401, code 501. The expiry can also be set later (rotation: expiry on the old key, a new key, deployment, deletion after the expiry). Read the key from configuration so that replacing it needs no new code
revoking a single key a revoked key returns 401 with code 501 at once, the other keys of the application keep working
limits belong to the application the defaults of 20 per second and 600 per minute are shared by all keys of the application (previously “per key”, the application had one)

Contract changes since 19 October 2026#

Main change: the API checks writes by a non-privileged caller the same way as the website forms, and external advert reads return only what the website shows. The administrator (admin role) is neither checked nor filtered.

Reads#

What changed Impact on the client
advert (bazaar, comcat): get, get-by, get-all and search return only adverts and profiles that are active and not expired (expirationDate today or later), or own ones (insertUserId = the user from the token) a hidden record disappears together with its relations (parameters, categories, images, files, texts); get of a hidden one looks like not found. A page may hold fewer records than limit, totalCount is an upper bound. An expired advert used to stay in listings. See Bazaar
category (bazaar, comcat): only active categories a disabled category is not returned
blog/carousel: get-all is public readable by a guest (application key only) and by a signed-in user

Writes — new refusals#

What changed Impact on the client
a refused save carries data.errorCode a stable name of the reason; data used to be null on failure. Other details (parameter id, missing fields, type of the blocked value) are only in the message text. See Error codes
advert/save (bazaar, comcat): parameter rules as in the form code: 2 with errorCode parameterTooLong, parameterUrlNotAllowed, parameterBlacklistedWord (active forbidden words in the request page language), parameterRequired (required by the parameter rules, e.g. price type) and parameterOptionNotAllowed. Required parameters are checked on insert; uploads and hidden fields are not
advert/save: a disabled or administrator-only category code: 615, errorCode: advertCategoryNotAllowed
advert/save: a new image over the size limit the image is not saved, the rest of the write passes; saveInfo.rejectedUploads contains {"name": …, "reason": "size"}. Limit: the parameter's max_size, else the maxImageSize setting, else 50 MB
advert/extend-expiration in a paid category code: 607, data: null — the extension is paid on the website
user/save: the account type requires a company ID and company name or a VAT ID code: 2, errorCode: userTypeDataMissing; only when the write carries the account type. See System
blacklist of e-mails, phones and IP addresses (CIDR ranges too) new comments, newsletter subscribers, adverts and profiles, replies, saved searches, contact messages, discussion posts, complaints, orders, reservations and new accounts with a blocked value: code: 615, errorCode: blacklisted. For an account edit, only a changed e-mail or phone. See System
comment/save into a thread with comments switched off code: 607, errorCode: commentsClosed
a guest comment/save where only signed-in users may comment code: 400, errorCode: commentOnlyForLoggedIn (HTTP 200)
response/save (bazaar) to a sold advert code: 607, errorCode: advertSold
forbidden words are one list (system/blacklisted-word) adverts, the company directory and the discussion share the system list; there are no per-module lists

Contract changes since 29 October 2026#

What changed Impact on the client
a technical failure (database, file, external service, queue, unknown error — e.g. code 1, 300, 500) no longer carries the exception text in message message is the generic "An internal error occurred. Quote the reference when contacting support." and the response gets an extra key errorRef (a short random code). The other keys (success, code, errorCode, data) do not change; domain errors (validation, state, not found) stay as they were, without errorRef. See Error codes

Behaviour on change#

The permission switch applies to the whole API

Changing the mode changes behaviour across every resource at once. Your client must handle a denial on an action that used to work.

Write your client defensively

Check the content type, the presence of keys and the status code. Responses may differ in detail from resource to resource.

What is coming#

Item State
Extending the specification to CRUD resources planned
HTTP wrappers for missing operations as integrations need them

Need something that is not available?

Contact the operator. Many operations exist and merely lack an HTTP wrapper — adding one is a matter of one resource, not a new feature.

Cookie settings