Plank help · updated 2026-07-27
Public API & API keys
Create an API key and read or write your Plank workspace files from your own tools — scripts, integrations, or a coding assistant like Claude Code.
Agents: fetch the raw markdown of this page at /en/help/public-api.md
Public API & API keys
Your Plank files don't have to stay inside the app. With an API key you can read — and, if you choose, write — the documents in your workspaces from your own tools: a script, an integration, or a coding assistant like Claude Code running on your laptop.
The API is the same one the Plank app uses, exposed as a stable, versioned surface under /v1 so you can build against it without it shifting under you.
Create a key
Go to Settings → API keys and click Create key. You choose:
- Name — a label so you remember where it's used ("My laptop", "Reporting script").
- Workspaces — which workspaces the key can reach: one, several, or all of your workspaces. A key can never reach a workspace you aren't a member of.
- Access — Read-only (list, read, search, download) or Read & write (also create, overwrite, move, delete).
- Expiry (optional) — a date after which the key stops working.
The key is shown once, right after you create it — copy it then. Plank stores only a secure hash, so it can't show it to you again. If you lose it, revoke it and make a new one. You can revoke any key at any time from the same screen, and it stops working immediately.
A key looks like plank_pat_…. Treat it like a password: anyone holding it has the access you granted.
Use a key
Send the key as a bearer header on every request:
Authorization: Bearer plank_pat_xxxxxxxx
Always start with whoami to discover which workspaces the key can see and their ids — you pass a workspace id into every file call.
# Discover your access
curl -H "Authorization: Bearer $PLANK_API_TOKEN" \
https://api.plank.md/v1/whoami
# → { "user_id": "...", "token": { "can_write": true },
# "workspaces": [ { "id": "ws_123", "slug": "q1-reports", "name": "Q1 Reports" } ] }
Then read, list, search, and write files in a workspace. Paths are relative to the workspace root (e.g. reports/q1.md).
WS=ws_123
BASE=https://api.plank.md/v1/workspaces/$WS
AUTH="Authorization: Bearer $PLANK_API_TOKEN"
# List a directory
curl -H "$AUTH" "$BASE/files?path=reports"
# Read a file
curl -H "$AUTH" "$BASE/files/content?path=reports/q1.md"
# Search
curl -H "$AUTH" "$BASE/search?q=revenue"
# The whole file tree
curl -H "$AUTH" "$BASE/tree"
# Write (create or overwrite) — needs a read & write key
curl -X PUT -H "$AUTH" -H "Content-Type: application/json" \
"$BASE/files/content?path=reports/draft.md" \
-d '{ "content": "# Draft\n\nHello." }'
# Move / rename
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
"$BASE/files/move" -d '{ "source": "reports/draft.md", "dest": "reports/final.md" }'
# Delete
curl -X DELETE -H "$AUTH" "$BASE/files?path=reports/final.md"
PDFs, images and other binary files
Text files go through the API as-is. Binary files — PDFs, images, Word and Excel documents — must be sent and fetched as base64, otherwise the bytes get mangled on the way through.
# Download a binary file to disk
curl -H "$AUTH" -H "Accept: application/octet-stream" \
"$BASE/files/content?path=acts/scan.pdf" -o scan.pdf
# ...or as base64 inside the normal JSON response
curl -H "$AUTH" "$BASE/files/content?path=acts/scan.pdf&encoding=base64"
# Upload a binary file
curl -X PUT -H "$AUTH" -H "Content-Type: application/json" \
"$BASE/files/content?path=acts/scan.pdf" \
-d "{\"content\": \"$(base64 < scan.pdf | tr -d '\n')\", \"encoding\": \"base64\"}"
A few things worth knowing:
- If the base64 contains invalid characters, or mixes the two base64 alphabets, the request fails with
400. - Validation cannot detect a payload that was cleanly truncated, so for large uploads compare the
sizefrom a follow-up read against your file. - Uploads are limited to about 18 MB per file (the 25 MB request limit, minus base64 overhead).
- Downloads with
Accept: application/octet-streamare limited to 100 MB; the?encoding=base64form is limited to 25 MB, because base64 has to be held in memory as text. - Leave
encodingoff entirely for ordinary text files; nothing changes for them.
Your workspace database
Some agent-built dashboards and CRMs in Plank store their data in real tables — the workspace database ("Lightweight Apps"). Your key can read and manage those tables too, with the same access level you gave it for files: read-only keys can list, describe, and query rows; read & write keys can also create tables and insert, update, or delete rows.
BASE=https://api.plank.md/v1/workspaces/$WS
AUTH="Authorization: Bearer $PLANK_API_TOKEN"
# List the tables in this workspace
curl -H "$AUTH" "$BASE/app-data/tables"
# Describe a table's columns
curl -H "$AUTH" "$BASE/app-data/tables/invoices"
# Query rows — filter and sort with JSON query params
curl -H "$AUTH" "$BASE/app-data/tables/invoices/rows?where={\"status\":\"open\"}&orderBy={\"column\":\"total\",\"direction\":\"desc\"}&limit=25"
# Create a table — needs a read & write key
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
"$BASE/app-data/tables" \
-d '{ "name": "invoices", "columns": [ { "name": "customer", "type": "text" }, { "name": "total", "type": "numeric" } ] }'
# Insert a row
curl -X POST -H "$AUTH" -H "Content-Type: application/json" \
"$BASE/app-data/tables/invoices/rows" \
-d '{ "customer": "Acme Co", "total": 199.50 }'
# Update a row by id
curl -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
"$BASE/app-data/tables/invoices/rows/<row-id>" \
-d '{ "status": "paid" }'
# Delete a row by id
curl -X DELETE -H "$AUTH" "$BASE/app-data/tables/invoices/rows/<row-id>"
A quick reference:
- List tables —
GET .../app-data/tables - Describe a table —
GET .../app-data/tables/:table(columns + types) - Read rows —
GET .../app-data/tables/:table/rows(optionally filter withwhereand sort withorderBy, both JSON) - Create a table —
POST .../app-data/tables - Insert / update / delete a row —
POST/PATCH/DELETEon.../app-data/tables/:table/rows[/:id]
You can create new tables from your own tools, but changing the shape of an existing table — adding, renaming, or dropping a column, or adding a relationship between tables — is done by the agent inside Plank, not through this API.
Using it with Claude Code
Drop a snippet like this into your project's CLAUDE.md so the assistant knows how to reach your Plank files:
## Plank file access
My Plank business documents are available over the Plank public API.
- Base URL: https://api.plank.md/v1
- Auth: send header `Authorization: Bearer $PLANK_API_TOKEN` (the key is in my environment).
- First call `GET /whoami` to discover my workspace ids.
- For PDFs, images, or Office files add `&encoding=base64` when reading and send
`{ "content": "<base64>", "encoding": "base64" }` when writing. Plain text needs neither.
- Then read files with `GET /workspaces/<id>/files/content?path=<relative/path>`,
list with `/files?path=`, search with `/search?q=`, and (if needed) write with
`PUT /workspaces/<id>/files/content?path=`.
Set the key in your shell so it never lands in the repo (the variable name is yours to choose — PLANK_API_TOKEN is just what these examples use):
export PLANK_API_TOKEN=plank_pat_xxxxxxxx
Limits & good practice
- Scope tightly. Give a key only the workspaces and the access (read vs write) it actually needs. A read-only key can't change anything, which makes a leak far less costly.
- Rotate and revoke. If a key might be exposed, revoke it and issue a new one — it's instant.
- Rate limits. Requests are rate-limited per key; if you're batching heavy work, pace it and handle
429responses by retrying after a moment. - Full reference. The complete, always-current endpoint reference (OpenAPI) is published at
/v1/docs, with the raw spec at/v1/openapi.json— point codegen tools at that.