Every request carries an API key as a bearer token in the Authorization header. The key is a
machine credential: it belongs to your organization, and no person signs in to use it.
API keys
curl -sS https://api.versionstory.com/v1/compare \
-H "Authorization: Bearer vs_live_..." \
-F "original=@v1.docx" \
-F "modified=@v2.docx"Getting a key
Keys are created in the Version Story web app, on the Developer page (the terminal icon in the sidebar, or app.versionstory.com/developer), under API keys. Issuing or revoking one requires the Developer permission on the organization.
- Signing up gives you access. Create an account and you own a new organization with the Developer permission, so the page is there straight away. New organizations start on an API trial.
- In an existing organization, a member who manages members can grant you the Developer permission from your entry in the organization's member settings.

The Developer page's other tabs are useful alongside the keys: Overview charts API activity and success rate and holds the zero-day retention setting, and Repository shows every document and redline the API has created.
Give the key a name that says what it serves — "Contract intake integration" reads better than "key 2" when someone audits the list a year later. The token is shown once, on creation, in a banner with a copy button. Store it before you dismiss the banner.
Getting a key from a coding agent
A coding agent setting up an integration (Claude Code, Codex, Cursor and the like) can get its own key, with one click from you and no copying. It opens Version Story in your browser, you sign in or register and click Allow, and the agent receives a new key and stores it where your secrets live. Quickstart with a coding agent is a prompt that has an agent do it, with the script it runs. Under the hood it is the OAuth authorization code flow with PKCE, for a native app on a loopback address (RFC 8252):
- The agent makes a PKCE pair (a random
code_verifierand its S256code_challenge) and a randomstate, and listens for one request athttp://127.0.0.1:<port>/callback. - It opens
https://app.versionstory.com/developer/authorizewith the queryclient_name, which becomes the key's name,redirect_uri,code_challenge,code_challenge_method=S256andstate. - You sign in or register, and allow the request for your organization. Allowing it needs the Developer permission, as creating a key on the Developer page does.
- The browser brings a one-time
codeback to the agent's listener, and the agent redeems it within five minutes:
curl -sS https://api.versionstory.com/v1/api-keys \
-H "Content-Type: application/json" \
-d '{"code": "...", "code_verifier": "...", "redirect_uri": "http://127.0.0.1:53682/callback"}'{
"api_key": "vs_live_...",
"name": "Claude Code on dana-laptop",
"organization_id": "...",
"organization_name": "Reyes LLP"
}POST /v1/api-keys is the one call that takes no key. The redirect_uri must be exactly
http://127.0.0.1:<port>/callback (or [::1]), with no query, and the same value the authorize
page was given; a code is redeemed once. A code that is unknown, expired, already used, or
sent with the wrong verifier or redirect is 400 INVALID_AUTHORIZATION_CODE.
The person who allowed the request is emailed that a key was created with their account, and the key list marks the key Created by sign-in, so a key allowed by mistake is easy to spot and revoke.
What a key is
A key looks like vs_live_{id}_{secret}, for example vs_live_9f3c…_R7x…, and works with
https://api.versionstory.com.
A key belongs to the organization, not to the person who created it, so it keeps
working when that person changes roles or leaves. Requests authenticate as the
organization's service account: a machine identity that exists only to carry API work and
has no sign-in of its own. That account is what every API-created comparison is attributed
to and metered against. The member who issued the key is recorded as created_by_email, as
an audit trail and nothing more.
Handling a key
- The secret is shown once, at minting, and is never recoverable. Version Story stores only a SHA-256 hash of it. If you lose the key, you get a new one; nobody can read the old one back to you.
- Treat it like a password. Keep it in a secrets manager or an environment variable, never in source control, and never in client-side code — a key in a browser bundle is a key the whole internet has.
- An organization can hold several keys at once, and each one can be revoked on its own. Revocation takes effect on the next request. Rotate in this order: create the new key, deploy it, then revoke the old one. The other order leaves a window with no valid credential.
- The key list shows each key's name, when it was created, and when it was last used, and marks revoked keys — enough to tell a live integration from one you can safely retire. Hover a key's Created date to see who issued it.
Auth failures
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_AUTHORIZATION_CODE | POST /v1/api-keys only: the code is unknown, expired or used, or its verifier or redirect does not match |
| 401 | INVALID_API_KEY | Missing, malformed, unknown, revoked, or expired key |
| 403 | API_KEY_ORG_MISMATCH | The key's service account is no longer operating in the key's organization |
API_KEY_ORG_MISMATCH is deliberately loud rather than silent: honoring a request whose
principal has drifted would attribute and bill the work to the wrong organization. Because
a key's service account is derived from the organization itself, you should never see this
in practice. If you do, issue a new key and revoke the old one.