Browse all documentation

REST API

Call Ridu’s generated HTTP contract from any language or Fetch-compatible runtime.

Ridu generates an OpenAPI document from the resolved application manifest. The tables below are the framework route families; your generated/ridu.openapi.json is authoritative for the concrete collection, global, auth, upload, version, and plugin routes enabled by your config.

A browser frontend on another origin must configure the HTTP boundary before calling these routes. See CORS for exact origins, credentials, custom headers, proxy trust, and preflight errors. Server-to-server clients do not need CORS.

Collection routes

{collection} is the authored collection slug and {id} is the public document ID.

Task Method and path Availability or input
List / create GET, POST /api/collections/{collection} JSON create for ordinary collections. An auth collection must use create-user; an upload collection uses multipart or remote-upload.
Read / update / delete GET, PATCH, DELETE /api/collections/{collection}/{id} PATCH accepts If-Match. With trash enabled, delete moves the row to trash.
Count GET /api/collections/{collection}/count Accepts the same filter, locale, and trash context as list.
Duplicate POST /api/collections/{collection}/{id}/duplicate JSON object contains optional field overrides; unavailable for auth collections.
Copy locale POST /api/collections/{collection}/{id}/copy-locale Body { "from": "en", "to": "fr" }; accepts If-Match.
Mutate inverse join PATCH /api/collections/{collection}/{id}/joins/{field} Body { "additions": [...], "removals": [...] }; only writable joins.
Bulk operations POST /api/collections/{collection}/bulk Body { action, ids, data? }; 1–100 unique non-empty IDs.

Bulk action is exactly one of update, publish, unpublish, delete, restoreDeleted, or deletePermanent. data is required only by update. Capability and access checks still run per document; this route is not a permission bypass.

Trash

These routes exist only for a trash-enabled collection:

Method and path Task
GET /api/collections/{collection}?trash=true List only trashed documents.
POST /api/collections/{collection}/{id}/restore-deleted Restore one document.
DELETE /api/collections/{collection}/{id}/permanent Permanently delete one document.
DELETE /api/collections/{collection}/trash Permanently empty the collection trash.

Versions and scheduling

These routes exist only when collection versions are enabled; draft/publish actions additionally depend on the configured version capability.

Method and path Task
GET /api/collections/{collection}/{id}/versions List snapshots.
GET /api/collections/{collection}/{id}/versions/{revision} Read one positive integer revision.
POST /api/collections/{collection}/{id}/publish Publish the current document.
POST /api/collections/{collection}/{id}/unpublish Return the current document to draft.
POST /api/collections/{collection}/{id}/restore/{revision} Restore a snapshot; add ?draft=true to restore as draft.
GET, POST /api/collections/{collection}/{id}/schedule List jobs or schedule publication with { "runAt": "…" }.
DELETE /api/collections/{collection}/{id}/schedule/{jobId} Cancel a scheduled publication.

Publishing, unpublishing, restoring, and scheduling accept If-Match for optimistic concurrency.

Uploads

Upload-enabled collections add these transports:

Method and path Content
POST /api/collections/{collection} multipart/form-data with required file and optional data JSON-object field.
POST /api/collections/{collection}/remote-upload JSON { "url": "https://…", "data": { … } }.
PATCH /api/collections/{collection}/{id}/image JSON focal point and optional crop coordinates; accepts If-Match.
GET, HEAD /api/uploads/{collection}/{object-key} Access-checked object delivery.

Multipart requests are limited to the collection’s maximum file size plus framing allowance. Remote-host, redirect, MIME, image-dimension, spool, and storage policies come from the configured upload backend. Object responses are always private and non-cacheable; HTML, SVG, and XML-like active content is forced to download with a sandbox policy.

Globals and schema

Method and path Task
GET /api/schema Read the canonical public manifest envelope.
GET, PATCH /api/globals/{global} Read or update a global; update accepts If-Match.
POST /api/globals/{global}/copy-locale Copy localized values; accepts If-Match.
GET /api/globals/{global}/versions List global versions.
GET /api/globals/{global}/versions/{revision} Read a global revision.
POST /api/globals/{global}/publish Publish a versioned global.
POST /api/globals/{global}/unpublish Unpublish a versioned global.
POST /api/globals/{global}/restore/{revision} Restore a global revision; accepts If-Match.
GET /healthz Process liveness.
GET /readyz Configured dependency and migration readiness.

Global scheduled publishing is not implemented. Version routes are absent when versions are not configured.

Authentication and account routes

Auth-collection feature flags determine which routes are generated.

Method and path Task
GET /api/auth/{collection}/bootstrap Check whether one-time first-admin setup is available.
POST /api/auth/{collection}/create-user Create a user with { "data": { … }, "password": "…" }.
POST /api/auth/{collection}/login Authenticate with email and password.
POST /api/auth/{collection}/forgot-password Request recovery when enabled.
POST /api/auth/{collection}/reset-password Consume a recovery token when enabled.
POST /api/auth/{collection}/request-verification Request verification when enabled.
POST /api/auth/{collection}/verify Consume a verification token when enabled.
POST /api/auth/{collection}/{id}/unlock Clear login-attempt lock state when enabled and authorized.
GET /api/auth/me Read the current session identity.
POST /api/auth/refresh Rotate/refresh the current session.
POST /api/auth/logout, POST /api/auth/logout-all Revoke the current or all actor sessions.
POST /api/auth/change-password Change password and revoke the current cookie session.
GET /api/auth/sessions List sessions for the current actor.
DELETE /api/auth/sessions/{id} Revoke one session.
GET, POST /api/auth/api-keys List API-key metadata or create a key when enabled.
DELETE /api/auth/api-keys/{id} Revoke an API key.

