---
title: "Stream tokens"
description: "Let a script or an agent follow a project's live events, such as new revisions, comments and finished sessions, without a full sign-in."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.myspec.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Stream tokens

A **stream token** lets a client follow one project's events as they happen:
new spec file revisions, comments, sessions starting and finishing, and more.
The client needs nothing else to connect: no sign-in and no API token.

Use one when something should react to changes in MySpec, for example a coding
agent that waits for a session to finish, or a script that posts a message when
a spec file gets a new revision.

- A stream token can only **read** events. It cannot change anything in MySpec.
- It covers **one project** and only the event types you choose.
- It expires after 24 hours by default, and after 7 days at most.

## Create a stream token

Create one with the `create_stream_token` tool, from either
[MCP server](/mcp/). For example, ask your agent:

```text
Create a stream token that follows spec file and session events in my
"Checkout redesign" project for the next two hours.
```

The tool takes these arguments:

| Argument | Required | Meaning |
|---|---|---|
| `resource_type` | No | What to follow. `project` is the only option and the default. |
| `resource_id` | Yes | The project's id. |
| `event_types` | Yes | The [event types](#event-types) to receive, or `["*"]` for all of them. An empty list is refused. |
| `ttl_seconds` | No | How long the token lasts, in seconds. The default is 24 hours and the maximum is 7 days. A value outside the allowed range is adjusted rather than refused, so check `expires_at` in the result. |
| `label` | No | A short name, so people can recognize the token in a list. |

The result describes the token (`id`, `label`, project, event types,
`expires_at`) and contains **everything a client needs to connect**, with a note
on how to connect. Pass it straight to the client that will follow the events.

`["*"]` means every event type that exists when you create the token. Event
types added to MySpec later are not added to existing tokens.

Who can create one:

- Any member who can see the project.
- A **Read only** API token can create stream tokens, because a stream token
  only reads.
- On the remote server, a connector (such as Claude or ChatGPT) connected
  without write access is asked to reconnect with write access first.

You can only have a limited number of stream tokens per person and per project,
and creating them is rate limited. Revoke the ones you no longer need.

> **Treat the connection details like a password**
>
> Anyone who has them can read the project's events until the token expires,
> without signing in. They are shown **once** and cannot be retrieved later.
> Never paste them into a chat, a file, a commit, an issue or a log. If they may
> have leaked, [revoke the token](#revoke-a-stream-token) at once.

## Event types

| Event type | Sent when |
|---|---|
| `project.updated` | The project's name, description, type or status changes, including archive and unarchive. |
| `project.deleted` | The project is deleted. This ends the token, so it is the last event it sends. |
| `spec_file.created` | A spec file is added. |
| `spec_file.updated` | A file gets a new revision, an older revision is restored, or the file is moved to or restored from the Trash Bin. |
| `spec_file.deleted` | A file is deleted permanently. |
| `spec_file.lock` | Someone starts, renews, releases or takes over editing a file. |
| `spec_file_comment.created` | Someone starts a comment thread or replies to one. |
| `spec_file_comment.updated` | A comment is edited or deleted. |
| `spec_file_comment.thread_state_changed` | A thread is resolved or reopened. |
| `spec_file_comment.anchors_updated` | Comment threads move to follow changed text, after a save or after someone re-attaches a thread. One event covers every thread that one save moved. |
| `attachment.created` | An attachment is uploaded. |
| `attachment.deleted` | An attachment is removed. |
| `spec_session.created` | A session starts. |
| `spec_session.updated` | A session is completed, archived, unarchived or renamed, or its status changes. |
| `spec_session.deleted` | A session is deleted. |
| `*` | All of the above. |

Events say what happened, not the full content. They never include the text of
comments, and new chat messages in a session are not sent as events. To get the
details, read the project, file or session with the other
[MCP tools](/mcp/tools/).

## What a client receives

Each message is one line of JSON text:

- **First**, a message that confirms what the token covers: the project, the
  event types and the expiry. Check it to be sure you connected to the right
  feed.
- **Then one message per event**, with its type, its time, the project, a
  sequence number (`seq`) and the event's details.
- **About a minute before the token expires**, a warning, so the client can
  create a new token in time instead of mistaking the end for a network problem.
- **Before the server ends a connection**, an error message with a reason, such
  as an expired or revoked token.

A new connection receives only events that happen from then on. Every event
carries a sequence number, so a client that reconnects can ask for everything
after the last event it saw and miss nothing. The note in the
`create_stream_token` result explains how. Events are kept only for as long as
the token lives.

## Handle closed connections

When the server closes a connection, the close code tells the client what to do:

| Close code | Meaning | What to do |
|---|---|---|
| `4001` | The token no longer works: it is unknown, expired or revoked, or its project was deleted. The error message before the close says which. | Stop, or create a new token. |
| `4008` | The connection could not keep up and was dropped. | Reconnect, resuming after the last event you saw. |
| `4009` | The token already has as many open connections as it allows. | Wait for another connection to close. The token is still good. |
| `1013` | The feed is unavailable for a moment. | Wait a little, then retry with the same token. |

## List stream tokens

`list_stream_tokens` lists the stream tokens in your organization: label,
project, event types, who created it, when it expires, whether it still works,
how many times it was used and when it was last connected. It never shows the
secret, only a short prefix to tell tokens apart.

| Argument | Meaning |
|---|---|
| `resource_id` | Only tokens for this project. |
| `live_only` | Hide expired and revoked tokens. |
| `mine_only` | Only tokens you created. Off by default, so you can find any token in your organization. |
| `limit`, `offset` | Paging. The default page size is 50 and the maximum is 200. |

## Revoke a stream token

`revoke_stream_token` takes the token's `id` from the create result or from
`list_stream_tokens`, never the secret. Revoking takes effect at once: open
connections are closed and the events kept for the token are deleted. A revoked
token cannot be turned back on.

- You can always revoke a token you created.
- To revoke a token someone else created, you need the **Owner** or **Admin**
  role in the organization. Otherwise, ask an owner or admin.
- A stream token cannot be extended. When it expires, create a new one.

> **Revoking an API token does not revoke its stream tokens**
>
> A stream token created through an API token keeps working until it expires,
> even after you revoke that API token. If an API token leaks, also list your
> stream tokens and revoke the ones it created.

Source: https://docs.myspec.dev/mcp/stream-tokens/index.mdx
