The alpha testing program is now open to the public! We’d love to hear your feedback.Join!

Content

Developer tools

Read published entries through Content's v1 and v2 delivery APIs and GraphQL, generate TypeScript types, manage API tokens, and import or export entries.

Basics

Reading published entries over the API

Your website or app reads a project's published entries over HTTP. To list them, send a GET request to the v1 entries endpoint with your project's id:

GET /content/api/content/v1/entries?project=PROJECT_ID

Replace PROJECT_ID with your project's id, which Settings → Workspace shows. Addresses start with the domain you open Content on, followed by the path. To get the full address for your project, choose Publishing → Edge Delivery in the sidebar and use the copy icon beside Public REST endpoint.

The delivery APIs return published entries only, never drafts, and the v1 and GraphQL endpoints need no token. Responses are cached for up to 60 seconds, so a change can take a minute to show.

Concepts

The v1 and v2 delivery APIs

Content has two delivery APIs, and both return published entries only.

  • v1 returns every entry with the same fixed fields: title, slug, type, excerpt, body, author and so on. Use it when you don't use content types.
  • v2 works per content type. Each content type has its own address, named after its plural API ID, like articles, and its entries carry their typed fields. It supports filters, sorting, field selection, populating references and media, paging and locales.

There's also a small GraphQL endpoint with the same fixed fields as v1. Content types and fields are set up in Content architecture.

REST API

v1 entries endpoints

The v1 API has two endpoints. Both need the project's id in project; without it they answer with an error and status 400.

  • GET /content/api/content/v1/entries?project=PROJECT_ID lists published entries, the most recently published first. Add type=Article (or Page, Guide or Doc) to keep one type, and limit for how many to return: 50 by default, 100 at most.
  • GET /content/api/content/v1/entries/SLUG?project=PROJECT_ID returns one published entry by its slug, or status 404 if there isn't one.

Each entry has id, title, slug, status, type, excerpt, body, author, locale, coverUrl, environmentId, projectId, scheduledAt, publishedAt, createdAt and updatedAt. The list returns a JSON array of entries. The body is a JSON string of blocks, each with a type (paragraph or heading) and its text.

REST API

Querying a content type with the v2 API

Each content type has two v2 endpoints, named after its plural API ID:

  • GET /content/api/content/v2/projects/PROJECT_ID/PLURAL lists the type's published entries.
  • GET /content/api/content/v2/projects/PROJECT_ID/PLURAL/ID_OR_SLUG returns one.

A list answers with { "data": [...], "meta": { "pagination": {...} } } and a single entry with { "data": {...}, "meta": {} }. Each entry has id, slug, locale, type, publishedAt, createdAt and updatedAt, the built-in title, excerpt, body, author and coverUrl, and the type's delivered fields. Private fields are never included. A Media field returns the asset's id, url, name, mime, width, height and alt.

Requests without a token read the project's public entries. To use a token, send it in an Authorization: Bearer TOKEN header: a token in the query string is rejected. A token has to be active and belong to the project.

Reference

v2 filters, sorting and paging

v2 list requests take these query parameters, written in bracket syntax:

  • filters: filters[title][$containsi]=guide. Text, Rich text and Enum fields take $eq, $eqi, $ne, $nei, $in, $notIn, $lt, $lte, $gt, $gte, $between, $contains, $notContains, $containsi, $notContainsi, $startsWith, $startsWithi, $endsWith, $endsWithi, $null and $notNull. Numbers and dates take the comparisons, $in, $between and the null checks; Booleans take $eq, $ne and the null checks; JSON and Media fields take only the null checks. Combine conditions with $and, $or and $not. Reference fields can't be filtered.
  • sort: up to three keys, like sort=publishedAt:desc. The default is publishedAt, newest first.
  • fields: the fields to return.
  • populate: Reference fields to fill in with the linked entries, one level deep. Media fields are always filled in.
  • pagination: page and pageSize, or start and limit, but not both. Pages hold 25 entries by default and 100 at most. withCount=false skips the total.
  • locale: the locale to return. Without it, v2 uses the project's default locale.

