Files
RenewCMS/docs/llm/gotchas.md
T

3.5 KiB

Gotchas

What trips up API clients: session-only routes, error texts, rate limits and draft visibility.

Session-only routes

An API key cannot call these routes. They answer 403 with a plain-text body and no JSON:

HTTP/1.1 403 Forbidden

This action needs a real session.
  • /v1/api-key/*, /v1/system/*, POST /v1/auth/verify, DELETE /v1/auth/register.
  • Every activity route under /v1/activity.
  • Writes on sites (POST, PATCH, DELETE under /v1/site, so a key cannot create a site) and on authors (POST, PATCH, DELETE under /v1/author).
  • PATCH /v1/settings.

Variant routes under /v1/media/{id}/variants answer 401 to a key instead. The sign-in routes (login, logout, register, password reset) ignore a key and give no 403.

When a task needs one of these routes, stop and tell the user to do it in the app. Do not try to log in with a password.

Error texts are plain text

Errors are not JSON. The body is one sentence; branch on the status code, and show the sentence to the user.

Status Typical text
400 The request cannot be processed due to a mismatch in the format of the body.
401 You must be logged in to access this resource.
403 This action needs a real session., Only the owner can do this., Only owners and admins can do this., You must verify your account to access this resource.
404 Article not found, Image not found
429 Too many requests. Please try again later.

An invalid, unknown, expired or revoked key answers 401, even on public routes. It is never treated as anonymous.

Rate limit: 429

Each key may make 120 requests per minute. The 429 response carries a Retry-After header holding the seconds to wait:

HTTP/1.1 429 Too Many Requests
Retry-After: 46

Too many requests. Please try again later.

Sleep for Retry-After seconds, then retry once. Do not retry in a tight loop. Prefer one list call with size=100 over many single reads.

Draft versus online

  • Anonymous callers and unverified users only see online articles. A draft answers 404 with Article not found, the same as an id that does not exist.
  • A verified session or a key sees the drafts its role may read: every draft with content.read at all, only its own with content.read at own. In lists, counts.draft is 0 for anonymous callers and status=draft answers an empty page.
  • A role without content.update, content.delete or content.publish for an article gets 403 with the body missing_permission and the header X-Missing-Permission. Saving a draft never publishes it.
  • POST /v1/article/ always creates a draft. Publishing is a separate call, PATCH /v1/article/{id}/publish.
  • Sitemaps list online articles only.

Writes

  • A title cannot be changed after creation. Create a new article instead.
  • PATCH /v1/article/{id} accepts body, site_id, author_ids and the SEO fields only. {} and null values answer 400, except cover_image_id and social_image_id, where null removes the image.
  • Request bodies are HTML even though responses default to markdown. Send <p> and <h2>, not markdown syntax, or it is stored literally.
  • Ids in paths are unsigned integers. Anything else answers 400.

Permissions follow the key's creator

A key acts as the user who made it. A key made by a user who is neither owner nor admin cannot do what only owners and admins can, and it answers 403 Only owners and admins can do this. Check GET /v1/auth/me to read the role of the key.