MantisDocs

Keys

The secret and publishable keys, where each one goes, and how to add, reset, rotate and delete them.

Every request to https://data.shipmantis.com carries a project key. The key says which project the request is for and what it may do. There are two kinds, and they always come as a pair.

Secret keyPublishable key
Starts withmk_secret_mk_pub_
Lives inYour server, the CLI, your agentYour app in the browser
Environment variableMANTIS_SECRET_KEYMANTIS_PUBLISHABLE_KEY
Queries and filesEvery row and every file. Access rules are skipped.Only what your access rules allow. Nothing by default.
Schema, branches, rewindYesNo

A project starts with one pair, made with the project. Each machine that runs init against that project later gets its own pair.

Which key a request needs

RequestSecret keyPublishable key
POST /v1/query, and live queries over /v1/liveYesYes, through the rules
/v1/storage/* (files)YesYes, through the file rules
/v1/schema/*: read, plan, apply, undoYesNo
/v1/branches/*: list, create, promote, deleteYesNo
/v1/changes/{id}YesNo
/v1/rewind/*YesNo

A publishable key sent where the secret key is needed is refused with 403, before the request does anything.

Sending a key

The SDK sends the key for you. Pass the one that fits where the code runs:

lib/mantis.ts
import { createClient } from "@shipmantis/sdk";
import schema from "../mantis/schema";

export const mantis = createClient({
  url: process.env.MANTIS_URL!,
  key: process.env.MANTIS_SECRET_KEY!,
  schema,
});

Without the SDK, send the key as a bearer token. Mantis-Branch picks a branch; leave it out for main.

curl https://data.shipmantis.com/v1/schema \
  -H "Authorization: Bearer $MANTIS_SECRET_KEY" \
  -H "Mantis-Branch: try-tags"
HeaderWhat it holds
AuthorizationBearer <key>. Required on every /v1 request.
Mantis-BranchA branch name. Optional; main without it.
Mantis-User-TokenThe signed-in user's JWT, for the rules. Only the publishable key needs it.

A live query sends the key once, when its connection opens, and the branch as a connection parameter. The SDK does both.

A pair per machine

Every key has a name, and the two keys of a pair share it. The first pair has no name; the dashboard lists it as Made with the project.

Running init on a project that already has keys makes a new pair named after the machine, like work-laptop, mantis init, and writes it to that folder's .env.local. The keys on every other machine keep working.

To make a pair yourself, open the project in the dashboard, type a name under New key pair (up to 64 characters), and press Add. A pair for your production server, one for CI and one per teammate's laptop means any one of them can be reset or deleted without touching the others.

Shown once

Mantis keeps a SHA-256 hash of each key, never the key itself. The full key is shown exactly once: in the init output and .env.local, or in the dashboard right after you add or reset it. After that the dashboard shows only its first 16 characters, like mk_secret_BS5QFt…, to tell keys apart.

A lost key can't be recovered. Reset it, or add a new pair.

Reset or delete

Both are on the project's page in the dashboard, next to each key, and both ask before they do anything.

ResetDelete
The keyStops working at onceStops working at once
A replacementA new key of the same kind and name, shown onceNone
Use it whenThe key leaked, but the place that used it still needs oneThe machine or service is gone, or you rotated it out
The other key of the pairUntouchedUntouched

Neither can be undone. To get a deleted key's place back, add a new pair.

Deleting every key leaves the project unreachable from code until you add a new pair. The dashboard and your data are not affected.

Rotating without downtime

A reset stops the old key before you have put the new one in place. To swap a key on a running service without a single refused request, overlap them:

Add a new pair

Under New key pair, name it after the service and today's date, like production 2026-10. Copy both keys.

Deploy with the new keys

Set MANTIS_SECRET_KEY and MANTIS_PUBLISHABLE_KEY on the service and deploy. Both pairs work in the meantime.

Delete the old pair

Once every instance runs the new keys, delete the old pair's two keys. Anything still on them is refused from its next request.

If a key leaks

A leaked secret key can read and change every row, change the schema and rewind. Treat it as an incident.

Reset it

Reset the key in the dashboard. It stops working on its next request.

Put the new key where the old one was

Update .env.local, your host's environment variables and CI. Requests with the old key are refused until they have the new one.

Check what happened

Mantis records every write. Preview a rewind to the time the key leaked to see what has changed since, and apply it if the key was used against you.

A leaked publishable key is expected: every visitor to your site has it. What protects your data is the access rules. Reset it only if you want to cut off a copy of your app that uses it.

When a reset or delete takes effect

Every HTTP request looks its key up again, so the next request with a reset or deleted key is refused.

A live query checks its key when its connection opens. A connection that is already open keeps receiving updates until it closes, for example when the page is reloaded; it can't reconnect with the old key.

Keys and branches

Every key belongs to its project's main. There are no branch keys: any key can reach any branch by naming it, through Mantis-Branch, --branch, MANTIS_BRANCH or createClient({ branch }). A request for a branch that doesn't exist is refused with 404.

Keys and your agent

The MCP server and the CLI read MANTIS_SECRET_KEY from .env.local, then .env. The agent works with the secret key, so its queries skip the rules; a risky change on main still waits for a person in the dashboard.

init adds .env.local to .gitignore, and the instructions it writes for the agent tell it never to print or commit the key. If it ever does, reset the key.

Errors

The SDK throws a MantisError with the status and the message:

import { MantisError } from "@shipmantis/sdk";

try {
  await mantis.from("todos").select();
} catch (error) {
  if (error instanceof MantisError && error.status === 401) {
    // The key is missing, mistyped, reset or deleted.
  }
  throw error;
}
StatusMessageWhat to do
401Send a valid project key as Authorization: Bearer <key>.The key is missing, mistyped, reset or deleted. Copy the current one, or add a new pair.
403This needs the project's secret key, not the publishable one.Run that call on your server, with the secret key.
404There is no branch "…".Check the branch name with npx shipmantis branch list.
400Send one Mantis-Branch header.The request sent the header twice.

On this page