---
title: Payload
description: Read a Payload collection through its REST API with the payload() source, lowering Lexical rich text bodies to Markdown with nothing to install.
---

The built-in `payload()` adapter reads a collection through the Payload REST API (`/api/<collection>`) and lowers each document's Lexical body to Markdown: paragraphs, headings, bullet, numbered, and check lists, quotes, links, uploads, and horizontal rules. A body held in a text field passes through as Markdown, except that a link that isn't a web, mail, phone, or relative address keeps only its label. Nothing to install.

```ts blume.config.ts
import { defineConfig } from "blume";
import { filesystem, payload } from "blume/sources";

export default defineConfig({
  content: {
    sources: [
      filesystem({ root: "docs" }),
      payload({
        prefix: "handbook",
        url: "https://cms.example.com",
        collection: "docs",
        // Field paths default to title / description / slug / content / updatedAt
        fields: { body: "richText" },
        // Extra query parameters: where[...], sort
        params: { sort: "title" },
      }),
    ],
  },
});
```

The API key comes from the `PAYLOAD_API_KEY` environment variable and is sent as `users API-Key <key>`; set `authCollection` when the key belongs to another auth-enabled collection. Only published documents are imported — `--preview` requests drafts and stages them with `draft: true`. Documents are fetched with `depth: 1` so uploads carry their URLs, and a relative upload path (`/media/x.png`) resolves against `url`. A `block` or `inlineBlock` node maps to a Blume component through the engine's `serializers` option, keyed by `blockType`, when you construct `payloadSource` directly and pass it to [`custom()`](/docs/content/sources/custom). Setting `serializers` writes the source's pages as MDX so the returned components render; a body held in a Markdown text field stays Markdown.
