ZevContent Docs
Open dashboard

Getting started

Quickstart

From a key to real content in three requests. Nothing to install.

There is no SDK and no build step. A key and curl are the whole toolchain.

1. Get a key

Create a project at dashboard.zevcontent.com, then Settings → API keys. You are offered two kinds; take a secret key for now, because you are calling from a terminal.

export ZEVCONTENT_KEY=sk_...

The key selects the project. There is no project id in any URL — the same path serves different content for different keys.

2. Ask the project what it holds

GET /v1/introspection
curl https://api.zevcontent.net/v1/introspection \
  -H "Authorization: Bearer $ZEVCONTENT_KEY"

This is the single most useful request in the API. It returns every content type with its fields and the exact shape each response will have, every built-in module with its endpoints, the rich text contract, and the rules for authentication, paging, filtering, rate limits and errors.

It describes your project, so it cannot be out of date with the content you are about to fetch. Introspection covers what comes back.

3. Read something

The built-in modules work immediately, with nothing configured:

curl "https://api.zevcontent.net/v1/blog/articles?limit=5" \
  -H "Authorization: Bearer $ZEVCONTENT_KEY"
{
  "data": [
    {
      "slug": "how-we-deploy",
      "title": "How we deploy",
      "excerpt": "A short tour of the pipeline.",
      "authors": [{ "id": "aut_…", "name": "Ada", "slug": "ada" }],
      "categories": [{ "id": "cat_…", "name": "Engineering", "slug": "engineering" }],
      "reading_time_minutes": 6,
      "published_at": "2026-08-14T09:00:00.000Z",
      "seo": { "title": "How we deploy", "og_image": { "url": "https://…" } }
    }
  ],
  "meta": { "module": "blog", "limit": 5, "has_more": false, "next_cursor": null }
}

Note what you did not have to do: no second request for the byline, no second request for the category, and no fallback chain to build seo yourself.

Your own types work the same way, at /v1/content/{type}:

curl "https://api.zevcontent.net/v1/content/team-member?where[role]=engineer&sort=name" \
  -H "Authorization: Bearer $ZEVCONTENT_KEY"

4. Page properly

Every listing is paginated, and there is no way to ask for all of something. Read both meta.next_offset and meta.next_cursor: exactly one is set on a page that has a successor, and both are null on the last page.

# The loop that works against every listing here.
next=0
while [ -n "$next" ]; do
  page=$(curl -s "https://api.zevcontent.net/v1/kb/articles?limit=50&offset=$next" \
    -H "Authorization: Bearer $ZEVCONTENT_KEY")
  echo "$page" | jq '.data[].title'
  next=$(echo "$page" | jq -r '.meta.next_offset // empty')
done

Do not compute the next offset yourself, and do not loop on has_more alone. Pagination and filtering explains why the two styles exist.

Next

Updated at, Wednesday, September 2, 2026