Go Scribi

The API

Notes

A note is text, a checklist, a board or a map. These are the calls that make, read, change and bin one, whichever kind it is.

Every call here carries Authorization: Bearer <key> and answers JSON. What is true of every call, and what every refusal means.

GET /api/v1/w/:workspace_id/notes

Every note you can read, most recently changed first.

needs
read on the thing it touches
answers
notes, each one without its body, plus page, per_page, total and pages.
refusals
unauthorized, not_found, too_many_requests
Parameters for GET /api/v1/w/:workspace_id/notes
Parameter In Type Description
page query integer Defaults to 1.
per_page query integer Fifty by default, a hundred at most.
type query string One of markdown, checklist, map, board. Anything else is ignored.
folder_id query integer Only the notes in that folder.

Bodies are never in a list, and ?text=true does not change that — a hundred notes with bodies is megabytes nobody asked for.

A workspace with a daily-notes folder makes today's entry when anything here is asked, credited to whoever set the folder up rather than to the caller.

An example
curl -X GET https://goscribi.com/api/v1/w/9879/notes \
  -H "Authorization: Bearer $GO_SCRIBI_KEY"

Answers 200:

{
  "notes": [
    {
      "id": 14335,
      "title": "Another 1",
      "type": "markdown",
      "folder": {
        "id": 2939,
        "name": "Survey"
      },
      "diary_date": null,
      "subject": null,
      "created_at": "2026-09-16T01:10:31Z",
      "updated_at": "2026-09-16T01:10:31Z",
      "lock_version": 0,
      "url": "https://goscribi.com/w/9879/notes/14335"
    },
    {
      "id": 14334,
      "title": "Another 0",
      "type": "markdown",
      "folder": {
        "id": 2939,
        "name": "Survey"
      },
      "diary_date": null,
      "subject": null,
      "created_at": "2026-09-16T01:10:31Z",
      "updated_at": "2026-09-16T01:10:31Z",
      "lock_version": 0,
      "url": "https://goscribi.com/w/9879/notes/14334"
    },
    {
      "id": 14333,
      "title": "Leases",
      "type": "markdown",
      "folder": {
        "id": 2939,
        "name": "Survey"
      },
      "diary_date": null,
      "subject": null,
      "created_at": "2026-09-16T01:10:31Z",
      "updated_at": "2026-09-16T01:10:31Z",
      "lock_version": 0,
      "url": "https://goscribi.com/w/9879/notes/14333"
    }
  ],
  "page": 1,
  "per_page": 50,
  "total": 3,
  "pages": 1
}

GET /api/v1/w/:workspace_id/notes/:id

One note, whole: its body, or its rows, columns and cards, or its nodes.

needs
read on the thing it touches
answers
note, and then body for a Markdown note, items for a checklist, columns for a board, nodes for a map.
refusals
unauthorized, not_found
Parameters for GET /api/v1/w/:workspace_id/notes/:id
Parameter In Type Description
text query boolean Adds the plain-text twin of every Markdown field.

A note you may not read is absent, not forbidden. So is one in the bin.

An example
curl -X GET https://goscribi.com/api/v1/w/10598/notes/13953?text=true \
  -H "Authorization: Bearer $GO_SCRIBI_KEY"

Answers 200:

{
  "note": {
    "id": 13953,
    "title": "Leases",
    "type": "markdown",
    "folder": null,
    "diary_date": null,
    "subject": null,
    "created_at": "2026-09-16T01:10:29Z",
    "updated_at": "2026-09-16T01:10:29Z",
    "lock_version": 0,
    "url": "https://goscribi.com/w/10598/notes/13953"
  },
  "body": "The **ferry terminal** closes at six.",
  "text": "The ferry terminal closes at six.\n"
}

POST /api/v1/w/:workspace_id/notes

Make a note of any of the four kinds.

needs
create on the thing it touches
answers
**201**, and the whole note, in the shape GET /notes/:id answers with.
refusals
unauthorized, not_found, forbidden, read_only_key, workspace_locked, over_the_note_limit, missing_parameter, invalid
Parameters for POST /api/v1/w/:workspace_id/notes
Parameter In Type Description
note[title] required body string Up to 300 characters.
note[body] body string Markdown, for a Markdown note.
note[note_type] body string markdown, checklist, map or board. Anything else is taken as markdown.
note[folder_id] body integer Where to put it. Left out, it goes to the top level.
note[template_id] body integer Stamps a template in, and settles the kind of note it is.

Creating a note through an application key leaves it with no created_by — the program's name lands on the opening version instead.

An example
curl -X POST https://goscribi.com/api/v1/w/1023/notes \
  -H "Authorization: Bearer $GO_SCRIBI_KEY" \
  -H "Content-Type: application/json" \
  -d '"{\"note\":{\"title\":\"By program\",\"template_id\":67}}"'

Answers 201:

{
  "note": {
    "id": 915,
    "title": "By program",
    "type": "checklist",
    "folder": null,
    "diary_date": null,
    "subject": null,
    "created_at": "2026-09-23T00:30:10Z",
    "updated_at": "2026-09-23T00:30:10Z",
    "lock_version": 1,
    "url": "https://goscribi.com/w/1023/notes/915"
  },
  "items": [
    {
      "id": 268,
      "content": "One",
      "note": null,
      "checked": false,
      "checked_at": null,
      "repeats": null,
      "position": 1,
      "children": []
    },
    {
      "id": 269,
      "content": "Two",
      "note": null,
      "checked": false,
      "checked_at": null,
      "repeats": null,
      "position": 2,
      "children": []
    }
  ]
}

POST /api/v1/w/:workspace_id/notes/:note_id/files

Attach a picture or a document to a note, and get the Markdown that shows it.

needs
comment on the thing it touches
answers
**201** — id, filename, content_type, byte_size, image, url, and markdown to write into the note.
refusals
unauthorized, not_found, forbidden, read_only_key, cannot_comment, workspace_locked, missing_parameter, invalid, over_the_storage_limit
Parameters for POST /api/v1/w/:workspace_id/notes/:note_id/files
Parameter In Type Description
file body file Multipart. The ordinary way in, and the one that streams — send this if you can.
data body string The same bytes as base64, for a client that can only send JSON. A whole data: URI is accepted and its prefix ignored.
filename body string Required with data, since base64 carries no name. Sent with file it overrides the uploaded name.

THE UPLOAD DOES NOT CHANGE THE NOTE. Write the markdown into the body yourself, with PATCH /notes/:id — so an upload never becomes an edit somebody did not make, and never costs a version.

The bytes decide the type. content_type and the filename's extension are hints and neither is stored: what comes back is what the file was sniffed as.

SVG, HTML and XML are refused whatever they are called, because they can carry scripts and we serve from our own origin. Zip one to keep a copy.

data is capped lower than file: base64 is held in memory as a string where multipart is streamed to a tempfile.

A file put on a note that is later binned goes with it, and its links 404 — the same as a picture uploaded through the interface.

An example
curl -X POST https://goscribi.com/api/v1/w/82/notes/89/files \
  -H "Authorization: Bearer $GO_SCRIBI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGNgAAACAAEA//8DAAAGAAVXv6vUAAAAAElFTkSuQmCC",
  "filename": "pier.png"
}'

Answers 201:

{
  "id": 10,
  "filename": "pier.png",
  "content_type": "image/png",
  "byte_size": 75,
  "image": true,
  "markdown": "![pier](/w/82/files/10)",
  "created_at": "2026-09-16T05:17:25Z",
  "url": "https://goscribi.com/w/82/files/10"
}

PATCH PUT /api/v1/w/:workspace_id/notes/:id

Change a note's title, body, folder or settings.

needs
write on the thing it touches
answers
The whole note.
refusals
unauthorized, not_found, forbidden, read_only_key, workspace_locked, conflict, kind_is_fixed, invalid
Parameters for PATCH /api/v1/w/:workspace_id/notes/:id
Parameter In Type Description
note[title] body string
note[body] body string
note[lock_version] body integer The version you read. Sent and stale, the write is refused rather than merged.
note[folder_id] body integer Moves it, which is a separate permission from changing it: a move is a delete here and a create there, so it needs create on the note AND create at the destination. null means the top level.
note[note_type] body string Not changeable: a note's kind is fixed when it is made. A different kind is refused with kind_is_fixed and nothing is applied; the kind it already has is accepted and ignored.
An example
curl -X PATCH https://goscribi.com/api/v1/w/10783/notes/11464 \
  -H "Authorization: Bearer $GO_SCRIBI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "note": {
    "body": "Changed"
  }
}'

Answers 200:

{
  "note": {
    "id": 11464,
    "title": "Leases",
    "type": "markdown",
    "folder": {
      "id": 3259,
      "name": "Survey"
    },
    "diary_date": null,
    "subject": null,
    "created_at": "2026-09-16T01:10:30Z",
    "updated_at": "2026-09-16T01:10:30Z",
    "lock_version": 1,
    "url": "https://goscribi.com/w/10783/notes/11464"
  },
  "body": "Changed"
}

DELETE /api/v1/w/:workspace_id/notes/:id

Move a note to Deleted notes.

needs
create on the thing it touches
answers
**200** — note, deleted: true, and a sentence saying it can be put back for thirty days.
refusals
unauthorized, not_found, forbidden, read_only_key

A delete is a bin, not a destroy, and it keeps working when a workspace is locked — that is the way out of the lock.

An example
curl -X DELETE https://goscribi.com/api/v1/w/10832/notes/11863 \
  -H "Authorization: Bearer $GO_SCRIBI_KEY"

Answers 200:

{
  "note": {
    "id": 11863,
    "title": "Leases",
    "type": "markdown",
    "folder": {
      "id": 3276,
      "name": "Survey"
    },
    "diary_date": null,
    "subject": null,
    "created_at": "2026-09-16T01:10:30Z",
    "updated_at": "2026-09-16T01:10:30Z",
    "lock_version": 0,
    "url": "https://goscribi.com/w/10832/notes/11863"
  },
  "deleted": true,
  "message": "Moved to Deleted notes. It can be put back for 30 days."
}