← Documentation

Use these recipes with the /api/v2 API on your own installation. They target the API shipped with oCMS v0.30.0. The shared Fly.io demo disables writes. You need curl; Go and Node.js are not required.

Run the snippets in the same Bash or Zsh session. Set the base URL to your local server, or to the canonical HTTPS origin of your remote site. Use the interactive API reference to inspect this site's current schema.

Jump to reading pages, authentication, draft creation, updates, media uploads, or error handling.

1. Read published content

OCMS_API='http://localhost:8080/api/v2'
curl --fail-with-body --silent --show-error \
  "$OCMS_API/pages?per_page=5&page=1"

No key is needed to read published pages. Results are in data; pagination is in meta. Advance page through meta.pages; per_page is limited to 100. An empty data may be null.

curl --fail-with-body --silent --show-error \
  "$OCMS_API/pages/slug/your-published-slug?include=author,categories,tags"

Replace your-published-slug with a published page's slug. Anonymous requests cannot read drafts.

2. Check a scoped API key

Create a key in Admin → API Keys on your own site. For the draft examples grant pages:read and pages:write; add media:write for uploads. Keep any expiration and source-IP restrictions appropriate to your client.

Paste the key at the hidden prompt. This helper passes the header through standard input, keeping the key out of shell history and curl's command arguments. Do not enable shell tracing while working with credentials.

printf 'API key: '
read -r -s OCMS_API_KEY
printf '\n'
ocms_curl() {
  printf 'Authorization: Bearer %s\n' "$OCMS_API_KEY" |
    curl --header @- --fail-with-body --silent --show-error "$@"
}
ocms_curl "$OCMS_API/auth"

The auth response contains permissions at the top level. Confirm the scopes before making a write. Protected requests should go directly to the site's canonical origin; avoid following redirects with a bearer key.

3. Create and read back a draft

Choose an unused slug and save this JSON as draft.json. Keeping the payload in a file makes the exact request easy to review and reuse. The example stays a draft and creates no taxonomy or publication schedule.

{
  "title": "My API draft",
  "slug": "my-api-draft",
  "body": "<p>A draft created through the REST API.</p>",
  "summary": "A small API example.",
  "status": "draft",
  "page_type": "page",
  "language_code": "en"
}
ocms_curl --request POST "$OCMS_API/pages" \
  --header 'Content-Type: application/json' \
  --data-binary @draft.json

A successful create returns HTTP 201 and the new page in data. Copy its data.id into PAGE_ID below, replacing the placeholder. Use only the ID of the draft you just created.

PAGE_ID='replace-with-data.id'
ocms_curl "$OCMS_API/pages/$PAGE_ID?include=author,categories,tags"

Verify the title, body, slug, language, author, and status: draft. With no authentication, the same ID and slug return 404. A draft's uploaded media can still be public independently of the page.

4. Update only the fields you intend to change

ocms_curl --request PUT "$OCMS_API/pages/$PAGE_ID" \
  --header 'Content-Type: application/json' \
  --data-binary '{"summary":"Updated through the API."}'
ocms_curl "$OCMS_API/pages/$PAGE_ID"

The update is partial: omitted fields are preserved. Explicit taxonomy arrays replace those collections. Check that your draft remains a draft after updating. Review it in Admin → Pages before publishing; these examples never set status to published.

5. Upload an image

Choose an existing folder in Admin → Media and use its numeric ID. Replace the folder placeholder and ./example.jpg with your own values. The multipart fields below are all required by the v0.30.0 schema.

FOLDER_ID='replace-with-your-folder-id'
ocms_curl --request POST "$OCMS_API/media" \
  --form 'file=@./example.jpg' \
  --form-string "folder_id=$FOLDER_ID" \
  --form-string 'alt=A description of the image' \
  --form-string 'caption=An example upload'

A successful upload returns HTTP 201. Save data.id and inspect data.urls for the generated sizes. You can set that ID as featured_image_id in a later page update. Read the returned image URL without an Authorization header to check the public file.

Handle errors and uncertain writes

  • 401: check the key and its expiry. 403: check permissions, source-IP policy, and whether the site is running in demo mode.
  • 404: confirm the ID or slug and draft-read permission.
  • 422: inspect the returned validation details. In v0.30.0, a duplicate page slug also returns 422; read the existing page before choosing another slug.
  • 429: respect the response's retry guidance before trying again.

If a POST times out, do not repeat it immediately: the write may have completed. Read a page by its chosen slug and compare its content; for an upload, inspect Media for the expected file and metadata. Resolve an uncertain outcome before making another create request.

unset OCMS_API_KEY
unset -f ocms_curl

See the REST API guide, the live OpenAPI schema, and the installation troubleshooting notes for further reference.