> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended**:
> ```bash
> npx @scalekit-inc/cli setup
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Mint a session token for a connection

`POST /api/v1/mcp/connections/{key_id}/tokens`

Mints a short-lived token for one user that an MCP client sends to one connection's MCP server, at `<environment URL>/mcp/v3/connections/{key_id}`, without a Virtual MCP server. The token's `sub` claim is the identifier and its `aud` claim is that server URL, so the token works only there. Use it when an agent needs the tools of exactly one connection.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `key_id` | string | Yes | The connection name, as shown in AgentKit > Connections. It's also the last path segment of the connection's MCP server URL. |

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | string | Yes | Your app's ID for the user, the same value you used when the user connected. |
| `expiry` | string | No | How long the token lasts, in seconds with an `s` suffix, such as `1800s`. Between `60s` and `86400s` (24 hours). Defaults to `3600s`. |

**Response (200)**

| Name | Type | Description |
| --- | --- | --- |
| `expires_at` | string | When the token expires: the time it was minted plus `expiry`. |
| `token` | string | The session token, a signed JWT. Its `sub` claim is the identifier and its `aud` claim is the MCP server URL it works at. Send it as `Authorization: Bearer <token>` from the MCP client. |

**Errors**

- `400`: Invalid request - `key_id` or `identifier` is missing or malformed, `expiry` is outside the 60s-24h window, or the connection isn't an AgentKit connection. When the user has no active account on the connection yet, Scalekit creates a pending one and still returns a token, so the user can authorize from the MCP client.
- `404`: Not found - no active connection with this name exists in the environment.

**Request**

```bash
curl -sS -X POST \
  "$SCALEKIT_ENVIRONMENT_URL/api/v1/mcp/connections/gmail/tokens" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "identifier": "user_123",
    "expiry": "1800s"
  }'
```

**Response**

```json
{
  "token": "[SESSION TOKEN]",
  "expires_at": "2026-10-02T15:00:00Z"
}
```

**Python:** Call this endpoint over REST, as the example shows.

```python
import os

import requests

env_url = os.environ["SCALEKIT_ENVIRONMENT_URL"]
token = requests.post(
    f"{env_url}/oauth/token",
    data={
        "grant_type": "client_credentials",
        "client_id": os.environ["SCALEKIT_CLIENT_ID"],
        "client_secret": os.environ["SCALEKIT_CLIENT_SECRET"],
    },
).json()["access_token"]

response = requests.post(
    f"{env_url}/api/v1/mcp/connections/gmail/tokens",
    headers={"Authorization": f"Bearer {token}"},
    json={"identifier": "user_123", "expiry": "1800s"},
)
response.raise_for_status()
result = response.json()
```

**Node.js:** Call this endpoint over REST, as the example shows.

```ts
const envUrl = process.env.SCALEKIT_ENVIRONMENT_URL!;
const tokenResponse = await fetch(`${envUrl}/oauth/token`, {
  method: "POST",
  body: new URLSearchParams({
    grant_type: "client_credentials",
    client_id: process.env.SCALEKIT_CLIENT_ID!,
    client_secret: process.env.SCALEKIT_CLIENT_SECRET!,
  }),
});
const token = (await tokenResponse.json()).access_token;

const response = await fetch(`${envUrl}/api/v1/mcp/connections/gmail/tokens`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ identifier: "user_123", expiry: "1800s" }),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const result = await response.json();
```


Part of [Virtual MCP servers](https://docs.scalekit.com/agentkit/reference/virtual-mcp-servers/) in the [AgentKit API reference](https://docs.scalekit.com/agentkit/reference/). Authentication: https://docs.scalekit.com/agentkit/reference/authentication.md. Errors and rate limits: https://docs.scalekit.com/agentkit/reference/errors.md. Pagination: https://docs.scalekit.com/agentkit/reference/pagination.md


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
