94 lines
2.2 KiB
Markdown
94 lines
2.2 KiB
Markdown
# API Reference
|
||||
|
|
|
|||
|
|
> Status: the public read API (`/api/volumen`) and the admin (`/admin`) are
|
|||
|
|
> implemented. The admin is server-rendered HTML, not part of the JSON API.
|
|||
|
|
|
|||
|
|
Base path: `/api/volumen`. All responses are JSON unless noted. Read endpoints
|
|||
|
|
send `Access-Control-Allow-Origin: *`.
|
|||
|
|
|
|||
|
|
## `GET /api/volumen/site`
|
|||
|
|
|
|||
|
|
Returns site metadata from the configuration.
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"title": "My Blog",
|
|||
|
|
"description": "A blog powered by volumen.",
|
|||
|
|
"base_url": "https://example.com",
|
|||
|
|
"language": "en",
|
|||
|
|
"author": "Anonymous"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## `GET /api/volumen/posts`
|
|||
|
|
|
|||
|
|
Paginated list of published posts (drafts are excluded), newest first.
|
|||
|
|
Posts with `all_langs = true` in their frontmatter match every `lang` filter.
|
|||
|
|
|
|||
|
|
| Name | Type | Default | Description |
|
|||
|
|
|-------|--------|---------|--------------------|
|
|||
|
|
| lang | string | — | Filter by language |
|
|||
|
|
| tag | string | — | Filter by tag |
|
|||
|
|
| page | int | 1 | Page number |
|
|||
|
|
| limit | int | 20 | Per page (1–100) |
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"page": 1,
|
|||
|
|
"page_size": 20,
|
|||
|
|
"total": 1,
|
|||
|
|
"posts": [
|
|||
|
|
{
|
|||
|
|
"slug": "hello",
|
|||
|
|
"title": "Hello",
|
|||
|
|
"excerpt": "Hello world.",
|
|||
|
|
"date": "2026-01-15",
|
|||
|
|
"lang": "en",
|
|||
|
|
"tags": ["intro"],
|
|||
|
|
"author": null,
|
|||
|
|
"cover": null,
|
|||
|
|
"reading_time": 1,
|
|||
|
|
"translations": {},
|
|||
|
|
"url": "/api/volumen/posts/hello"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## `GET /api/volumen/posts/{slug}`
|
|||
|
|
|
|||
|
|
Single post including the raw Markdown body and rendered HTML. Optional
|
|||
|
|
`?lang=` selects a translation. Returns `404` with `{"error":"not_found"}` if
|
|||
|
|
no match.
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"slug": "hello",
|
|||
|
|
"title": "Hello",
|
|||
|
|
"excerpt": "Hello world.",
|
|||
|
|
"date": "2026-01-15",
|
|||
|
|
"lang": "en",
|
|||
|
|
"tags": ["intro"],
|
|||
|
|
"author": null,
|
|||
|
|
"cover": null,
|
|||
|
|
"reading_time": 1,
|
|||
|
|
"translations": {},
|
|||
|
|
"url": "/api/volumen/posts/hello",
|
|||
|
|
"body": "Hello **world**.",
|
|||
|
|
"html": "<p>Hello <strong>world</strong>.</p>\n"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## `GET /api/volumen/tags`
|
|||
|
|
|
|||
|
|
Tag cloud with counts (published posts only), most frequent first.
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{ "tags": [{ "name": "intro", "count": 1 }] }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## `GET /api/volumen/feed.xml`, `GET /api/volumen/sitemap.xml`
|
|||
|
|
|
|||
|
|
RSS 2.0 feed (latest 20 posts) and a sitemap of post URLs, built from
|
|||
|
|
`site.base_url`.
|