API keys and authentication
Every Connect API call needs an API key in the X-Api-Key header. The public booking API (/public/v1) needs no key.
Publishable and secret keys
Each API key you create is a pair:
| Part | Prefix | Use it in | Access |
|---|---|---|---|
| Publishable key | pk_ | Your customer app or website | Only what a customer can do: locations, sign-in, the menu, restaurant orders, the product catalogue, payment status and the customer's own account. |
| Secret key | cnct_ | Your own server | Every endpoint, including the cart, webshop orders and shipping lookups. |
Treat the secret key like a password. Never put it in an app or a web page.
These endpoints need the secret key. A publishable key gets 403 PUBLISHABLE_KEY_NOT_ALLOWED:
GET /store/shipping/locationsGET /store/shipping/delivery-optionsPOST /store/orders- everything under
/store/cart/…
Keys belong to your organization and work with any of its active sales channels. There are no separate test and live keys.
Create a key
- Sign in to my.conciar.com as an admin or manager. Employees can't manage keys.
- Open Management → API Keys and click New API Key (or Create first key if the list is empty).
- Enter a Key Name, up to 100 characters, and click Create Key.
- In API Key Created, copy the publishable key and the secret key with their Copy buttons, then click Done.
Keys are shown only once
Conciar stores only a hash of each key. If you lose a key, create a new one.
The list shows each key's first characters, the date it was created, and when it was last used.
Replace or revoke a key
Conciar has no "rotate" button. To replace a key:
- Create a new key.
- Switch your app or server to the new key.
- Revoke or delete the old key.
Revoke stops the key at once; it stays in the list as "Revoked" and can't be switched back on. Delete removes it from the list. Both act on the whole pair: revoking the publishable key also revokes its secret key.
Calling from a browser
The Connect API sends no CORS headers, so a browser blocks calls made from JavaScript on another domain. Call it from your server or from a native app. A web shop can route its calls through its own backend, which also keeps the secret key off the page.
Errors
Errors come back as JSON. Check the HTTP status first.
| Status | Body | Cause |
|---|---|---|
| 401 | {"message": "API key required."} | No X-Api-Key header. |
| 401 | {"message": "Invalid or expired API key."} | The key is wrong, revoked or deleted. |
| 401 | {"message": "Unauthenticated."} | A customer endpoint without a valid bearer token. |
| 403 | {"status": false, "message": "PUBLISHABLE_KEY_NOT_ALLOWED"} | This endpoint needs the secret key. |
| 404 | {"message": "X-Sales-Channel header is required."} | No X-Sales-Channel header on a /store/… call. |
| 404 | {"message": "…"} | The channel token is unknown, inactive or from another organization. |
| 409 | {"status": false, "message": "IDEMPOTENCY_KEY_REUSED"} | An Idempotency-Key was reused for a different order, or the first order is still being placed (IDEMPOTENCY_KEY_IN_PROGRESS). |
| 422 | {"message": "…", "errors": {…}} | Validation failed. Other request errors return {"status": false, "message": "CODE"}. |
| 429 | {"message": "Too Many Attempts."} | Over a rate limit. Wait for the number of seconds in Retry-After. |
| 503 | {"maintenance": true, "message": "…"} | The sales channel is in maintenance mode. |
The public booking API returns {"status": false, "code": "…"}, for example NOT_FOUND, UNAVAILABLE or INVALID.
Rate limits
Responses carry X-RateLimit-Limit and X-RateLimit-Remaining.
Connect API
| Limit | Counted per |
|---|---|
| 300 requests per minute, whole API | IP address |
POST /app/init: 30 per minute | key |
POST /store/cart/init: 30 per minute | key |
| Other cart changes: 120 per minute | key |
| Payment status: 60 per minute | key |
| Placing, paying or cancelling a restaurant order: 10 per minute | key |
| Restaurant order status: 30 per minute | key |
| All restaurant orders for one store: 60 new orders and 120 payment or cancel calls per minute | store |
register, otp/request and otp/resend: 5 per minute | IP address |
otp/verify: 20 per minute | IP address |
| Sign-in codes: 1 per minute and 5 per hour | email address |
For a publishable key, "per key" means per key and IP address, so one busy app user doesn't use up the limit for everyone else.
Asking for a new sign-in code too soon returns 429 {"status": false, "message": "OTP_COOLDOWN", "retry_after": 42}.
Public booking API
| Limit | Counted per |
|---|---|
| 120 reads and 10 bookings or changes per minute | restaurant and IP address |
| Gift cards: 60 reads and 6 purchases per minute | restaurant and IP address |