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

# Plainrouter authentication: API secrets and MCP tokens

> Choose the correct Plainrouter credential and authenticate REST, TypeScript, Python, Ruby, Go, CLI, MCP, or management-discovery requests.

Plainrouter uses a per-workspace Signals secret for the Signals Conversion API, an
account-bound workspace execution token for production MCP tool calls, and a
narrowly scoped OAuth management credential for account discovery. Public MCP
discovery and the synthetic MCP sandbox require no credential.

REST, TypeScript, Python, Ruby, Go, and the CLI are six interfaces to the same
Conversion API and all use the same Signals workspace secret.

## Which credential should I use?

| Goal                                                   | Interface                                                  | Credential                                | Scope                                                                  |
| ------------------------------------------------------ | ---------------------------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------- |
| Send or read Signal data                               | REST, TypeScript SDK, Python SDK, Ruby SDK, Go SDK, or CLI | Signals workspace secret                  | One workspace and its Signals resources                                |
| Test an MCP integration with synthetic data            | `https://plainrouter.com/mcp/sandbox`                      | None                                      | Four sandbox-only tools; no tenant data or provider access             |
| Call Plainrouter tools as an agent                     | MCP or an authorized workspace route                       | Workspace execution token                 | One workspace, one Meta ad account, and one Read, Write, or Admin tier |
| Discover the approved agent context                    | `GET /api/v1/agent/context`                                | OAuth management credential               | Read-only account discovery                                            |
| Manage tokens, policies, or approvals in the dashboard | Browser session                                            | Signed-in person's current workspace role | Interactive UI only                                                    |

These credentials are not interchangeable. The Conversion API rejects workspace
execution tokens and OAuth management credentials. MCP rejects Signals workspace
secrets and OAuth management credentials.

<Warning>
  Never paste any Plainrouter credential into an agent prompt. Inject credentials
  through your server-side secret manager or the client's protected credential
  configuration.
</Warning>

## How do I authenticate the REST API?

Send the Signals workspace secret as a bearer token to the server-side Conversion
API at `https://plainrouter.com/api/v1`:

```bash theme={null}
curl "https://plainrouter.com/api/v1/dashboard/events" \
  --header "Authorization: Bearer $PLAINROUTER_TOKEN" \
  --header "Accept: application/json"
```

`PLAINROUTER_TOKEN` must contain the Signals workspace secret. A missing or
invalid secret returns HTTP `401`.

## How do I authenticate the TypeScript SDK?

Install `@plainrouter/sdk@0.5.1`, then configure the generated client explicitly:

```ts theme={null}
import {
  configurePlainrouter,
  listEvents,
} from "@plainrouter/sdk";

configurePlainrouter({
  signalTrackerSecret: process.env.PLAINROUTER_TOKEN!,
});

const result = await listEvents({
  query: { per_page: 25 },
});
```

The TypeScript SDK does not read environment variables automatically. Your
server must pass the Signals workspace secret through `signalTrackerSecret`.
The property keeps its pre-collapse name for compatibility.

## How do I authenticate the Python SDK?