Single-entry requests take fields, populate and locale. status only accepts published.

Reference

v2 limits, caching and errors

  • A request can have up to 200 query parameters, nested six brackets deep, with up to 20 filter conditions, logic nested five levels deep, 100 values in a list and 1,000 characters in a value.
  • Responses without a token are cached for up to 60 seconds; responses to a token aren't shared. Every response has an ETag, and a request whose If-None-Match matches gets status 304 with no body.
  • Errors answer with { "data": null, "error": { "status": …, "name": …, "message": … } }, with status 400 for a bad query, 401 or 403 for a token problem and 404 for an unknown project, type or entry.

Type Generation

Generating TypeScript types

Developers → Type Generation turns the project's content types into a TypeScript file, geiger-content.d.ts, with an interface for each type's entries, filter types and a map from each plural API ID to its type. Private fields are left out. Choose Copy or Download .d.ts, and Regenerate after you change content types. The figures across the top count Content types, Fields and Lines.

To fetch the same file in a build, request /content/api/content/v2/projects/PROJECT_ID/_schema?format=ts with a token that has the schema:read scope. Without format, the endpoint returns the schema as JSON. The screen's Fetch in CI card shows the full command.

GraphQL API

The GraphQL endpoint

Content's GraphQL endpoint, /content/api/content/v1/graphql, answers two queries about published entries. Send the query as JSON in a POST body, { "query": "…" }, or as a query parameter on a GET request.

  • { entries(projectId: "PROJECT_ID") { id title slug } } returns up to 50 entries, the most recently published first.
  • { entry(slug: "…", projectId: "PROJECT_ID") { id title body } } returns one entry, or null.

You can ask for id, title, slug, status, type, excerpt, body, author, locale, coverUrl and publishedAt. Any other query returns an error listing the supported ones.

API Tokens

Creating and revoking API tokens

To create a token for the v2 API, choose Developers → API Tokens, then Mint token. Only the Name is required. Pick its Scopes (delivery:read is selected to start), optionally set Expires at (optional), and choose Mint token.

The token, which starts with gct_, is shown once, in the Copy your token dialog. Copy it then: Content keeps only a hash, so a lost token can't be shown again and you have to mint a new one.

The list shows each token's scopes, its state (Active, Expired or Revoked) and when it was last used. To stop a token working, choose Revoke in its ⋯ menu and confirm. It stops at once and can't be undone. Of the scopes, the v2 API checks schema:read for the schema endpoint and delivery:read for private entries.

Creating and revoking tokens needs the Create and revoke delivery tokens permission, which the Owner and Admin roles have.

Service Accounts

Service accounts

Developers → Service Accounts keeps a list of named identities for automations, such as a nightly sync job, each with a role. To add one, choose Create account, type a Name (required), pick a Role, which is Viewer (the default), Editor or Admin, and choose Create account.

Each account's ⋯ menu has Edit and Delete, which asks you to confirm first. The figures across the top count Accounts, Admins, Editors and Viewers. Search names and roles.

Logs & Usage

Logs and usage

Developers → Logs & Usage merges the project's latest webhook deliveries and audit events into one list, newest first, up to 100 rows. Each row shows its kind (Webhook or Audit), what happened and its status, and when. Filter by kind, which starts on All kinds, and search the list. The screen only reads; Publishing covers webhooks and Governance covers the audit log.

Import & Export

Exporting and importing entries

Developers → Import & Export downloads the project's data as files. Choose Download beside the one you want:

  • Full workspace: entries, collections and slots, as JSON.
  • Entries, Collections or Slots, each as JSON.
  • Entries spreadsheet: entries as CSV, with id, title, slug, status, type, author and locale.

To import entries, choose a JSON file under Entries JSON file. It can hold an array of entries, or an object with an entries array, like an Entries or Full workspace export. Every row becomes a new entry with a new id, so importing the same file twice makes copies. Each row needs a title, and rows without a status become Drafts. A failed row doesn't stop the rest: Content reports how many were imported and lists the first failures.

Importing needs the Edit an entry or page permission, and Publish an entry or page for rows that are Published or Scheduled.