Content API clients
The Content API clients in @uniformdev/canvas let you read and write Uniform content (compositions, entries, component definitions, content types, and routes). The most common use case is reading content for frontend applications such as Next.js apps. You can also call them from any server-side context: an automation handler, a CLI, a script, or a backend service.
Pick a delivery or a management client based on what you need to do:
- Delivery clients fetch content from Uniform's Edge Delivery APIs. Use them to render or serve compositions, entries, and routes. They are read-only.
- Management clients create, update, publish, and delete content through Uniform's Management APIs. Use them from automations, CLIs, and backend services.
Minimum SDK version
The clients on this page require @uniformdev/canvas version 20.74.7 or later. If you pass them to helpers from other Uniform packages (for example @uniformdev/tms-sdk), upgrade those packages to the same version.
The clients#
| Client | Mode | Methods | Host / shape |
|---|---|---|---|
CompositionDeliveryClient | delivery | get list | edge, resolved |
CompositionManagementClient | management | get list save saveAndPublish unpublish remove history | origin, canonical |
EntryDeliveryClient | delivery | get list | edge, resolved |
EntryManagementClient | management | get list save saveAndPublish unpublish remove history | origin, canonical |
ComponentDefinitionClient | management | get list save remove | origin |
ContentTypeClient | management | get list save remove | origin |
RouteClient | delivery | get | edge, resolved |
Constructing a client#
Supply projectId and either apiKey or bearerToken:
Delivery clients additionally accept edgeApiHost (defaults to https://uniform.global) and disableSWR, which sends x-disable-swr to skip stale-while-revalidate on data-resource caches. Management clients accept apiHost (defaults to https://uniform.app). For EU projects, see Configure SDKs for EU.
Reading#
Select what to read with a selector, then layer read options on top.
stateis optional and has a per-mode default. Delivery defaults to published, management defaults to draft.- Editions are derived, not asked for. An edition is a locale-targeted variant of a composition or entry. On a management
get, a bare id returns that composition or entry (raw). Passing alocaleresolves the locale-active edition (auto). Passing aneditionIdfetches that edition. That way a later save targets the same entity you just read. You can forceeditions: 'raw' | 'auto'if you need to. Onlist, pass the fulleditions: 'auto' | 'all' | 'raw'enum.
Searching and filtering#
list accepts filters, a full-text search, and an orderBy sort. Patterns are listed through the same clients with the pattern and patternType options.
For the filter syntax, operators, supported field types, and assets, see search and filter.
Selecting fields with data projection#
The select option on get and list fetches a subset of each entry or composition instead of the whole thing. The API prunes fields, field types, and slots before it resolves values. Pruned content skips asset resolution, rich text reference expansion, and data resource fetches. This reduces both payload size and response time.
select accepts a ProjectionSpec object, which the client serializes into select.* query parameters. The full wire-level projection syntax is documented in the entries endpoint OpenAPI specification.
Every article in the response contains only its title and coverImage fields. System properties such as _id, _name, and type stay in the response.
A projection spec has three buckets:
| Bucket | Selects by | Example |
|---|---|---|
fields | Field or parameter name | fields: { only: ["title", "slug"] } |
fieldTypes | Field type ID (for example text, richText, asset) | fieldTypes: { except: ["richText"] } |
slots | Slot name (compositions only) | slots: { only: ["hero"] } |
fields supports these operators:
| Operator | Type | Description |
|---|---|---|
only | string[] | Keep only fields whose name matches one of these patterns |
except | string[] | Drop fields whose name matches one of these patterns |
locales | string[] | For matching fields that survive filtering, return the full per-locale value map instead of only the requested locale's value |
blockDepth | number | "preserveAll" | Limit how many levels of block field children are kept. 0 removes all block fields. "preserveAll" prevents projection from trimming fields inside block children. |
fieldTypes supports only and except with field type IDs. slots supports:
| Operator | Type | Description |
|---|---|---|
only | string[] | Keep only the named slots |
except | string[] | Drop the named slots |
depth | number | Limit how many slot levels are kept, counted from the root. 0 removes all slots on the root. 1 keeps the root's slots but not the slots of their children. |
named | { [slotName]: { depth } } | Per-slot depth caps that override the container-wide depth for that slot |
Projection behaves as follows:
- Wildcards: values accept a single
*wildcard matching zero or more characters.seo_*,*Title, andmeta*Publishedare all valid. - Recursive by default: projection applies at every component and block in the returned tree, and is forwarded into entries resolved through reference fields.
- Exclusion wins: all
onlysets are intersected first, thenexceptsets are subtracted. - Unknown names are ignored: a name that doesn't match a field on a node doesn't cause an error. If none of the names in
onlymatch, the node is returned without fields. - Empty
onlystrips everything:fields: { only: [] }removes every field, andslots: { only: [] }flattens the component tree.except: ["*"]is equivalent. - Depth resets across references:
depthandblockDepthcount nesting within a single fetched tree and reset inside referenced entries.
For example, to drop rich text fields everywhere, including inside referenced entries:
To return only title and slug, and keep every locale's value of slug for hreflang tags:
The same option is available on RouteClient.get.
Writing#
Writing is available on the management clients only.
Use an AI coding assistant
The uniform-sdk agent skill teaches coding assistants such as Claude Code, Codex, Cursor, and Copilot how to authenticate with Uniform, configure the CLI, resolve routes, and read and write compositions, entries, and content types with the content API clients. To install it, see Uniform agent skills.
Migrating from the old clients#
The first migration decision for every call site is delivery or management? If the code reads to render or serve, use delivery. If it reads in order to mutate and save, or writes at all, use management.
| Old | New |
|---|---|
CanvasClient (compositions) | CompositionDeliveryClient + CompositionManagementClient |
CanvasClient (component definitions) | ComponentDefinitionClient |
ContentClient (entries) | EntryDeliveryClient + EntryManagementClient |
ContentClient (content types) | ContentTypeClient |
Uncached*Client | bypassCache: true |
RouteClient.getRoute | RouteClient.get (same client, renamed method) |
Delivery read#
Read, modify, write#
For example, an automation reacting to a draft event. The old approach needed six options to avoid losing data:
Content types and component definitions#
Renamed methods on the other clients#
The remaining clients keep their class but standardized their verbs on the same list, save, and remove vocabulary. Only the method names changed, and the old names remain as @deprecated aliases.
| Client | Deprecated → new |
|---|---|
CategoryClient | getCategories → list, upsertCategories → save, removeCategory → remove |
LabelClient | getLabels → list, upsertLabel → save, removeLabel → remove |
ProjectClient | getProjects → list, upsert → save, delete → remove |
DataSourceClient | getList → list, upsert → save |
DataTypeClient | get → list, upsert → save |
LocaleClient | get → list, upsert → save |
WorkflowClient | get → list, upsert → save |
ReleaseClient | get → list, upsert → save |
RelationshipClient | get → list |
ReleaseContentsClient | get → list |
EntityReleasesClient | get → list |
Note the list-returning get → list renames. get now consistently means a single fetch.
Using the clients from an automation#
An automation can call these clients as its own Uniform identity. Pass context.uniformCredentials to the client constructor. It carries the projectId and bearerToken the clients expect: