---
title: Publish and rerender
description: Two maintenance endpoints for acting on stored content without changing it — refreshing every cached page, and re-rendering a whole site in chunks.
order: 8
---

# Publish and rerender

A content change needs neither of these. Pages go live when they are written: there is no build step, no publish gate, and nothing to purge afterwards. These two endpoints exist for the rarer case where you need to act on stored content without changing it.

Both require an organization API key. `:site` accepts a slug or an id.

## Publish

```
POST /v1/sites/:site/publish
```

Refreshes every cached page for the site at once. There is no partially-updated window: one call, and every subsequent request is answered from freshly built output.

```bash
curl -s -X POST "$DOCSARY_API/v1/sites/acme/publish" \
  -H "authorization: Bearer $DOCSARY_KEY"
```

Responds `200` with the site's current publish counter — the same value that appears in the `x-docsary-epoch` header on every served page.

That is the whole operation. It publishes nothing that was not already live, so it is not a staging gate: use it when something outside your own writes changed how pages should look, or when you simply want a response rebuilt now rather than served from cache. It is also a safe no-op health check on the write path.

Publishing also retires the stored pages held by installed [offline readers](/offline), so nobody keeps an obsolete procedure after a correction ships.

## Rerender

```
POST /v1/sites/:site/rerender
```

Re-runs the render over stored markdown for **every page of every version** of the site. Titles, descriptions, HTML, tables of contents, and search index entries are all rewritten from the markdown you already pushed. No content changes; only its rendered form.

Reach for it after Docsary itself gains a rendering change you want applied to pages you are not otherwise touching. Re-pushing your folder does the same thing, so this is mainly for the case where the source is not conveniently to hand.

### The loop

The endpoint processes a small batch per call and tells you where to resume.

| Field | Type | Notes |
| --- | --- | --- |
| `offset` | number | Where to resume. Defaults to `0`. |
| `limit` | number | Batch size. Defaults to `6` and is **capped at 6**. |

```bash
curl -s -X POST "$DOCSARY_API/v1/sites/acme/rerender" \
  -H "authorization: Bearer $DOCSARY_KEY" \
  -H "content-type: application/json" \
  -d '{"offset":0}'
```

```json
{ "processed": 6, "next_offset": 6 }
```

Call again with the returned `next_offset` until it comes back `null`:

```json
{ "processed": 3, "next_offset": null }
```

```bash
offset=0
while [ "$offset" != "null" ]; do
  offset=$(curl -s -X POST "$DOCSARY_API/v1/sites/acme/rerender" \
    -H "authorization: Bearer $DOCSARY_KEY" \
    -H "content-type: application/json" \
    -d "{\"offset\":$offset}" | sed -n 's/.*"next_offset":\([^,}]*\).*/\1/p')
  echo "at $offset"
done
```

Pages are processed in a stable order, so the offset stays meaningful across calls.

### What happens at the end

The final call — the one returning `next_offset: null` — rebuilds the navigation tree for every version and publishes the result.

Nothing is published mid-loop. While a rerender is in progress the site keeps serving what it was already serving, and readers see the new output only once the loop completes. Half-rerendered content never reaches anyone; an abandoned loop leaves the site exactly as it was, which is the safe failure.

An interrupted loop can simply be restarted from `offset: 0`. Rerendering a page that was already rerendered is harmless.