Login establishes the HttpOnly, SameSite=Lax ridu_session cookie. Cookie-authenticated browser requests must include credentials. A raw session token uses Authorization: Session <token>; Authorization: JWT <token> remains accepted for compatibility. An API key uses Authorization: Bearer <key>. API-key creation specifically requires cookie authentication, and the returned secret cannot be retrieved from a later list call.

Access, preferences, and document locks

Method and path Task
POST /api/access/collections/{collection} Resolve operation and field capabilities for optional { id, data, trash }.
POST /api/access/collections/{collection}/selection Resolve an access-checked { where?, trash? } to at most 100 IDs.
POST /api/access/globals/{global} Resolve global capabilities for optional { data }.
GET, PUT, DELETE /api/preferences/{key} Read, set ({ value }), or delete an actor preference.
DELETE /api/preferences Reset all preferences for the actor.
GET, POST, DELETE /api/collections/{collection}/{id}/lock Inspect, acquire ({ takeover? }), or release an editor lock.

Capability responses help build interfaces. Every later operation independently re-runs access rules and storage predicates, so a cached capability response is never authorization.

Preview routes

Method and path Task
POST /api/preview/collections/{collection}/{id}/token Mint a short-lived collection preview token.
GET /api/preview/collections/{collection}/{id} Read preview content with the preview token as Bearer authorization.
POST /api/preview/globals/{global}/token Mint a global preview token.
GET /api/preview/globals/{global} Read a global preview.
POST /api/preview/token/revoke Revoke { "token": "…" }.

Preview tokens are resource-bound credentials, not general API keys. See Live preview for iframe URL and update-channel handling.

Plugin routes

Application-authored root, collection, and global routes appear in the same generated OpenAPI document. Their handlers own arbitrary request and response shapes, and they are not authenticated automatically. See Custom endpoints for mounting, path parameters, actor/LocalAPI context, limits, route precedence, and raw SDK calls.

Compiled plugins contribute concrete method/path pairs to the generated OpenAPI document. Generic namespaced endpoints use /api/plugins/{plugin-key}/{endpoint}; a plugin transport may instead declare its exact path, such as the official GraphQL transport. Only declared methods are accepted, request bodies are bounded, and plugin errors use the same Ridu envelope. Inspect your generated OpenAPI file and the installed plugin’s reference module, such as graphql, for its available routes.

Query-string encoding

Collection list and count routes reject unknown query parameters.

Parameter Encoding and limit
page Positive integer; default 1, maximum 1,000,000.
limit Positive integer; default 10, maximum 100.
sort Repeat the parameter for each field; prefix a field with - for descending order.
where URL-encoded JSON query expression.
select URL-encoded JSON selection object.
populate URL-encoded JSON population object.
depth Integer from 0 to 5; expands eligible relationship roots uniformly. Cannot be combined with populate.
trash Exactly true or false; true requires trash capability.
locale Locale code, all, or *.
fallback-locale One locale, a comma-separated chain, or false. fallbackLocale is an accepted alias, but the two names may not conflict.
raw-fetch.ts
const query = new URLSearchParams({
  page: '1',
  limit: '20',
  where: JSON.stringify({ status: { equals: 'published' } }),
  select: JSON.stringify({ title: true, author: true }),
  locale: 'fr',
  'fallback-locale': 'en'
});
query.append('sort', '-createdAt');
query.append('sort', 'title');

const response = await fetch(`${origin}/api/collections/posts?${query}`, {
  credentials: 'include'
});

Exact operators and resource paths come from the generated contract; see Querying data.

Requests, responses, and limits

JSON input is strict: request objects reject unknown fields, duplicate keys, trailing data, excessive structural complexity, and bodies over the configured server limit (1 MiB by default). Send Content-Type: application/json for JSON and multipart/form-data for direct uploads. Successful resource reads use Ridu envelopes such as { "doc": … }, { "docs": …, "pagination": … }, or capability-specific envelopes. 204 is not the generic delete shape; delete operations return a JSON { id, deleted: true } envelope.

Every response includes X-Request-ID; include it when reporting a failure. CORS permits Accept, Authorization, Content-Type, and If-Match by default when an origin is allowed. If-Match accepts a quoted or unquoted positive revision. Host allowlists, CORS, rate limits, request timeouts, upload admission, and plugin-specific body limits may reject a request before its handler runs.

Errors

Failures use one stable JSON envelope. Validation errors use HTTP 422 and put field-addressable problems in issues; conflicts use HTTP 409. Do not branch on message text.

response.json
{
  "error": {
    "code": "validation",
    "status": 422,
    "message": "document validation failed",
    "requestId": "req_…",
    "issues": [{ "code": "required", "path": "title", "message": "title is required" }]
  }
}

The generated OpenAPI file is the language-neutral authority for enabled paths and schemas. The protocol reference lists the shared envelopes and stable error-code union; the SDK reference lists the typed Fetch methods. Prefer the TypeScript SDK when TypeScript is available—it performs query encoding and success-envelope checks for you.