NomaCMS

Content

Content

Content Overview

Content methods read and write entries under /{collectionSlug} and bulk routes. They use your API key (CMS routes), not end-user tokens.

const noma = createClient({ projectId, apiKey })

Entry bodies use a data object keyed by each field’s name from the schema (usually kebab-case, e.g. meta-title). System fields such as locale and published_at sit next to data on create and update. state is accepted on create only — saves never change publish state.

Saves are separate from publish/unpublish

NomaCMS uses a classic working-draft + published-snapshot model:

  • content.update / content.patch / content.bulkUpdate mutate only the draft. They never mint a version and never flip the entry's public visibility.
  • content.publish(collectionSlug, uuid) mints a new immutable snapshot from the current draft and makes it live under state: "published".
  • content.unpublish(collectionSlug, uuid) takes the entry offline from state: "published" reads without deleting any versions.
  • On content.create, passing state: "published" is still a valid one-step flow (publish-on-create).

Draft vs. published reads

NomaCMS keeps an immutable snapshot every time an entry is published (see Versions). The state option on content.list / content.get chooses which source to read from:

  • state: "published" (default) reads the latest published snapshot. Entries that have never been published, or were later unpublished, are excluded.
  • state: "draft" reads the live working-draft field values.

Editing an entry does not immediately change what state: "published" consumers see — only content.publish does.

content.list

Query entries in a collection.

const result = await noma.content.list("blog-posts", {
  state: "published",
  locale: "en",
  sort: "created_at:DESC",
  paginate: 20,
  page: 1,
})
ParamTypeDescription
state'draft' | 'published'Filter by draft or published entries.
localestringLocale code.
excludestring | string[]Field names to omit from each entry.
whereRecord<string, unknown>Structured filters; serialized to where[field][...] query params.
sortstringComma-separated sort keys. Each key is column:ASC or column:DESC (for example created_at:DESC, title:ASC). Core columns include id, created_at, updated_at, published_at; custom field names sort when paginate is set.
limitnumberMax rows (non-paginated list).
offsetnumberSkip rows (only applied when limit is set).
paginatenumberPage size when using page.
pagenumberPage number.
timestampsbooleanInclude created_at / updated_at on each entry when supported.
countflagIf the count query parameter is present, the response is { count: number } for the current filters instead of a list of entries.
firstflagIf the first query parameter is present on a list collection, the response is a single entry object (first row). Singleton collections use a different code path and ignore this.

Singleton collections

If the collection has is_singleton: true, list returns one entry resource directly (not an array), before pagination. That is separate from the first query parameter, which applies to non-singleton collections when you want only the first matching row.

where filters

Pass a nested object; the SDK flattens it for query strings. Detailed operators (equals, in, relations, and so on) are documented in the Content API filtering reference.

content.get

Fetch a single entry by UUID.

const entry = await noma.content.get("blog-posts", entryUuid, {
  locale: "en",
  translation_locale: "tr",
  state: "published",
})
ParamTypeDescription
localestringPreferred locale for the entry.
translation_localestringLoad a linked translation in this locale when available.
state'draft' | 'published'Which revision to read.
excludestring | string[]Fields to strip from the response.
timestampsbooleanInclude timestamps when supported.

content.create

Create an entry.

await noma.content.create("blog-posts", {
  locale: "en",
  state: "draft",
  data: {
    title: "Hello",
    slug: "hello",
    content: "<p>...</p>",
  },
})
FieldDescription
localeOptional locale for the new entry.
statedraft or published. Use the built-in state instead of a custom "published" boolean field.
published_atOptional ISO timestamp when publishing.
dataRequired. Field values keyed by field name.

content.update

Full replacement of an entry's draft (PUT semantics on the API). Saves never change publish state — call content.publish afterwards to make edits live.

await noma.content.update("blog-posts", entryUuid, {
  data: {
    title: "Hello (updated)",
    slug: "hello",
    content: "<p>Updated</p>",
  },
})
 
await noma.content.publish("blog-posts", entryUuid)

content.patch

Partial update (PATCH). Send only the fields you want to change inside data, plus optional locale / published_at.

await noma.content.patch("blog-posts", entryUuid, {
  data: {
    title: "New title only",
  },
})

content.publish

Mint a new immutable version from the current draft and make it the live snapshot served under state: "published".

const { version_number } = await noma.content.publish("blog-posts", entryUuid)

content.unpublish

Clear the live pointer so state: "published" reads return 404. Versions are retained and still accessible via content.versions.*.

await noma.content.unpublish("blog-posts", entryUuid)

content.delete

Delete an entry.

await noma.content.delete("blog-posts", entryUuid)
await noma.content.delete("blog-posts", entryUuid, true) // force when API allows

The third argument sets force on the query string when you need hard deletes per API rules.

Bulk operations

content.bulkCreate

await noma.content.bulkCreate("blog-posts", {
  items: [
    { locale: "en", state: "draft", data: { title: "A", slug: "a" } },
    { locale: "en", state: "draft", data: { title: "B", slug: "b" } },
  ],
})

content.bulkUpdate

Like content.update, bulk updates only mutate drafts; state is not a field here. Call content.publish per UUID afterwards if you want the edits to go live.

await noma.content.bulkUpdate("blog-posts", {
  items: [
    { uuid: uuid1, data: { title: "A2" } },
    { uuid: uuid2, data: { title: "B2" } },
  ],
})

content.bulkDelete

await noma.content.bulkDelete("blog-posts", {
  uuids: [uuid1, uuid2],
  force: false,
})

content.versions

Every publish creates a new immutable snapshot. The versions namespace lets you list, inspect, revert, and label those snapshots.

content.versions.list

List all versions of an entry (most recent first).

const { data } = await noma.content.versions.list("blog-posts", entryUuid)

content.versions.get

Fetch a specific version by its integer version_number, including the full snapshot payload.

const v3 = await noma.content.versions.get("blog-posts", entryUuid, 3)
// v3.snapshot.fields -> values keyed by field name

snapshot.fields mirrors the same shape accepted by content.create / content.update: primitive scalars, UUID arrays for media, UUID or ID arrays for relations, and nested arrays for group fields.

content.versions.revert

Restore the working draft from a prior snapshot and publish it as a new version (vNext). Older versions are preserved, subject to plan retention.

const result = await noma.content.versions.revert("blog-posts", entryUuid, 3)
// result.message, result.version, result.entry

content.versions.updateLabel

Edit the label and/or description of a version. The snapshot stays immutable.

await noma.content.versions.updateLabel("blog-posts", entryUuid, 3, {
  label: "Launch copy",
  description: "Approved by marketing.",
})

Version retention is plan-based (Basic 10 / Grow 50 / Pro unlimited). When the cap is reached, the oldest versions are pruned on the next publish — the currently published version is never pruned. See Versions.

content.linkTranslation

Link two entries in the same collection as translations (different locales).

import type { LinkTranslationPayload } from "@nomacms/js-sdk"
 
const payload: LinkTranslationPayload = {
  translation_entry_uuid: otherEntryUuid,
}
 
await noma.content.linkTranslation("blog-posts", entryUuid, payload)
  • Assets - Upload files referenced from media fields.
  • Error Handling - Validation and not-found errors from these calls.

Search documentation

Find guides and reference pages