feat: llms.txt and llms-full.txt, openapi.json, MCP server
This commit is contained in:
1 parent
daba3c04c0
commit
4cff43fefb
25 files changed
+1691
-1
No files matched your search
@@ -0,0 +1,67 @@
|
||||
# Recipe: paginate, filter and choose a body format
|
||||
|
||||
> List articles page by page, search and sort them, and read bodies as markdown, HTML or JSON blocks.
|
||||
|
||||
`GET /v1/article/` always answers an envelope, never a bare array:
|
||||
|
||||
```sh
|
||||
curl "{{BASE_URL}}/v1/article/?format=html&size=5&page=1" \
|
||||
-H "Authorization: Bearer $RENEWCMS_API_KEY"
|
||||
```
|
||||
|
||||
```json
|
||||
{"items":[{"id":1,"title":"How we price a bathroom renovation","body":"<h2>What drives the price</h2><p>Room size, plumbing changes and finish level.</p>","body_format":"html","is_online":true,"site_id":2,"authors":[],"created_at":"2026-10-23T01:11:16.767761797+02:00","updated_at":"2026-10-23T01:11:24.236138156+02:00","excerpt":"What drives the price of a bathroom renovation.","slug":"how-we-price-a-bathroom-renovation","seo_status":"suggestions","seo_suggestions":3}],"total":1,"page":1,"size":5,"counts":{"all":1,"online":1,"draft":0,"suggestions":1}}
|
||||
```
|
||||
|
||||
In JSON, `<` and `>` are escaped as `<` and `>`; a JSON parser returns the plain characters.
|
||||
|
||||
## Walking every page
|
||||
|
||||
1. Request `page=1` with the `size` you want (`5`, `25`, `50` or `100`).
|
||||
2. Read `total` and `size`. The number of pages is `ceil(total / size)`.
|
||||
3. Request the next pages until `page * size >= total`. A page past the end answers `200` with `items: []`, so an empty `items` also ends the loop.
|
||||
|
||||
Ordering is applied to the whole list before slicing and ends with the id, so pages never overlap or skip.
|
||||
|
||||
## Filters
|
||||
|
||||
Combine them freely.
|
||||
|
||||
| Parameter | Example | Effect |
|
||||
| --- | --- | --- |
|
||||
| `q` | `q=grout` | Title contains the text, ignoring case and accents. Up to 200 characters. |
|
||||
| `status` | `status=draft` | `online` or `draft`. |
|
||||
| `site` | `site=renew-blog` | Only that site's articles. |
|
||||
| `seo` | `seo=suggestions` | `ready`, `suggestions` or `hidden`. |
|
||||
| `sort` | `sort=title:asc` | `title`, `status`, `created_at` or `updated_at`, then `:asc` or `:desc`. Default `updated_at:desc`. |
|
||||
|
||||
`counts` ignores every filter, so tab totals do not move while searching. `total` follows the filters.
|
||||
|
||||
```sh
|
||||
curl "{{BASE_URL}}/v1/article/?site=renew-blog&status=draft&sort=title:asc&q=grout" \
|
||||
-H "Authorization: Bearer $RENEWCMS_API_KEY"
|
||||
```
|
||||
|
||||
```json
|
||||
{"items":[{"id":2,"title":"Draft about grout","body":"x","body_format":"markdown","is_online":false,"site_id":2,"authors":[],"created_at":"2026-10-23T01:12:24.922895943+02:00","updated_at":"2026-10-23T01:12:24.926728869+02:00","excerpt":"","slug":"draft-about-grout","seo_status":"suggestions","seo_suggestions":4}],"total":1,"page":1,"size":25,"counts":{"all":2,"online":1,"draft":1,"suggestions":2}}
|
||||
```
|
||||
|
||||
## The `format` parameter
|
||||
|
||||
| Value | `body` | `body_format` |
|
||||
| --- | --- | --- |
|
||||
| absent or `markdown` | markdown string | `markdown` |
|
||||
| `html` | the stored HTML | `html` |
|
||||
| `json` | array of blocks | `json` |
|
||||
|
||||
It applies to every article route, including the writes. Request bodies of `POST` and `PATCH` stay HTML whatever the format. An invalid `format` is reported before any other error.
|
||||
|
||||
## Invalid values
|
||||
|
||||
A bad `page`, `size`, `status`, `sort` or `seo` answers `400` with a plain-text body:
|
||||
|
||||
```
|
||||
The request cannot be processed due to a mismatch in the format of the body.
|
||||
```
|
||||
|
||||
Media lists paginate the same way (`GET /v1/media/?page=2&size=50`) with their own `counts`.
|
||||
Reference in new issue
Block a user