Skip to content
Foliosodev

REST API

Recycle bin and snapshots

Read the pages in your recycle bin, and list, read and take snapshots of a page. These endpoints read what the app's recycle bin and version history show. Restoring a page from the bin, deleting it forever and restoring a snapshot are done in the app.

All examples use https://acme.folioso.dev/api/v1; use your organisation's address instead.

List your recycle bin

http
GET /recycle-bin

Needs the read ability. Lists the same pages as your own Recycle bin in the app's sidebar:

  • every page you deleted, in any space of the organisation, including My space; and
  • every page deleted by anyone in the spaces you administer. Organisation admins administer every shared space.

It never lists pages from another member's My space.

Pages are listed most recently deleted first.

Parameter Description
space Only pages in the space with this slug. An unknown slug gives an empty list.
per_page Results per page, from 1 to 100. Default 25. A value outside that range is treated as the nearest limit, not refused.
page Which page of results to return. Default 1.
bash
curl "https://acme.folioso.dev/api/v1/recycle-bin?space=engineering" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"
json
{
  "data": [
    {
      "id": 1207,
      "slug": "1f0e2d3c-5b6a-4978-8a9b-0c1d2e3f4a5b",
      "title": "Old on-call rota",
      "excerpt": null,
      "visibility": "space",
      "space": { "slug": "engineering", "name": "Engineering" },
      "group": null,
      "url": null,
      "createdAt": "2026-08-02T10:00:00+00:00",
      "updatedAt": "2026-10-01T16:20:41+00:00",
      "deletedAt": "2026-10-18T09:30:00+00:00",
      "purgeAt": "2026-11-17T09:30:00+00:00",
      "deletedBy": { "name": "Ada Lovelace" }
    }
  ],
  "links": {
    "first": "https://acme.folioso.dev/api/v1/recycle-bin?space=engineering&page=1",
    "last": "https://acme.folioso.dev/api/v1/recycle-bin?space=engineering&page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "path": "https://acme.folioso.dev/api/v1/recycle-bin",
    "per_page": 25,
    "to": 1,
    "total": 1
  }
}

Each item has the fields of a page object, without tags and content, plus:

Field Type Description
url null Always null. A page in the bin can't be opened in the editor until it's restored.
excerpt null Always null. The bin lists pages you may not be allowed to read, such as a colleague's private page in a space you administer, so it never previews their text. Read the page itself for its body.
deletedAt string When the page was deleted.
purgeAt string When the page becomes due for permanent deletion. Pages are permanently deleted by a nightly clean-up, so it goes at the first run after this time. See Retention.
deletedBy object or null The name of the person who deleted it, or null if their account no longer exists.

Pagination works as for List pages.

Get a page in the bin

http
GET /recycle-bin/{slug}

Needs the read ability. Returns one page from your recycle bin with its tags, content and contentEpoch, in the same shape as a bin list item. Add ?format=markdown to get its body as markdown instead. See Content formats.

Status When
404 The page isn't in your recycle bin: it doesn't exist, belongs to another organisation, hasn't been deleted, or is in a bin you can't see.
403 The page is in your bin, but you can't view it.
422 format isn't json or markdown, or you asked for Markdown and the stored content can't be written as Markdown without loss. See When Markdown isn't available.

Note

A space admin's bin lists every page deleted in the space, including other people's private pages, by title, as the app does. Their content is still private: their bin item carries no excerpt, and getting one of those pages answers 403.

List a page's snapshots

http
GET /pages/{slug}/snapshots

Needs the read ability, a plan that includes version history, and the editor or admin role in the page's space, or authorship of the page. On a private page, only its author. People who can open a page only because it was shared with them can't see its history, as in the app. See Who can see snapshots.

Snapshots are listed newest first, without their content. Snapshots from before the page's audience last changed are hidden, as in the app.

