Token Vault
Getting Started

Quickstart: First Credential in ~10 Minutes

Deploy the reference webhook to Cloudflare Workers, bind it to Token Vault, and have an AI agent fetch its first credential — copy-paste steps, honest prerequisites.

By the end of this page an AI agent will fetch a real credential from your own vault with one curl. Honest scope up front: Token Vault is webhook-sovereign — your credentials live on a small server you deploy, so step 1 is deploying one. With a free Cloudflare account the whole path takes about ten minutes.

Prerequisites: a Cloudflare account (free tier is fine), Node.js 18+, and a Google account for Token Vault sign-in.

Deploy your webhook (Cloudflare Workers)

The reference webhook is TypeScript, runs on the Workers free tier, stores credentials in an auto-provisioned D1 database, and encrypts at rest with a key derived from one seed secret that never leaves your account.

Terminal
git clone https://github.com/c-lgrant/tvault.git
cd tvault/examples/webhook
npm install

# Authenticate wrangler with your Cloudflare account (opens browser)
npx wrangler login

# Generate the root seed — an encrypted, write-only Workers Secret.
# Your AES key and HMAC secret are derived from it; Token Vault never has it.
openssl rand -hex 32 | npx wrangler secret put TV_WEBHOOK_SEED

# Deploy. The D1 database is auto-provisioned on first run.
npm run deploy

The deploy finishes with your webhook URL: https://<name>.<account>.workers.dev.

Prefer local-only for a first look?

The same repo runs locally with Docker + a tunnel — see Deploy Your Own Webhook Locally with ngrok. Cloudflare is the recommended path: no machine to keep online, and it's the same setup you'd run in production.

Bind the webhook to Token Vault

Binding is a one-time automatic handshake — you never copy an HMAC secret by hand.

  1. Open https://<your-worker>.workers.dev/bind in a browser.
  2. Click Connect to TokenVault. You're redirected to Token Vault (sign in with Google if prompted) with a one-time code.
  3. Review the webhook URL and click Connect. Token Vault exchanges the code at your webhook's /v1/exchange endpoint and receives the HMAC secret directly from the webhook.

Your vault is now live, and Token Vault holds only its URL and the shared HMAC secret — no credentials, no encryption key.

Store a credential

In the dashboard, open Tokens → Add Custom Token. Paste any API key you want an agent to use — a GitHub personal access token is a good first test. Name the service github.

The browser sends the credential directly to your webhook with a signed store ticket; it never passes through Token Vault.

Give an agent access

  1. Open Agents → New Agent, name it (e.g. quickstart-test), and copy the tvagent_… API key — it's shown once.
  2. On the agent's page, grant it the github token with an expiry (1 hour is fine for a test).

Fetch the credential

Terminal
curl -sL "https://api.tokenvault.uk/api/agents/credentials?service=github" \
  -H "Authorization: Bearer tvagent_YOUR_KEY"
Response — served by YOUR webhook, not Token Vault
{
  "token": {
    "accessToken": "ghp_…",
    "serviceName": "github",
    "tokenType": "pat",
    "createdAt": "2026-07-14T10:00:00Z"
  }
}

The -L matters: Token Vault validates the agent's key and policies, then answers with a 307 redirect to your webhook, which serves the credential straight to the agent. Token Vault's involvement ends at the redirect — it never sees the token.

Using an MCP client instead?

Claude Code, Cursor, and any MCP client can skip the static key entirely: claude mcp add --transport http token-vault https://api.tokenvault.uk/api/agents/mcp, then authenticate in-client via OAuth 2.1. See OAuth 2.1 for MCP Clients.

What you just built

Loading diagram...

Storing works the same way in reverse: when you added the credential in step 3, the browser sent it straight to your Worker with a signed ticket. Token Vault has never held it at any point.

Where to go next

Create an MCP proxy → — point Cursor or Claude at a proxy URL and let your webhook inject credentials server-side, so the agent never holds a key at all.

Also worth reading: how the architecture works, access policies (time windows, IP allowlists, manual approval), and the webhook protocol if you'd rather implement your own webhook than run the reference.

On this page