API keys and the public API
How a workspace creates, scopes and revokes API keys for its own systems, and how those systems call the public API under /api/v1 with one.
For the Full Stack package
What a key is for
An API key lets a workspace's own code, a script, a server or another product, read, create and edit its projects, read its tasks and add tasks, without anyone signing in. Each key belongs to one workspace, carries the permissions chosen when it was made, and is sent as a bearer token to the public API under /api/v1.
- The full key is shown once, when it is created. The API keeps only a SHA-256 hash of it and a short prefix such as
nst_live_3f9a, so a lost key cannot be shown again: revoke it and create another. - Every call made with a key counts towards the workspace's API requests on the Billing page, and updates the key's Last used.
- The seed gives Forma Studio and Monogram one key each, so the list is not empty. Their secrets were never shown, so they authenticate nothing: create your own to try the API.
Creating a key
Open the API keys tab
In the dashboard, open Settings, then API keys, and press Create key. The tab appears only for a role holding
keys.manage.Name it and choose what it may do
Give it a Key name, such as "Production server", and tick what the key may do under "What the key may do". Reading projects and reading tasks are ticked to start with.
Copy the secret
"Copy the secret now": the dialog shows the full key once, with Copy key. Store it in your secret manager, then press I stored it. Closing the dialog forgets it.
| What the key may do | Scope | Used by |
|---|---|---|
| Read projects | projects:read | GET /api/v1/projects |
| Create and edit projects | projects:write | POST /api/v1/projects, PATCH /api/v1/projects/:projectId |
| Read tasks | tasks:read | GET /api/v1/projects/:projectId/tasks |
| Create and edit tasks | tasks:write | POST /api/v1/projects/:projectId/tasks |
A workspace that is past due beyond its grace period, or canceled, cannot create keys: see a failed payment.
Revoking a key
Press Revoke on the key's row and confirm with Revoke key: "Anything that uses this key stops working at once. This cannot be undone." A revoked key stays in the list, marked Revoked, below the active ones. Creating and revoking a key are both written to the workspace's activity log.
Calling the API with a key
Send the key as Authorization: Bearer on every request. The answers have the same envelope as the rest of the API, { "success": true, "data": ..., "message": "" }.
List the workspace's projects, newest change first, at most 100:
curl http://localhost:8000/api/v1/projects -H "Authorization: Bearer <your key>"List one project's tasks, in board order, with the project's id from that list (such as prj_01):
curl http://localhost:8000/api/v1/projects/prj_01/tasks -H "Authorization: Bearer <your key>"Add a task. Only the English title is required; status is backlog (the default), in_progress, review or done, priority is low, normal or high, and dueDate is written YYYY-MM-DD:
curl -X POST http://localhost:8000/api/v1/projects/prj_01/tasks \
-H "Authorization: Bearer <your key>" -H "Content-Type: application/json" \
-d '{"translations":{"en":{"title":"Check the launch email"}},"priority":"high"}'The task lands at the end of its column, and the board and the activity log show it as made by the person who created the key.
Create a project, or change one, with the same fields as the dashboard's project drawer: translations (the English name required, up to 120 characters, and an optional description), and optionally status (in_progress, review, blocked or completed), ownerId (a member), dueDate and progress (0 to 100):
curl -X POST http://localhost:8000/api/v1/projects \
-H "Authorization: Bearer <your key>" -H "Content-Type: application/json" \
-d '{"translations":{"en":{"name":"Launch site"}},"status":"in_progress"}'PATCH /api/v1/projects/<id> takes any of the same fields. Every write runs as the key's creator, with the dashboard's checks: the creator must still hold projects.write in the workspace, and a past-due workspace whose grace period has run out cannot create projects.
When a call is refused
| Status | Meaning |
|---|---|
| 401 | No bearer token, one that does not start with nst_, or a key that is unknown or revoked |
| 403 | The key was made without the scope this route needs, or the workspace is suspended (keys may still read, never write) |
| 403, "The account that created this API key may no longer change projects in this workspace." | A write, while the key's creator no longer holds projects.write |
| 404 | The person who created the key has left the workspace, so every route but the project list answers nothing: create a new key. Also an unknown project |
The message is a sentence in the request's language: the one above, or the general sentence for the status. A body field the route does not take answers 400.
Who can manage keys
| Permission | Allows | Seeded roles |
|---|---|---|
keys.manage | Seeing the API keys tab, creating and revoking keys | Owner, Admin |
It is part of each workspace's roles matrix, so the owner can grant it to another role.