Skip to content
Foliosodev

REST API

API overview

The Folioso REST API lets scripts and integrations read your organisation's spaces, groups, tags and pages, search them, and create, update, move, tag and delete pages, with their content as TipTap JSON or Markdown. It can also upload images, read your recycle bin, and read and take page snapshots. It's available if your organisation's plan includes API access. See the pricing page.

What you can do

Method Endpoint Needs What it does
GET /me read Who the token belongs to, its organisation and its abilities.
GET /spaces read The spaces you can reach.
GET /groups read Groups in those spaces.
GET /tags read Tags in those spaces.
GET /pages read List pages, or search them with q.
GET /pages/{slug} read One page, with its content.
POST /pages write Create a page, with its group and tags.
PATCH /pages/{slug} write Rename a page, replace its content, move it, or set its tags.
DELETE /pages/{slug} write Move a page to the recycle bin.
POST /images write Upload an image to use on a page.
GET /recycle-bin read The pages in your recycle bin.
GET /recycle-bin/{slug} read One page in your recycle bin, with its content.
GET /pages/{slug}/snapshots read A page's snapshots.
GET /pages/{slug}/snapshots/{id} read One snapshot, with its content.
POST /pages/{slug}/snapshots write Take a snapshot of a page.

The API covers pages, their images and history, and reading their surroundings. Tags are created when you name them on a page. Groups, spaces, sharing and members are managed in the app, and so are restoring pages and snapshots.

Base address

The API lives on your organisation's address, under /api/v1:

http
https://{slug}.folioso.dev/api/v1

For an organisation at acme.folioso.dev, that's https://acme.folioso.dev/api/v1. The exact address is shown in Settings under API tokens.

If your organisation changes its address, requests to the old one are redirected for 30 days. See Errors.

Your first request

  1. Create a token in Settings.
  2. Call /me to check it works:
bash
curl https://acme.folioso.dev/api/v1/me \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"
json
{
  "data": {
    "user": {
      "id": 5,
      "name": "Ada Lovelace",
      "email": "ada@example.com"
    },
    "organisation": {
      "slug": "acme",
      "name": "Acme"
    },
    "token": {
      "name": "Deploy script",
      "abilities": ["read", "write"],
      "lastUsedAt": "2026-10-16T09:12:44+00:00",
      "expiresAt": null
    }
  }
}

How the API behaves

  • It acts as you. A token has exactly your access in its organisation, and never more. Lists only include what you can see, and writes follow the same permissions as the app. See Permissions.
  • Changes are the same as in the app. Pages created, edited or deleted through the API show in the space's activity feed and notify people you mention, just as they would from the editor.
  • JSON in, JSON out. Every response, including errors, is JSON. Send request bodies as JSON with Content-Type: application/json. The one exception is an image upload, which is sent as multipart/form-data.
  • Pages are identified by their slug, a UUID such as 9b2f6c1e-4d1a-4b8e-9f0a-2c3d4e5f6a7b. It's the last part of the page's address in the app. Page objects also carry a numeric id, which is what a link from one page's content to another names.
  • Your user id is data.user.id in the /me response above. It's what a mention of you names. The API doesn't list other members, so another person's id can only come from a mention already in content you can read.
  • Spaces are identified by their slug, groups and tags by a numeric id.
  • Dates are ISO 8601 with a timezone offset.
  • Field names in responses are camelCase (createdAt); request fields use snake_case where they have two words (group_id, per_page).

Page content

A page's body is stored as a JSON document in the TipTap format, the format the editor uses. The API returns it as content and accepts the same shape when you create or update a page.

You can also read and write it as Markdown: add ?format=markdown to get a markdown string instead, and send markdown instead of content. Markdown you read and send back unchanged keeps everything on the page. HTML isn't accepted. See Content formats.

Reference