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

# Choosing a board

> A Tylon credential can reach several boards. The X-Tylon-Workspace header says which one a call is about, by workspace id.

A credential reaches the boards it was ticked for — one or several. Every call except `/v1/me` is about exactly one of them, and says which in a header.

```bash theme={null}
curl https://api.tylon.app/v1/board \
  -H "Authorization: Bearer $TYLON_SECRET" \
  -H "X-Tylon-Workspace: 84415731592203229"
```

## Why a header, and why an id

**A header** because it belongs with the credential rather than with the request. The same value goes on every call your integration makes, and something that never varies has no business in a URL that does — it also keeps it out of the logs and browser histories that record paths.

**An id** because a name is a thing somebody renames on a Tuesday, and a slug is a thing two organizations can share. Either one can turn a working integration into a silent one — or, worse, into one now reading a different board. An id cannot come to mean something else.

<Note>
  The [MCP server](/mcp/connect) does accept `acme/product`, and that is not an inconsistency. There a person is typing it and a model is reading the refusal. Here nobody is typing anything.
</Note>

## Finding the ids

`/v1/me` is the listing, and the one call that never asks you to choose.

```bash theme={null}
curl https://api.tylon.app/v1/me -H "Authorization: Bearer $TYLON_SECRET"
```

```json theme={null}
{
  "clientId": "tyl_id_1yIrdcxW_gkz8XBY",
  "name": "the deploy script",
  "scopes": ["read"],
  "boards": [
    {
      "workspaceId": "84415731592203229",
      "organizationId": "84415731491539931",
      "role": "viewer"
    },
    {
      "workspaceId": "83729280714017040",
      "organizationId": "81904798345068545",
      "role": "member"
    }
  ],
  "answering": null
}
```

`boards` is exactly the set of ids the header will accept. `answering` is which board served the call — always `null` here, because this route answers with the list rather than out of it.

## When you can leave it out

When the credential reaches exactly one board. Then there is no question to ask, and the header is optional.

Leave it out with several and you get `400` with the ids:

```json theme={null}
{
  "message": "Say which workspace in the X-Tylon-Workspace header: 84415731592203229, 83729280714017040.",
  "error": "Bad Request",
  "statusCode": 400
}
```

## The refusals

<ResponseField name="A name instead of an id" type="400">
  ```json theme={null}
  { "message": "X-Tylon-Workspace takes a workspace id, not a name. This credential reaches 84415731592203229, 83729280714017040." }
  ```

  Said plainly rather than answered as "no such board", so a slug pasted in by habit does not read as a board that has gone missing.
</ResponseField>

<ResponseField name="An id this credential does not reach" type="400">
  ```json theme={null}
  { "message": "This credential does not reach workspace 12345678901234567. It reaches 84415731592203229, 83729280714017040." }
  ```
</ResponseField>

## Boards do not leak into each other

A `projectId` belonging to another board is `404`, even when that board is one the same credential reaches. Card numbers are per board: `/v1/cards/7` answers with card #7 of the board in your header, and never with another board's.
