Skip to content

Catalog API ​

The Catalog API manages collection settings — the named document and media folders that structure a store's content. It is served by buildJsonApi from laikacms/catalog-api.

⚠️ You must state an access policy. buildJsonApi requires an authorize callback — it runs before every action below, including the two OpenAPI routes, and receives the action descriptor plus the originating Request. Return true to allow, false for a 403, or a LaikaError for a custom status. It decides what a caller may do; authenticating them is still your job — validate the credential inside the callback, or mount the handler behind @laikacms/server/api, which checks a Bearer token first. For a deliberately open surface, say so with authorize: allowAll from laikacms/json-api.

Resource Types ​

Resource typeattributes.typeDescription
document-collection"document"Document content folder
media-collection"media"Media / binary file folder

Both resource types use the collection key as the JSON:API id.

Endpoints ​

MethodPathStatusDescription
GET/openapi.json200OpenAPI 3.1 specification for this API
GET/openapi.yaml200OpenAPI 3.1 specification for this API, as YAML
GET/collections200List all collections
GET/collections/:key200Read a single collection
POST/collections201Create a collection
PATCH/collections/:key200Update a collection
DELETE/collections/:key204Delete a collection

All responses carry Cache-Control: no-store.

GET /openapi.json ​

Returns the OpenAPI 3.1 specification for the Catalog API as a JSON document.

Response — 200 OK, Content-Type: application/json

The response body is an OpenAPI 3.1.0 document. The servers array is rewritten to the absolute mount point so the document is usable as-is by code generators and API clients.

json
{
  "openapi": "3.1.0",
  "info": { "title": "Catalog API", "version": "1.0.0" },
  "servers": [{ "url": "https://example.com/api/catalog" }],
  "paths": { ... }
}

GET /openapi.yaml ​

Returns the same OpenAPI 3.1 specification as GET /openapi.json, serialized as YAML.

Response — 200 OK, Content-Type: application/yaml


GET /collections ​

Returns all configured collections.

Response 200:

json
{
  "data": [
    {
      "type": "document-collection",
      "id": "posts",
      "attributes": { "type": "document", "name": "Posts", "directory": "content/posts" }
    },
    {
      "type": "media-collection",
      "id": "images",
      "attributes": { "type": "media", "name": "Images", "directory": "public/uploads" }
    }
  ]
}

GET /collections/:key ​

Returns a single collection by key.

Response 200:

json
{
  "data": {
    "type": "document-collection",
    "id": "posts",
    "attributes": {
      "type": "document",
      "name": "Posts",
      "directory": "content/posts",
      "recursive": false
    }
  }
}

Response 404 — collection key does not exist:

json
{
  "errors": [
    {
      "status": "404",
      "code": "not_found",
      "title": "Not Found",
      "detail": "Collection 'posts' not found."
    }
  ]
}

POST /collections ​

Creates a new collection. Returns 201 Created on success.

Request — document collection:

json
{
  "data": {
    "type": "document-collection",
    "id": "articles",
    "attributes": {
      "type": "document",
      "name": "Articles",
      "directory": "content/articles",
      "recursive": true
    }
  }
}

Request — media collection:

json
{
  "data": {
    "type": "media-collection",
    "id": "images",
    "attributes": {
      "type": "media",
      "name": "Images",
      "directory": "public/uploads",
      "accept": ["image/png", "image/jpeg", "image/webp"]
    }
  }
}

Response 201 — echoes the created resource:

json
{
  "data": {
    "type": "document-collection",
    "id": "articles",
    "attributes": {
      "type": "document",
      "name": "Articles",
      "directory": "content/articles",
      "recursive": true
    }
  }
}

Response 400 — invalid body or unknown collection type.

PATCH /collections/:key ​

Updates an existing collection. data.id must match the URL :key; a mismatch returns 409 Conflict.

Request:

json
{
  "data": {
    "type": "document-collection",
    "id": "articles",
    "attributes": { "type": "document", "name": "All Articles", "recursive": true }
  }
}

Response 200 — same shape as POST 201, without status code.

Response 404 — collection key does not exist:

json
{
  "errors": [
    {
      "status": "404",
      "code": "not_found",
      "title": "Not Found",
      "detail": "Collection 'articles' not found."
    }
  ]
}

Response 409 Conflict — data.id ≠ URL :key:

json
{
  "errors": [{
    "status": "409",
    "code": "conflict",
    "title": "Conflict",
    "detail": "Body data.id ('wrong-key') does not match URL key ('articles'). Use the URL key as the resource identifier."
  }]
}

DELETE /collections/:key ​

Deletes the collection with the given key.

Response 204 No Content — empty body.

Response 404 — collection key does not exist.

Released under the MIT License.