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, pluspage,per_page,totalandpages.- refusals
- unauthorized, not_found, too_many_requests
| 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 thenbodyfor a Markdown note,itemsfor a checklist,columnsfor a board,nodesfor a map.- refusals
- unauthorized, not_found
| 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/:idanswers with. - refusals
- unauthorized, not_found, forbidden, read_only_key, workspace_locked, over_the_note_limit, missing_parameter, invalid
| 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, andmarkdownto write into the note. - refusals
- unauthorized, not_found, forbidden, read_only_key, cannot_comment, workspace_locked, missing_parameter, invalid, over_the_storage_limit
| 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": "",
"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
| 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."
}