Authentication
Non-public endpoints require authentication. Most integrations use app credentials sent in a Bearer header; user tokens cover requests made on behalf of a signed-in user.
Which method should I use?
- App auth - you are a backend or integration. Recommended. Uses
app_id+app_secret. - Token auth - you are acting on behalf of a signed-in ReadyCMS user (their orders, wishlist, rewards). Uses
user_id+token. - No auth - a small set of public endpoints (likes, views, bookmarks, notification register, forgot/reset password). Still send
namespace.
App authentication
App credentials are scoped to a tenant. Send them in the Authorization header - this keeps secrets out of URLs, logs, and caches:
curl -s "https://api.readycms.io/orders/?namespace=<tenant>" \ -H "Authorization: Bearer <app_id>:<app_secret>"
The Bearer token is the two values joined by a colon: <app_id>:<app_secret>. The scheme is parsed case-insensitively and the colon separator is required.
Credentials may also be passed as query or body parameters (app_id, app_secret, namespace), but the header form is strongly preferred.
Domain enforcement
A key can optionally restrict which origins may use it. When domain enforcement is enabled for a key, the request's Origin host must match the key's allowlist (exact, or a wildcard such as *.example.com). Requests with no Origin are allowed only if the key permits it. This matters most for browser-based usage, including the try-it console.
Token authentication
Use a user token to act as a specific signed-in user. Send user_id and token with tenant context:
curl -s "https://api.readycms.io/users/?namespace=<tenant>&user_id=<user_id>&token=<token>"
Expired or revoked tokens fail with error 5207 - refresh the token and retry.
Obtaining a user token
External clients (for example a mobile app backend) obtain a v2 user token by calling POST /auth/login/ with the user's email and password in the JSON body. This call needs no app credentials: the store name in namespace plus the email and password are the whole sign-in, so a client can connect to a store whose key pair it has never seen. The token is random, stored hashed, expires after 30 days by default, and can be rotated or revoked.
curl -s -X POST "https://api.readycms.io/auth/login/?namespace=<tenant>" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"••••••"}'
The response carries data.user_id, data.token (v2.…) and data.expires_at. Send user_id + token on later requests. If the user has two-factor enabled the call fails with 5211; repeat it with the 6-digit code in otp. Use POST /auth/refresh/ to rotate the token before it expires and POST /auth/logout/ to revoke it. One token is active per user; a new login replaces the previous one.
data.store comes back with the session (namespace, title, domain, url, currency, currency_sign, logo) so a client can show which store it just connected to. An unknown or unreachable store name fails with 5215 before the password is ever checked. Login is throttled per email (3 failures / 20 minutes) and per IP (30 attempts / 20 minutes per store); it and the two password reset routes are the only ones that accept no credentials, and it is POST only so the password never lands in a URL.
Resetting a forgotten password
A back-office user who cannot sign in resets the password in two calls, without a browser and without credentials. POST /auth/password/forgot/ with the email sends a 6-digit code to that inbox. The reply is the same whether or not the email belongs to a user, so the endpoint cannot be used to find accounts.
curl -s -X POST "https://api.readycms.io/auth/password/forgot/?namespace=<tenant>" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","language":"en"}'
Then POST /auth/password/reset/ with email, code (as a string, to keep leading zeros) and the new password. The code works once, expires after 15 minutes and stops working after 5 wrong tries (5213; request a new code). The password must be at least 16 characters with a lowercase letter, an uppercase letter, a digit and a special character (5217). A successful reset revokes the user's API token, so every session signs in again, and it does not sign the user in: call /auth/login/ next, which still asks for the two-factor code when the user has one.
curl -s -X POST "https://api.readycms.io/auth/password/reset/?namespace=<tenant>" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","code":"048213","password":"••••••••••••••••"}'
Authentication error codes
| Code | Meaning | What to do |
|---|---|---|
5202 | Invalid app credential params | Ensure app_id, app_secret, and namespace are all present and valid. |
5203 | App auth failed (no match) | Wrong secret, or the key is not active/published. |
5204 | Invalid token params | Ensure token, user_id, and tenant are present. |
5205 | Token not found / mismatch | Re-issue the user token. |
5206 | General auth failed | No method succeeded - check which one you intended to use. |
5207 | Token expired / revoked | Refresh the user token. |
5209 | Rate limit exceeded | Too many auth attempts - back off (10 attempts/min per IP). |
5211 | Two-factor code required | Repeat /auth/login/ with the user's 6-digit otp. |
5212 | Invalid credentials | Wrong email, password or one-time code. |
5213 | Too many sign-in attempts | Wait a few minutes; 3 failures per 20 minutes are allowed per email. |
5214 | User token invalid, expired or revoked | Returned by /auth/refresh/ and /auth/logout/. Log in again. |
5215 | Store not found | The namespace sent to /auth/login/ or /auth/password/* has no reachable store. Check the store name. |
5216 | Reset code invalid or expired | Wrong, used or expired code for /auth/password/reset/. Request a new code. |
5217 | Password too weak | Use at least 16 characters with a lowercase letter, an uppercase letter, a digit and a special character. |
See the full error code index for every code.