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

# Workspaces API — Create Workspaces and Their Keys

> List the workspaces you belong to, create a new one with POST /v1/workspaces (it comes with its primary key), list, create and revoke its workspace keys, and link or unlink your reserve card per workspace — all with an account key (ps_account_). Covers the per-user ceiling, how reseller workspaces are born on Pay As You Go and shareCard.

# Workspaces API

These endpoints work at the level of **your user**, not of one workspace. They answer **only to an [account key](https://docs.pilotstatus.com.br/api/key-types.md#account-keys)** (`ps_account_`, created in **Profile → API**).

| Method | Endpoint | What it does |
| - | - | - |
| `GET` | `/v1/workspaces` | The workspaces you are an active member of, with your role in each. |
| `POST` | `/v1/workspaces` | Creates a workspace that you own, with its primary key. |
| `GET` | `/v1/workspaces/{workspaceId}/api-keys` | The workspace's keys (primary and named), masked. |
| `POST` | `/v1/workspaces/{workspaceId}/api-keys` | Creates a named workspace key. |
| `DELETE` | `/v1/workspaces/{workspaceId}/api-keys/{keyId}` | Revokes a named workspace key. |
| `PUT` | `/v1/workspaces/{workspaceId}/shared-card` | Links your reserve card (shared card) to the workspace. |
| `DELETE` | `/v1/workspaces/{workspaceId}/shared-card` | Unlinks your reserve card from the workspace. |

> [!NOTE]
>
> **Only account keys.** A workspace key, a number key or an OAuth/MCP token gets **403 `ACCOUNT_KEY_REQUIRED`**. OAuth/MCP tokens are refused on purpose: these endpoints mint keys, and a key minted through a connector would keep working after the connector is revoked. `x-workspace-id` is ignored here: the workspace, when there is one, is in the path.

Every response is sent with `Cache-Control: no-store`. Errors are `{ "error": "English | Português", "code": "…" }`.

## List your workspaces

`GET https://pilotstatus.com.br/v1/workspaces`

```bash theme={null}
curl "https://pilotstatus.com.br/v1/workspaces" \
  -H "x-api-key: ps_account_your_account_key"
```

```json Response (200) theme={null}
{
  "data": [
    {
      "id": "cmh2a1b2c0001ws8example7k",
      "name": "Acme Resale",
      "role": "OWNER",
      "plan": "PAY_AS_YOU_GO",
      "createdAt": "2026-03-02T12:00:00.000Z",
      "sharedCard": { "linked": false, "sourceWorkspaceId": null }
    },
    {
      "id": "cmh2a9z8y0002ws8example1q",
      "name": "Bakery Downtown",
      "role": "OWNER",
      "plan": "PAY_AS_YOU_GO",
      "createdAt": "2026-10-28T09:15:00.000Z",
      "sharedCard": { "linked": true, "sourceWorkspaceId": "cmh2a1b2c0001ws8example7k" }
    }
  ]
}
```

* **Only workspaces where your membership is active.** Archived workspaces are left out.
* `role` is your role in that workspace: `OWNER`, `ADMIN`, `AGENT` or `ANALYST`.
* `plan` is the workspace's current plan (`FREE`, `PAY_AS_YOU_GO`, `ON_DEMAND`, …).
* `sharedCard` says whether the workspace is linked to a shared card: `linked` and, when linked, the `sourceWorkspaceId` whose card backs it (`null` when not linked). See [Shared card per workspace](#shared-card-per-workspace).
* Use the `id` in `x-workspace-id` to act inside that workspace with the same account key.

## Create a workspace

`POST https://pilotstatus.com.br/v1/workspaces` with `{ "name": "…" }` and, optionally, `"shareCard": true`. You become the workspace's **Owner**, and the response carries its **primary key**, shown **this one time only**.

**name** `string` *required*

1 to 60 characters, after trimming spaces.

**shareCard** `boolean`

`true` links the new workspace to **your reserve card** (the [shared card](#shared-card-per-workspace)), so it backs this customer's renewals. `false` or **absent**: the workspace is **not** shared. Must be a JSON boolean: `"true"`, `1` or `null` get **400 `INVALID_SHARE_CARD`**.

`name` and `shareCard` are the only fields accepted. Any other field gets **400 `UNKNOWN_FIELDS`**.

> [!WARNING]
>
> **Behavior change (2026-10-29): the reserve card is no longer shared automatically.** Before, a workspace a reseller created through `POST /v1/workspaces` inherited the reserve card on its own. Now it is shared **only when you send `"shareCard": true`**. If your integration counted on the old behavior, add the field, or link existing workspaces with [`PUT …/shared-card`](#link-the-shared-card).

```bash cURL theme={null}
curl -X POST "https://pilotstatus.com.br/v1/workspaces" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ps_account_your_account_key" \
  -d '{ "name": "Bakery Downtown", "shareCard": true }'
```

```json Response (201) theme={null}
{
  "id": "cmh2a9z8y0002ws8example1q",
  "name": "Bakery Downtown",
  "plan": "PAY_AS_YOU_GO",
  "createdAt": "2026-10-28T09:15:00.000Z",
  "role": "OWNER",
  "apiKey": {
    "id": "cmh2aa0010003ak8example4d",
    "name": "Workspace API Key",
    "key": "ps_workspace_9f3c1a7e5b2d8f4a6c0e9b1d7f3a5c8e2b4d6f8a0c1e3b5d",
    "prefix": "ps_workspace_",
    "last4": "3b5d",
    "isPrimary": true,
    "createdAt": "2026-10-28T09:15:00.000Z"
  },
  "sharedCard": { "linked": true, "sourceWorkspaceId": "cmh2a1b2c0001ws8example7k" }
}
```

* **`apiKey.key` comes only in this response.** Store it before doing anything else. Later reads show only `prefix` and `last4`.
* **`apiKey` can be `null`.** The workspace is saved first and the key is minted next. If minting fails, the answer is still `201`, so that a retry does not create a second workspace. Rotate the primary key with `POST /v1/api-keys/regenerate` (account key plus `x-workspace-id`, Owner role), or create a named key with [`POST /v1/workspaces/{id}/api-keys`](#create-a-named-key).
* **Creating is not idempotent.** Two `POST`s create two workspaces. After a timeout, check `GET /v1/workspaces` before trying again.
* **`sharedCard`** tells you how the workspace was born: `{ "linked": false, "sourceWorkspaceId": null }` without `shareCard: true`.
* **With `shareCard: true`, the card is checked before anything is created.** No reserve card configured for you (**409 `SHARED_CARD_NOT_CONFIGURED`**), the source workspace archived (**409 `SOURCE_ARCHIVED`**) or you no longer an active Owner of it (**409 `NO_SHARED_OWNER`**): **no workspace is created**, so retrying without `shareCard` is safe.

### How the new workspace is born

| You are | Plan | Prices | Card |
| - | - | - | - |
| A regular user | **Free** | The standard ones | None |
| A **reseller** (marked by the Pilot Status team) | **Pay As You Go**, billed from the wallet | **Your reseller prices**: the per-number price and the phone line price agreed with you | **None**, unless you send `shareCard: true` — then **your reserve card** (shared card) |

Reseller workspaces start with nothing charged: no plan fee, no numbers and no balance. The first charge is the first number that connects, or the first line you buy. The **shared card** is a backup: it pays a charge only when the workspace's wallet does not cover it **and** the workspace has no card of its own. See [Billing for resellers](https://docs.pilotstatus.com.br/reseller-billing.md#shared-card).

> [!NOTE]
>
> The reseller mark and the reseller prices are set by the **Pilot Status team**, not through the API. The team also configures **which of your workspaces holds your reserve card** — that is what allows you to share it. Which customer workspaces use it is **your** decision, per workspace: `shareCard` on creation, or [`PUT`/`DELETE …/shared-card`](#shared-card-per-workspace) afterwards. Talk to us to set them up. They apply to workspaces created from then on; workspaces you already had keep their plan.

### How many workspaces you can own

Each user can own up to **10 workspaces** by default, counting every workspace where you are the active Owner, your first one included. Over the limit, the answer is **409 `WORKSPACE_LIMIT_REACHED`**, with the limit in `limit`:

```json Response (409) theme={null}
{
  "error": "You already own 10 workspaces, which is the limit | Você já é dono de 10 workspaces, que é o limite",
  "code": "WORKSPACE_LIMIT_REACHED",
  "limit": 10
}
```

The limit is a brake against abuse, not a plan rule. If you resell and need more, the Pilot Status team raises it for your user.

## Shared card per workspace

Your **reserve card** is the card saved on one of your workspaces — the **source workspace**, chosen by the Pilot Status team for your user. A customer workspace **linked** to it falls back to that card when its own wallet does not cover a platform charge and it has no card of its own (its own card always comes first; the fallback is one hop: the source's own shared card is not followed). You decide which customer workspaces are linked:

* **On creation:** `"shareCard": true` on [`POST /v1/workspaces`](#create-a-workspace). Absent or `false`, the workspace is not linked.
* **Afterwards:** `PUT` links, `DELETE` unlinks — below. **Unlink a customer who stopped paying** and your card no longer pays that customer's renewals: a failed renewal then suspends only them.

Both endpoints require you to be the **Owner** of `{workspaceId}` — not an active member, a workspace that does not exist or is archived get **403 `WORKSPACE_MEMBERSHIP_REQUIRED`**, and a role below Owner gets **403 `PERMISSION_DENIED`**. They take **no body** (an empty body or `{}`); any field gets **400 `UNKNOWN_FIELDS`**.

### Link the shared card

`PUT https://pilotstatus.com.br/v1/workspaces/{workspaceId}/shared-card`

```bash theme={null}
curl -X PUT "https://pilotstatus.com.br/v1/workspaces/cmh2a9z8y0002ws8example1q/shared-card" \
  -H "x-api-key: ps_account_your_account_key"
```

```json Response (200) theme={null}
{
  "workspaceId": "cmh2a9z8y0002ws8example1q",
  "sharedCard": { "linked": true, "sourceWorkspaceId": "cmh2a1b2c0001ws8example7k" },
  "changed": true
}
```

* **Idempotent.** Already linked to the same source: `200` with `"changed": false`, and nothing is recorded.
* The link is recorded in the workspace's **History** as **Backup card linked**. No e-mail is sent.
* **409 `SHARED_CARD_NOT_CONFIGURED`** — the Pilot Status team has not configured a reserve card for you.
* **400 `SELF_SOURCE`** — `{workspaceId}` is the source workspace itself.
* **409 `SOURCE_ARCHIVED`** — the source workspace is archived.
* **409 `NO_SHARED_OWNER`** — you are no longer an active Owner of the source workspace.

### Unlink the shared card

`DELETE https://pilotstatus.com.br/v1/workspaces/{workspaceId}/shared-card`

```bash theme={null}
curl -X DELETE "https://pilotstatus.com.br/v1/workspaces/cmh2a9z8y0002ws8example1q/shared-card" \
  -H "x-api-key: ps_account_your_account_key"
```

```json Response (200) theme={null}
{
  "workspaceId": "cmh2a9z8y0002ws8example1q",
  "sharedCard": { "linked": false, "sourceWorkspaceId": null },
  "changed": true
}
```

* **Idempotent.** Not linked: `200` with `"changed": false`, and nothing is recorded.
* The unlink is recorded in the workspace's **History** as **Backup card unlinked**. No e-mail is sent.
* From then on, the workspace's charges use only its own wallet and card. If they do not cover a renewal, **that workspace** is suspended — your card is not charged.
* **409 `NO_SHARED_OWNER`** — the workspace is linked to a source workspace you are not an active Owner of. Ask the Pilot Status team.

## Workspace keys

These three endpoints manage the [workspace keys](https://docs.pilotstatus.com.br/api/key-types.md#workspace-keys) of one workspace, with your **current role** in it. Not being an active member, or a workspace that does not exist or is archived, all get the same **403 `WORKSPACE_MEMBERSHIP_REQUIRED`**.

### List the keys

`GET https://pilotstatus.com.br/v1/workspaces/{workspaceId}/api-keys` — **Owner or Admin**.

```json Response (200) theme={null}
{
  "data": [
    {
      "id": "cmh2aa0010003ak8example4d",
      "name": "Workspace API Key",
      "prefix": "ps_workspace_",
      "last4": "3b5d",
      "isPrimary": true,
      "createdAt": "2026-10-28T09:15:00.000Z",
      "lastUsedAt": "2026-10-28T09:20:11.000Z"
    },
    {
      "id": "cmh2ab7770004ak8example9m",
      "name": "Billing integration",
      "prefix": "ps_workspace_",
      "last4": "a1c0",
      "isPrimary": false,
      "createdAt": "2026-10-28T10:02:40.000Z",
      "lastUsedAt": null
    }
  ]
}
```

The raw key never comes back here. Number keys are not listed: they are managed on [`/v1/api-keys`](https://docs.pilotstatus.com.br/api/api-keys).

### Create a named key

`POST https://pilotstatus.com.br/v1/workspaces/{workspaceId}/api-keys` with `{ "name": "…" }` — **Owner or Admin**.

**name** `string` *required*

1 to 60 characters, after trimming spaces. Use it to tell which integration holds the key.

```json Response (201) theme={null}
{
  "apiKey": {
    "id": "cmh2ab7770004ak8example9m",
    "name": "Billing integration",
    "key": "ps_workspace_4e8b0d2f6a1c3e5b7d9f0a2c4e6b8d0f1a3c5e7b9d0fa1c0",
    "prefix": "ps_workspace_",
    "last4": "a1c0",
    "isPrimary": false,
    "createdAt": "2026-10-28T10:02:40.000Z"
  }
}
```

The raw `key` is shown **this one time only**. The key is recorded as created by you, so it is revoked if you are removed from the workspace. A workspace holds up to **50** live workspace keys — revoked keys do not count; over that, **409 `WORKSPACE_KEY_LIMIT_REACHED`** with `limit`.

### Revoke a named key

`DELETE https://pilotstatus.com.br/v1/workspaces/{workspaceId}/api-keys/{keyId}` — **Owner or Admin**. Answers `{ "id": "…", "revokedAt": "…" }`. The key stops working on the next request. Revoking a key that is already revoked also answers `200`, with its original `revokedAt`, so a retry is safe.

* **The primary key cannot be revoked** (**409 `PRIMARY_KEY_NOT_REVOCABLE`**): the in-app AI agent uses it. Rotate it instead with `POST /v1/api-keys/regenerate`, sending your account key and `x-workspace-id` (Owner role). Only the primary changes; named keys keep working.
* An id that is not a workspace key of this workspace gets **404 `API_KEY_NOT_FOUND`**. Number keys are managed on [`/v1/api-keys`](https://docs.pilotstatus.com.br/api/api-keys).

## Errors

| Status | `code` | Where | What happened |
| - | - | - | - |
| `400` | `NAME_REQUIRED` | `POST` | `name` missing or blank. |
| `400` | `NAME_TOO_LONG` | `POST` | `name` longer than 60 characters. `maxLength` says the limit. |
| `400` | `UNKNOWN_FIELDS` | `POST`, `…/shared-card` | Fields other than `name` and `shareCard` on `POST /v1/workspaces`; any field on `…/shared-card`. `unknownFields` names them. |
| `400` | `INVALID_SHARE_CARD` | `POST /v1/workspaces` | `shareCard` is present but not a JSON boolean (`"true"`, `1`, `null`, …). |
| `400` | `SELF_SOURCE` | `PUT …/shared-card` | The workspace is the source of your reserve card. |
| `401` | — | all | Missing, invalid or revoked key. |
| `403` | `ACCOUNT_KEY_REQUIRED` | all | The credential is not an account key. |
| `403` | `WORKSPACE_MEMBERSHIP_REQUIRED` | `…/{workspaceId}/…` | You are not an active member of that workspace, or it does not exist. |
| `403` | `PERMISSION_DENIED` | `…/{workspaceId}/…` | Your role there is below Admin (below Owner on `…/shared-card`). |
| `404` | `API_KEY_NOT_FOUND` | `DELETE` | No workspace key with that id in that workspace. |
| `409` | `WORKSPACE_LIMIT_REACHED` | `POST /v1/workspaces` | You already own as many workspaces as your limit. `limit` says how many. |
| `409` | `WORKSPACE_KEY_LIMIT_REACHED` | `POST …/api-keys` | The workspace already has 50 live (non-revoked) workspace keys. |
| `409` | `PRIMARY_KEY_NOT_REVOCABLE` | `DELETE` | The id is the primary key. |
| `409` | `SHARED_CARD_NOT_CONFIGURED` | `POST` with `shareCard: true`, `PUT …/shared-card` | No reserve card is configured for you. On `POST`, no workspace is created. |
| `409` | `SOURCE_ARCHIVED` | `POST` with `shareCard: true`, `PUT …/shared-card` | The source workspace of your reserve card is archived. On `POST`, no workspace is created. |
| `409` | `NO_SHARED_OWNER` | `POST` with `shareCard: true`, `…/shared-card` | You are not an active Owner of the source workspace. On `POST`, no workspace is created. |
| `500` | — | all | Unexpected failure (`Internal server error`). |

On `POST /v1/workspaces` the checks run in this order: `UNKNOWN_FIELDS`, `INVALID_SHARE_CARD`, `NAME_REQUIRED` / `NAME_TOO_LONG`, `WORKSPACE_LIMIT_REACHED`, and only then, with `shareCard: true`, the reserve card checks (`SHARED_CARD_NOT_CONFIGURED`, `SOURCE_ARCHIVED`, `NO_SHARED_OWNER`).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.