bash
curl https://acme.folioso.dev/api/v1/pages/9b2f6c1e-4d1a-4b8e-9f0a-2c3d4e5f6a7b/snapshots \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"
json
{
  "data": [
    {
      "id": 2048,
      "kind": "manual",
      "label": "Before the refactor",
      "title": "Deploying the API",
      "wordCount": 412,
      "createdAt": "2026-10-16T09:00:12+00:00",
      "createdBy": { "name": "Ada Lovelace" }
    },
    {
      "id": 1990,
      "kind": "auto",
      "label": null,
      "title": "Deploying the API",
      "wordCount": 398,
      "createdAt": "2026-10-15T03:15:40+00:00",
      "createdBy": null
    }
  ],
  "links": {
    "first": null,
    "last": null,
    "prev": null,
    "next": "https://acme.folioso.dev/api/v1/pages/9b2f6c1e-4d1a-4b8e-9f0a-2c3d4e5f6a7b/snapshots?cursor=eyJpZCI6MTk5MCwiX3BvaW50c1RvTmV4dEl0ZW1zIjp0cnVlfQ"
  },
  "meta": {
    "path": "https://acme.folioso.dev/api/v1/pages/9b2f6c1e-4d1a-4b8e-9f0a-2c3d4e5f6a7b/snapshots",
    "per_page": 50,
    "next_cursor": "eyJpZCI6MTk5MCwiX3BvaW50c1RvTmV4dEl0ZW1zIjp0cnVlfQ",
    "prev_cursor": null
  }
}
Field Type Description
id integer The snapshot's identifier.
kind string auto (a daily snapshot), manual or pre_restore (taken automatically before a restore). See Kinds of snapshot.
label string or null The label given to a manual snapshot.
title string The page's title when the snapshot was taken.
wordCount integer The number of words in the snapshot.
createdAt string When the snapshot was taken.
createdBy object or null The name of the person who took it, or null for a daily snapshot or a person whose account no longer exists.

The list returns 50 snapshots at a time. Follow links.next, or pass meta.next_cursor as cursor, until it's null.

Get a snapshot

http
GET /pages/{slug}/snapshots/{id}

Needs the same as listing them. Returns one snapshot with its body as content, or as markdown with ?format=markdown. Snapshots have no contentEpoch.

bash
curl "https://acme.folioso.dev/api/v1/pages/9b2f6c1e-4d1a-4b8e-9f0a-2c3d4e5f6a7b/snapshots/2048?format=markdown" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"
json
{
  "data": {
    "id": 2048,
    "kind": "manual",
    "label": "Before the refactor",
    "title": "Deploying the API",
    "wordCount": 412,
    "markdown": "## Install\n\nRun `composer install` first.",
    "createdAt": "2026-10-16T09:00:12+00:00",
    "createdBy": { "name": "Ada Lovelace" }
  }
}

A snapshot of another page, or one hidden because the page's audience has changed since it was taken, gets 404.

Take a snapshot

http
POST /pages/{slug}/snapshots

Needs the write ability and the same plan and role as listing them. Takes a manual snapshot of the page as it was last saved, like Take snapshot in the app.

Field Rules Description
label Optional. Text, up to 80 characters, or null. A label for the snapshot. Leading and trailing spaces are trimmed, and a blank label is no label.
bash
curl https://acme.folioso.dev/api/v1/pages/9b2f6c1e-4d1a-4b8e-9f0a-2c3d4e5f6a7b/snapshots \
  -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{ "label": "Before the refactor" }'

The response is 201 Created with the new snapshot, without its content, in the shape above. Its kind is manual and createdBy is you.

You can take up to 10 snapshots a minute. The allowance is shared with taking and restoring snapshots in the app.

Errors

Status When
403 Your plan does not include this feature.: the plan doesn't include version history.
403 This action is unauthorized.: you don't have the editor or admin role in the page's space and didn't write the page.
403 Invalid ability provided.: a read-only token tried to take a snapshot.
404 The page or snapshot doesn't exist, belongs to another organisation, or the snapshot is hidden.
422 A format other than json or markdown, a label over 80 characters, or a request for a snapshot as Markdown when its content can't be written as Markdown without loss (see When Markdown isn't available).
429 You've taken more than 10 snapshots in the last minute.