Документация

Три способа получить контент и справочник, созданный на основе самих маршрутов, поэтому в нём не может оказаться несуществующего эндпоинта.

Быстрый старт

Обычный fetch

Без SDK и сборки. Для списка записей это вся интеграция.

const response = await fetch(
  "https://api.schemahaus.com/v1/content/blog-post?locale=ka&limit=10",
  { headers: { authorization: `Bearer ${process.env.SCHEMAHAUS_TOKEN}` } },
);

const { data, meta } = await response.json();
// data is only what is PUBLISHED in Georgian. Nothing is substituted
// unless you ask: add &fallback=chain, and check item.localeFallback.

Next.js

SDK и вебхук ревалидации: когда редактор нажимает «Опубликовать», страница пересобирается сразу, не дожидаясь истечения кэша.

// app/[locale]/blog/[slug]/page.tsx
import { createClient } from "@schemahaus/client";

const cms = createClient({
  token: process.env.SCHEMAHAUS_TOKEN,
  site: process.env.SCHEMAHAUS_SITE,
});

export default async function Post({ params }) {
  const { locale, slug } = await params;
  const post = await cms.document("blog-post", slug, { locale });

  if (!post) notFound();
  return <article dangerouslySetInnerHTML={{ __html: post.data.body }} />;
}

// Publishing fires a webhook. Point a nextjs_revalidate webhook at your
// deploy and the page rebuilds itself when an editor presses publish.

Jekyll, во время сборки

Для статического сайта без серверной части: получите контент во время сборки и запишите файлы, которые ожидает генератор.

# _plugins/schemahaus.rb — runs at build time, writes _posts/
require "net/http"
require "json"

site = ENV.fetch("SCHEMAHAUS_SITE")
token = ENV.fetch("SCHEMAHAUS_TOKEN")

uri = URI("https://api.schemahaus.com/v1/content/blog-post?locale=en")
request = Net::HTTP::Get.new(uri)
request["authorization"] = "Bearer #{token}"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

JSON.parse(response.body)["data"].each do |post|
  File.write("_posts/#{post["publishedAt"][0, 10]}-#{post["slug"]}.md",
             "---\ntitle: #{post["data"]["title"].inspect}\n---\n" +
             post["data"]["body"])
end

Справочник API

Составляется из дерева маршрутов во время сборки. Эндпоинт появляется здесь вместе с файлом и исчезает при его удалении, поэтому документировать то, чего нет, здесь невозможно.

Доставка

Опубликованный контент, доступный по токену доставки. Его безопасно хранить в окружении сайта-потребителя: он умеет только читать.

  • GET/api/v1/authors

    The site's authors, with their per-language biographies.

  • GET/api/v1/content/{apiId}

    Published documents of one content type. Filter, sort, paginate by `page` or by cursor (`?cursor=` to start, then each page's `meta.nextCursor`); `?locale=` is strict unless `fallback` says otherwise.

  • GET/api/v1/content/{apiId}/{identifier}

    One published document, by slug or by document id.

  • GET/api/v1/media/{id}

    One media asset's metadata and variant URLs.

  • POST/api/v1/preview/verify

    Exchange a preview token for the draft it was minted for. Needs a delivery token with draft access.

  • GET/api/v1/site

    The site's settings and its content languages.

  • GET/api/v1/site/types

    The content types on the site, with their fields. Addressed by apiId; no internal ids are returned.

Управление

Запись, привязанная к участнику организации: ключ никогда не сможет больше, чем человек, который его создал. Именно этим пользуются скрипты импорта.

  • GETPOST/api/v1/manage/authors

    List or create authors.

  • PATCHDELETE/api/v1/manage/authors/{id}

    Edit or remove one author.

  • POST/api/v1/manage/documents

    Create a document in one language.

  • PATCHDELETE/api/v1/manage/documents/{id}

    Edit one language version, or soft-delete the whole document. Editing takes the revision you last read.

  • POST/api/v1/manage/documents/{id}/locales

    Start a translation of a document.

  • POST/api/v1/manage/documents/{id}/transition

    Move one language version through the workflow, including publishing it.

  • GET/api/v1/manage/documents/lookup

    Find a document by slug, drafts included — how an import decides whether it has already brought a post across.

  • POST/api/v1/manage/media

    Reserve an upload and get a presigned PUT for object storage.

  • POST/api/v1/manage/media/{id}/complete

    Confirm the bytes arrived. Idempotent, so a retried import does not count the storage twice.

  • GET/api/v1/manage/types

    Content types WITH their internal ids, which every write below needs.

Совместимость со Strapi

Формат запросов Strapi поверх того же опубликованного контента, чтобы существующий сайт мог переехать ещё до переписывания.

  • GET/api/strapi/api/{plural}

    The Strapi compatibility layer: Strapi's query shape over the same published content, so an existing site can move before it is rewritten.

Четыре правила, которые стоит знать перед началом

Доставка по умолчанию строгая
`?locale=ka` возвращает только то, что опубликовано на грузинском. Отсутствующий контент выглядит как отсутствующий, а не превращается незаметно в английский. Чтобы включить подстановку, добавьте `fallback=default` или `fallback=chain` и проверяйте у каждого элемента `localeFallback`, чтобы увидеть, что было подставлено.
API отдаёт опубликованные данные и никогда — черновики
Пока документ редактируется, отдаётся его последняя опубликованная версия — до следующей публикации. Если изменение не появляется, значит, оно не опубликовано: так и задумано.
Ключи медиафайлов никогда не меняются
При замене изображения создаётся новый файл с новым URL. Старый продолжает работать, потому что на него по-прежнему указывают граничные кэши и уже собранные сайты.
Каждый язык публикуется отдельно
Публикация английской версии не публикует немецкую. Единого статуса публикации у документа нет — он свой у каждой языковой версии.