# Rystic on Vercel

Connect Rystic once through Vercel Connect, pull a 24-hour API key from your code, and run a metered simulator in a Vercel Sandbox.

Rystic is a service on [Vercel Connect](https://vercel.com/connect/browse). Connect it once, and your code gets a Rystic API key whenever it needs one: no key to paste into project settings, and none that outlives the work.

1. Your code asks Vercel Connect for a token with `getToken()`.
2. It calls Rystic's MCP endpoint, `https://www.rystic.ai/mcp/account`, with that token, and the `create_api_key` tool answers a `rys_…` key.
3. A [simulator](https://www.rystic.ai/docs/concepts/glossary.md#simulator) runs on the key as `RYSTIC_TOKEN`, typically in a Vercel Sandbox.

## Connect Rystic

In your Vercel team, open **Connect → Browse Connectors**, pick **Rystic**, and create the connector. Authorizing it signs you in to Rystic (a new account starts on Free), asks which Rystic organization to connect, and asks you to allow it to make API keys. Link the connector to the project that will call it.

Keys belong to the organization you pick, and its plan decides what they run. A user who has not accepted Rystic's current terms gets an error from `create_api_key` naming the page to accept them at, [www.rystic.ai/legal/accept](https://www.rystic.ai/legal/accept).

## Pull a key

The connector's token works only against `/mcp/account`; the key it pulls is what a simulator and the CLI take. Each call makes a new key.

```ts
import { getToken } from "@vercel/connect";

const token = await getToken("rystic", { subject: { type: "user", id: userId } });

const res = await fetch("https://www.rystic.ai/mcp/account", {
  method: "POST",
  headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "tools/call",
    params: { name: "create_api_key", arguments: {} },
  }),
});
const { result } = await res.json();
if (result.isError) throw new Error(result.content[0].text);
const { api_key, expires_at } = result.structuredContent;
```

`"rystic"` is the uid you gave the connector. `structuredContent` carries `api_key`, `prefix`, `org_id` and `expires_at`; the text content says the same for a model. Any MCP client works too: point it at `https://www.rystic.ai/mcp/account` with the token as a bearer. The endpoint also serves `search_rystic_docs` and `fetch_rystic_doc`.

## Run a simulator in a Vercel Sandbox

```ts
import { Sandbox } from "@vercel/sandbox";

const sandbox = await Sandbox.create({ ports: [8080] });
await sandbox.runCommand({
  cmd: "sh",
  args: [
    "-c",
    "curl -fsSL https://www.rystic.ai/install.sh | RYSTIC_BIN=$HOME/.local/bin sh && " +
      "$HOME/.local/bin/rystic run slack-twin -d --port 8080 --scenario design_studio",
  ],
  env: { RYSTIC_TOKEN: api_key },
});
const slackApi = sandbox.domain(8080); // point the Slack SDK here
```

The simulator checks in with `lease.rystic.ai` while it runs and counts toward your organization's simulator time, as on any machine: [What a running simulator sends](https://www.rystic.ai/docs/licensing.md#what-a-running-simulator-sends).

## How long a key lasts

A pulled key works for 24 hours, the length of the longest Vercel Sandbox session.

1. A simulator running on it stops at the first check-in after the 24 hours, with `This API key has expired.` Pull a new key and start it again.
2. The key shows on [Account → API keys](https://www.rystic.ai/account/api-keys) as **Vercel Connect** until it expires, and you can revoke it there sooner.
3. Removing the connector, or revoking its token in Vercel, stops new pulls. Keys already pulled keep working until their 24 hours are up.

---

Source: https://www.rystic.ai/docs/vercel · Markdown: https://www.rystic.ai/docs/vercel.md
