Contents
1. Getting started
- Be on the Premium plan (see plans). Keys cannot be created on Free or Pro, and existing keys stop working if a Premium plan lapses.
- In the app open Settings → API, give the key a name, tick Allow writes if it should create or change notes, and click Create key.
- Copy the key. It looks like
nsk_live_…and is shown once. If you lose it, revoke it and create another.
Base URL: https://noteshik.app/api/v1. All requests and responses are JSON over HTTPS.
curl https://noteshik.app/api/v1/me \
-H "Authorization: Bearer nsk_live_YOUR_KEY"
{
"user_id": 123,
"email": "you@example.com",
"plan": "premium",
"key": { "id": 7, "name": "my-script", "scopes": ["read", "write"] },
"rate_limit_per_minute": 120
}
2. Authentication & keys
Send the key as a bearer token on every request:
Authorization: Bearer nsk_live_YOUR_KEY
Scopes
| Scope | Allows |
|---|---|
read | Every GET endpoint: list and read notes, search, notebooks, tags. Every key has this. |
write | POST, PATCH and DELETE on notes. Opt-in when you create the key. |
Managing keys
Keys are created and revoked in Settings → API in the web app. Up to 10 keys can be active at once. Revoking is immediate. The list shows each key's prefix and when it was last used, never the full key.
Treat a key like a password. It gives whoever holds it access to your notes. Do not commit it to source control, put it in a browser page, or share it. Revoke it the moment you suspect it leaked.
3. Rate limits
120 requests per minute per key. Every response carries RateLimit and RateLimit-Policy headers (IETF draft-7) showing the limit, what is left and when the window resets. Once exceeded you get 429 with code: "rate_limited" until the window resets.
RateLimit-Policy: 120;w=60
RateLimit: limit=120, remaining=97, reset=41
List endpoints return at most 100 items per page (default 25); use limit and offset, and follow next_offset until it is null.
4. Errors
Every error is a JSON object with a human message and a stable machine-readable code:
{ "error": "This API key does not have the \"write\" scope.", "code": "insufficient_scope" }
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request, invalid_id | Malformed body or parameter. The message says which. |
| 401 | unauthorized, invalid_api_key | Header missing or malformed, or the key is unknown or revoked. |
| 403 | upgrade_required | The account is not on Premium. Response also has upgrade_to: "premium". |
| 403 | insufficient_scope | Write call with a read-only key. |
| 404 | not_found, notebook_not_found | No such note / notebook in your account, or no such route. |
| 429 | rate_limited | Over 120 requests in the current minute. |
| 500 | server_error | Something failed on our side. Safe to retry with backoff. |
5. Notes
The note object
| Field | Type | Notes |
|---|---|---|
id | integer | Stable id. |
title | string | |
content | string (HTML) | The note body as the editor stores it. Only on single-note responses. |
content_text | string | Plain-text rendering of content. Only on single-note responses. |
notebook_id, notebook | integer | null, string | null | The notebook (folder) the note is in. |
tags | string[] | Tag names. |
is_pinned | boolean | |
created_at, updated_at, deleted_at | ISO-8601 | null | Deleted notes are in the trash, not gone; see include_deleted. |
GET/notes
List notes, newest change first, without content.
| Query | Description |
|---|---|
limit, offset | Paging. limit 1–100, default 25. |
notebook_id | Only notes in this notebook. |
updated_since | ISO-8601 timestamp; only notes changed at or after it. Handy for incremental sync. |
include_deleted | true to include trashed notes (they carry deleted_at). |
curl "https://noteshik.app/api/v1/notes?limit=2" \
-H "Authorization: Bearer nsk_live_YOUR_KEY"
{
"notes": [
{ "id": 42, "title": "Meeting notes", "notebook_id": 3, "notebook": "Work",
"tags": ["work"], "is_pinned": false,
"created_at": "2026-09-21T10:00:00.000Z", "updated_at": "2026-09-21T10:05:00.000Z", "deleted_at": null },
{ "id": 41, "title": "Recipe", "notebook_id": null, "notebook": null, "tags": [], "is_pinned": false,
"created_at": "2026-09-20T18:00:00.000Z", "updated_at": "2026-09-20T18:00:00.000Z", "deleted_at": null }
],
"total": 57, "limit": 2, "offset": 0, "next_offset": 2
}
GET/notes/:id
One note with content (HTML) and content_text.
curl https://noteshik.app/api/v1/notes/42 \
-H "Authorization: Bearer nsk_live_YOUR_KEY"
POST/notes write scope
Create a note. Send either content (HTML) or text (plain text; blank lines become paragraphs). Optional: title, tags, notebook_id, is_pinned. Returns 201 with the full note.
curl -X POST https://noteshik.app/api/v1/notes \
-H "Authorization: Bearer nsk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Standup 21 Sep",
"text": "Shipped the API docs.\n\nNext: onboarding email.",
"tags": ["work", "standup"],
"notebook_id": 3
}'
Notes created this way appear in the app on every device like any other note: they are encrypted at rest the same way, show up in sync and search, and get version history on later edits.
PATCH/notes/:id write scope
Partial update: send only the fields to change (title, content or text, tags — replaces the whole list — notebook_id (null moves it out of any notebook), is_pinned). Changing the content saves the previous version to the note's history.
curl -X PATCH https://noteshik.app/api/v1/notes/42 \
-H "Authorization: Bearer nsk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "tags": ["work", "done"], "is_pinned": true }'
DELETE/notes/:id write scope
Moves the note to the trash (same as deleting in the app; it can be restored from the app). Returns { "deleted": true, "id": 42 }.
6. Search
GET/search?q=…
The same engine as the app's search box: words are AND-ed, "quoted phrases" match exactly, -word excludes, OR works, and if nothing matches exactly a fuzzy pass runs ("fuzzy": true in the response). Optional notebook_id, limit, offset. Results are note summaries plus a snippet and relevance.
curl "https://noteshik.app/api/v1/search?q=invoice%20-draft" \
-H "Authorization: Bearer nsk_live_YOUR_KEY"
7. Notebooks & tags
GET/notebooks
Your notebooks (folders in the app), alphabetical, each with id, name, parent_id, note_count, created_at.
GET/tags
Your tags, alphabetical, each with id, name, note_count.
curl https://noteshik.app/api/v1/notebooks -H "Authorization: Bearer nsk_live_YOUR_KEY"
curl https://noteshik.app/api/v1/tags -H "Authorization: Bearer nsk_live_YOUR_KEY"
Creating notebooks and tags over the API is not in v1. Tags are created on the fly when you put a new name in a note's tags; notebooks are managed in the app.
8. Security & scope
- Keys are hashed. We store a SHA-256 digest of each key and a short display prefix, never the key itself, so it cannot be read back by anyone, including support.
- Same protection as the app. API traffic is TLS-only and note content is stored encrypted at rest (AES-256), exactly as for notes made in the app. See Security.
- Your account only. A key can only reach the notes of the account that created it. Shared and collaborative notes belonging to other users are not exposed.
- Not in v1: attachments and images (URLs inside
contentneed an app session), reminders, tasks, templates, note history, creating notebooks. Tell us what you need at Contact.
Use of the API is covered by the Terms of Service and Acceptable Use Policy. Automated abuse or attempts to reach other accounts' data will get the key and account suspended.