Install [`plainrouter==0.5.2`](https://pypi.org/project/plainrouter/), then create a client with the Signals workspace secret:

```python theme={null}
import os

from plainrouter import create_client, list_events

client = create_client(os.environ["PLAINROUTER_TOKEN"])
response = list_events.sync(client=client)
```

The Python SDK requires Python 3.11 or newer. Each operation module also exposes
an asynchronous `asyncio` method.

## How do I authenticate the Ruby SDK?

Install [`plainrouter-sdk 0.1.1`](https://rubygems.org/gems/plainrouter-sdk), then create a client with the Signals workspace secret:

```ruby theme={null}
require "plainrouter"

client = PlainRouter::Client.new(
  token: ENV.fetch("PLAINROUTER_TOKEN")
)

events = client.operations.list_events(per_page: 25)
```

The Ruby SDK requires Ruby 3.2 or newer. The client sends the supplied tracker
secret as a bearer token and does not read environment variables automatically.

## How do I authenticate the Go SDK?

Install `github.com/plainrouter/sdk-go@v0.5.2`, create the generated client, and attach the Signals workspace secret to the request context:

```go theme={null}
config := plainrouter.NewConfiguration()
client := plainrouter.NewAPIClient(config)
ctx := context.WithValue(
	context.Background(),
	plainrouter.ContextAccessToken,
	os.Getenv("PLAINROUTER_TOKEN"),
)

report, _, err := client.OperationsAPI.GetEmqReport(ctx).Execute()
```

The Go SDK requires Go 1.23 or newer. Keep the Signals workspace secret in server-side credential storage.

## How do I authenticate the CLI?

The CLI uses the same Signals workspace secret. Current `0.5.x` builds call it a
tracker token in prompts for compatibility. Store it through the hidden login
prompt for an interactive workstation:

```bash theme={null}
plainrouter auth login
plainrouter auth status
plainrouter events list --json
```

For CI or an ephemeral shell, inject `PLAINROUTER_TOKEN` through the job's secret
manager before running the command. The CLI does not expose a `--token` option.
An environment token takes precedence over the locally stored token.

## How do I try MCP without a credential?

Connect an MCP client to the synthetic test endpoint:

```text theme={null}
https://plainrouter.com/mcp/sandbox
```

It exposes `get_account_state`, `get_signal_health`, `get_performance`, and
`validate_sandbox_event`. Every response is synthetic and marked with
`"sandbox": true`. The endpoint reads no tenant data, persists nothing, and
contacts no advertising provider.

The production endpoint also permits anonymous protocol discovery, tool and
resource listing, and reads of static `ui://` app shells. Every production tool
call and every account-data read still requires an account-bound workspace
execution token.

## How do I authenticate Plainrouter MCP?

Configure an MCP-compatible client with these exact connection values:

| Setting       | Value                                |
| ------------- | ------------------------------------ |
| Transport     | Remote HTTP                          |
| Server URL    | `https://plainrouter.com/mcp`        |
| Authorization | `Bearer <workspace-execution-token>` |

A workspace owner issues the token from **API** in the dashboard for one workspace,
one active Meta ad account, one Read, Write, or Admin tier, and a 30, 90, or 365
day expiry.

Call `get_account_state` first. Confirm the returned workspace and Meta ad
account before calling another tool. Tool arguments cannot override the account
stored with the token.

<Warning>
  A Write or Admin token can submit governed proposals, but it does not bypass
  policy, human approval, provider verification, or account restrictions. A
  proposal-producing MCP request is not a direct Meta write.
</Warning>

## How do I use an OAuth management credential?

An OAuth management credential has one documented agent-facing use:

```http theme={null}
GET /api/v1/agent/context HTTP/1.1
Host: plainrouter.com
Authorization: Bearer <oauth-management-credential>
Accept: application/json
```

The route returns the approved read-only account-discovery context. The same
credential cannot call MCP tools, Launcher imports, or other agent-authenticated
routes. Use a separately issued workspace execution token for MCP after
discovery.

## Why does a dashboard URL reject my bearer token?

Dashboard settings and approval pages require a signed-in browser session. A valid workspace execution token or OAuth management credential cannot replace that session, even with an active grant or Admin tier.

If an automation receives `401` on a dashboard URL, check the requested interface before rotating credentials. Use the documented MCP or API operation with its matching credential, or sign in to complete the interactive action. For grant management, follow [the dashboard revocation steps](/docs/mcp/workspace-tokens#inspect-and-revoke-a-grant-in-the-dashboard) or the separately authorized [`revoke_grant` MCP tool](/docs/mcp/tools#revoke_grant).

## Which clients are available?

| Client                              | Package or endpoint                                                 | Current version           | Authentication                                                    |
| ----------------------------------- | ------------------------------------------------------------------- | ------------------------- | ----------------------------------------------------------------- |
| REST                                | `https://plainrouter.com/api/v1`                                    | Signed OpenAPI `0.5.0`    | Signals workspace secret                                          |
| [TypeScript setup](/docs/sdk/typescript) | `@plainrouter/sdk`                                                  | `0.5.1`                   | Signals workspace secret passed through `signalTrackerSecret`     |
| [Python setup](/docs/sdk/python)         | `plainrouter`                                                       | `0.5.2`                   | Signals workspace secret passed to `create_client`                |
| [Ruby setup](/docs/sdk/ruby)             | `plainrouter-sdk`                                                   | `0.1.1`                   | Signals workspace secret passed to `PlainRouter::Client.new`      |
| [Go setup](/docs/sdk/go)                 | `github.com/plainrouter/sdk-go`                                     | `v0.5.2`                  | Signals workspace secret attached to the request context          |
| [CLI setup](/docs/cli/get-started)       | `plainrouter`, `@plainrouter/cli`, or `plainrouter/tap/plainrouter` | PyPI `0.5.2`; npm `0.5.1` | Stored compatibility-labeled tracker token or `PLAINROUTER_TOKEN` |
| MCP sandbox                         | `https://plainrouter.com/mcp/sandbox`                               | Server `0.3.2`            | None                                                              |
| MCP production                      | `https://plainrouter.com/mcp`                                       | Server `0.3.2`            | Workspace execution token for tool calls and account data         |

The REST contract and all four SDKs expose the signed Conversion API operations. The
PyPI and npm CLI distributions expose nine commands and do not include an ingestion-verification
command. Use REST, an SDK, or MCP for ingestion verification.

## Which credentials must not be confused?

* A Signals workspace secret cannot authenticate MCP.
* A workspace execution token cannot authenticate the Conversion API.
* An OAuth management credential cannot authenticate MCP.
* A browser session cannot replace an API or MCP bearer credential.
* A same-origin Path B forwarding secret authenticates generated forwarding
  infrastructure only. It is not an API, SDK, CLI, or MCP credential.
* Meta access tokens remain on the Plainrouter server. Do not place a Meta token
  in a Plainrouter client configuration.

For complete request and response fields, use the [Conversion API
reference](/docs/api/conversions). For token tiers and lifecycle, use
[Workspace tokens](/docs/mcp/workspace-tokens). For available agent tools, use
the [MCP tool reference](/docs/mcp/tools). For machine discovery, start
with the [API resource index](/docs/api/resources) or the [RFC 9727
API catalog](/docs/api/catalog).
