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

# Uso do Mission Control

> Consulte o consumo de IA de um workspace (créditos, execuções, adoção) no Mission Control: um período, agrupado, filtrado e comparado com o período anterior.

Seu token de API precisa poder **usar agentes** (`use_agents`) e você precisa ter acesso à API no workspace. Além disso, o endpoint aplica as permissões de **Mission Control** do seu papel: `mission-control:view` para consultar, e o escopo de uso que você recebeu (o seu próprio uso, os seus times ou o workspace inteiro). O escopo é resolvido no servidor a partir do seu papel; a requisição nunca o amplia.

> [!NOTE]
>
> Este endpoint responde exatamente o que o painel do Mission Control na Tess mostra, a partir dos mesmos dados horários. O Mission Control precisa estar habilitado para o workspace, e existem dados a partir de `freshness.data_available_from`. Um período que começa antes disso é recusado, nunca respondido com zeros.

### **Exemplos de código**

Consumo por modelo de IA no mês atual, comparado com o período anterior:

```http cURL theme={null}
curl --request GET \
  --url 'https://api.tess.im/mission-control/usage?from=2026-10-01&to=2026-10-28&timezone=America/Sao_Paulo&group_by[]=resource&filters[resource_kind][]=model&compare=previous_period&granularity=month&limit=5' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'x-workspace-id: YOUR_WORKSPACE_ID' \
  --header 'Accept: application/json'
```

```javascript Node.js theme={null}
const axios = require('axios');

const config = {
  method: 'get',
  url: 'https://api.tess.im/mission-control/usage',
  params: {
    from: '2026-10-01',
    to: '2026-10-28',
    timezone: 'America/Sao_Paulo',
    'group_by[]': ['resource'],
    'filters[resource_kind][]': ['model'],
    compare: 'previous_period',
    granularity: 'month',
    limit: 5
  },
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'x-workspace-id': 'YOUR_WORKSPACE_ID',
    'Accept': 'application/json'
  }
};

try {
  const response = await axios(config);
  console.log(response.data.data.totals, response.data.data.groups);
} catch (error) {
  console.error(error.response?.status, error.response?.data);
}
```

```python Python theme={null}
import requests

url = "https://api.tess.im/mission-control/usage"
params = {
    "from": "2026-10-01",
    "to": "2026-10-28",
    "timezone": "America/Sao_Paulo",
    "group_by[]": ["resource"],
    "filters[resource_kind][]": ["model"],
    "compare": "previous_period",
    "granularity": "month",
    "limit": 5,
}
headers = {
    "Authorization": "Bearer YOUR_API_KEY",
    "x-workspace-id": "YOUR_WORKSPACE_ID",
    "Accept": "application/json",
}

response = requests.get(url, params=params, headers=headers)
if response.ok:
    data = response.json()["data"]
    print(data["totals"], data["groups"])
else:
    print(response.status_code, response.json())
```

### **Cabeçalhos**

**x-workspace-id** `integer` *required*

ID do workspace. Você precisa ser membro ativo do workspace e ter `mission-control:view` nele.

### **Parâmetros de consulta**

**from** `date (YYYY-MM-DD)` *required*

Início do período, data local no `timezone` (inclusive).

**to** `date (YYYY-MM-DD)` *required*

Fim do período (inclusive). O período tem no máximo **93 dias** e não pode começar antes de `freshness.data_available_from`.

**timezone** `string`

Fuso IANA das datas locais e dos buckets (por exemplo `America/Sao_Paulo`). Padrão: o fuso da plataforma.

**granularity** `string`

Tamanho do bucket de `series`: `hour`, `day` (padrão), `week` ou `month`.

**metrics\[]** `array of string`

Métricas a retornar. Padrão: `consumption_net`, `consumption_charged`, `consumption_refunded`. Disponíveis: `consumption_net`, `consumption_charged`, `consumption_refunded`, `executions`, `failed_executions`, `interrupted_executions`, `uses`, `success_rate`, `avg_credits_per_execution`, `avg_credits_per_person`, `active_people`, `active_agents`, `active_autonomous_agents`, `active_days`, `active_business_days`.

**group\_by\[]** `array of string`

Dimensões de agrupamento, no máximo 3: `agent`, `person`, `resource`, `resource_kind`, `execution_type`, `modality`, `activity_category`, `charge_type`, `execution_origin`, `trigger_source`, `agent_origin`. Agrupar por `person` exige `mission-control:person-data:view`; sem ela a consulta é recusada (403 `person_data_not_allowed`).

**filters\[person]\[]** `array of string`

`me` (o seu próprio uso), `my_team` (membros atuais dos seus times), `my_workspace` (todos no seu escopo) ou ids de pessoas. Os apelidos não exigem permissão extra; ids de pessoas exigem `mission-control:person-data:view` e precisam estar dentro do seu escopo.

**filters\[team]\[]** `array of integer`

Ids de times. Só os ids listados em `scope.teams` de uma resposta anterior são aceitos.

**filters\[agent]\[]** `array of integer`

Ids de agentes. Pegue-os em `groups[].dimensions.agent.id` de uma resposta anterior agrupada por `agent`.

**filters\[resource]\[]** `array of string`

Recursos como `<kind>:<name>`, por exemplo `model:gpt-5`, `tool:web_search`, `connector:googlesheets`. Pegue-os de uma resposta anterior agrupada por `resource`.

**filters\[resource\_kind]\[]** `array of string`

`model`, `tool`, `connector`, `upload`, `kb`, `memory`, `voice` ou `other`. Use `["model"]` para restringir um agrupamento por `resource` aos modelos de IA.

**filters\[modality]\[]** `array of string`

`chat`, `image`, `video`, `audio`, `upload`, `tools` ou `other`.

**filters\[activity\_category]\[]** `array of string`

`agents`, `tools`, `connectors` ou `kb`.

**filters\[agent\_origin]\[]** `array of string`

`standard` ou `cowork` (agentes de Cowork / Funcionários Digitais).

**filters\[trigger\_source]\[]** `array of string`

Quem iniciou a execução: `human`, `scheduler`, `autopilot`, `automation`, `api` ou `embed`.

**filters\[status]\[]** `array of string`

Resultado da execução: `succeeded`, `failed` ou `interrupted` (interrompida pela pessoa, ainda cobrada).

**filters\[execution\_type]\[]** `array of string`

Valores exatos de tipo de execução, como retornados em uma resposta agrupada anterior (por exemplo `chat`, `text`, `image`, `tool_execution`).

**filters\[charge\_type]\[]** `array of string`

Valores exatos de tipo de cobrança (por exemplo `execution`).

**filters\[execution\_origin]\[]** `array of string`

Valores exatos de origem da execução.

**compare** `string`

`previous_period` (mesmo número de dias, logo antes do período) ou `previous_calendar_month` (os meses-calendário anteriores inteiros, no máximo 3). Adiciona `comparison` à resposta e a cada grupo.

**sort** `string`

Id da métrica que ordena os grupos. Padrão: a primeira métrica solicitada.

**sort\_by** `string`

`value` (padrão), `delta_abs` ou `delta_pct` (variação em relação ao período de comparação; os dois exigem `compare`).

**order** `string`

`desc` (padrão) ou `asc`. Valores nulos ficam sempre por último.

**limit** `integer`

Grupos por página. Padrão 50, máximo 200.

**cursor** `string`

Cursor opaco da próxima página (`page.next_cursor` de uma resposta anterior).

**include\_group\_series** `boolean`

Retorna também a série de cada grupo.

**Parâmetros em array**

Envie chaves repetidas com colchetes, exatamente como mostrado: `group_by[]=resource&filters[person][]=me&filters[person][]=my_team`. Filtros só restringem os dados; um valor fora do seu escopo é recusado, nunca descartado em silêncio.

**IDs: nunca os invente**

* Ids de times vêm só de `scope.teams` de uma resposta (`scope.teams_total` é a contagem sem corte).
* Ids de agentes, pessoas e recursos vêm de `groups[].dimensions.<dimensão>.id` de uma resposta anterior agrupada por aquela dimensão.
* Conjuntos fechados (`modality`, `activity_category`, `agent_origin`, `trigger_source`, `resource_kind`, `status`) estão listados acima; valores abertos (`execution_type`, `charge_type`, `execution_origin`) vêm de uma resposta agrupada anterior.

**Recursos e totais não aditivos**

Agrupar ou filtrar por `resource`, `resource_kind` ou `charge_type` conta as execuções que **usaram** cada recurso. Uma execução que usou duas tools conta uma vez em cada grupo, então, entre recursos, os totais das métricas de execução (`executions`, `failed_executions`, `success_rate`, `avg_credits_per_execution`) voltam como `null` e `meta.non_additive` indica quais: leia os valores por grupo, nunca some os grupos. Créditos e `uses` sempre somam. Escopos só de modelo (`filters[resource_kind][]=model`) continuam exatos.

### **Resposta**

```json theme={null}
{
  "data": {
    "workspace_id": 4645,
    "scope": {
      "level": "workspace",
      "can_view_person_data": true,
      "can_view_cost": true,
      "downgrade_reason": null,
      "teams": [],
      "teams_total": 0
    },
    "period": {
      "from": "2026-10-01",
      "to": "2026-10-28",
      "timezone": "America/Sao_Paulo",
      "days": 28,
      "granularity": "month",
      "starts_at": "2026-10-01T03:00:00Z",
      "ends_at": "2026-10-29T03:00:00Z"
    },
    "metrics": {
      "consumption_net": {
        "id": "consumption_net",
        "name": "Net consumption",
        "unit": "credits",
        "aggregation": "sum",
        "max_window_days": 93
      }
    },
    "totals": {
      "consumption_net": 22.44224,
      "consumption_charged": 22.44224,
      "consumption_refunded": 0
    },
    "series_metrics": ["consumption_net", "consumption_charged", "consumption_refunded"],
    "series": [
      {
        "bucket": "2026-10-01",
        "starts_at": "2026-10-01T03:00:00Z",
        "ends_at": "2026-10-29T03:00:00Z",
        "complete": false,
        "values": {
          "consumption_net": 22.44224,
          "consumption_charged": 22.44224,
          "consumption_refunded": 0
        }
      }
    ],
    "dimensions": {
      "group_by": ["resource"],
      "filters": { "resource_kind": ["model"] },
      "resolved_filters": {}
    },
    "groups": [
      {
        "key": "[\"model:claude-fable-5.1\"]",
        "dimensions": {
          "resource": {
            "id": "model:claude-fable-5.1",
            "kind": "model",
            "name": "claude-fable-5.1",
            "label": "claude-fable-5.1",
            "kind_label": "AI model"
          }
        },
        "totals": {
          "consumption_net": 19.908,
          "consumption_charged": 19.908,
          "consumption_refunded": 0
        },
        "share": {
          "consumption_net": 0.887077,
          "consumption_charged": 0.887077,
          "consumption_refunded": null
        }
      }
    ],
    "page": {
      "limit": 5,
      "sort": "consumption_net",
      "sort_by": "value",
      "order": "desc",
      "total_groups": 6,
      "has_more": true,
      "next_cursor": "eyJmIjoi..."
    },
    "freshness": {
      "data_available_from": "2026-09-28T00:00:00Z",
      "data_as_of": "2026-10-28T19:50:00Z",
      "partial": false
    },
    "comparison": {
      "type": "previous_period",
      "period": { "from": "2026-09-03", "to": "2026-09-30", "days": 28 },
      "available": false,
      "reason": "period_before_coverage"
    },
    "meta": {
      "catalog_version": 6,
      "resource_scoped": true,
      "non_additive": {},
      "notes": [],
      "limits": {
        "max_window_days": 93,
        "max_group_by": 3,
        "max_filter_values": 100,
        "default_page_size": 50,
        "max_page_size": 200
      }
    }
  }
}
```

### **Campos da resposta**

| **Campo** | **Descrição** |
| :- | :- |
| scope | O que você pode ler: `level` (`own`, `team` ou `workspace`), `can_view_person_data`, `can_view_cost`, `teams` (os ids que `filters[team][]` aceita, com `mine` marcando os seus times) e `teams_total`. `downgrade_reason` diz por que o nível é mais restrito do que o seu papel pediu (`null` caso contrário). |
| period | O período solicitado, já resolvido: datas locais, fuso, número de dias, granularidade e os instantes em UTC. |
| metrics | Definição de cada métrica retornada: id, nome, definição, unidade, agregação, janela máxima e comparações suportadas. Detalhes internos do rollup não fazem parte do contrato público. |
| totals | Valor de cada métrica no período inteiro. `null` quando a métrica não é aditiva entre os recursos pedidos (veja `meta.non_additive`). |
| series | Um bucket por passo da granularidade, preenchido com zeros; `complete` é `false` no bucket ainda em andamento. |
| series\_metrics | Os ids das métricas que cada entrada de `series[].values` carrega, na ordem. |
| dimensions | Eco de `group_by` e `filters`; `resolved_filters.person` mostra como os apelidos de pessoa foram resolvidos (`aliases`, `resolved_count` e `user_ids` só com permissão de dados por pessoa). |
| groups | Com `group_by`: uma entrada por grupo com `dimensions` (sempre com o id para reutilizar como filtro), `totals`, `share` (parte do total do período, só métricas aditivas) e, com `compare`, `comparison` e `change_abs`. |
| page | `limit`, `sort`, `sort_by`, `order`, `total_groups`, `has_more` e `next_cursor` para a próxima página. |
| freshness | `data_available_from` (primeiro dia com dados), `data_as_of` (atualidade dos dados) e `partial` (`true` enquanto o período inclui horas ainda não processadas). |
| comparison | Com `compare`: o período de comparação, `available`, totais, `delta` e, para `consumption_net` e `executions`, uma `decomposition` em efeito pessoas e efeito intensidade. `reason` explica uma comparação indisponível. |
| meta | `catalog_version`, `non_additive`, `notes` (por exemplo `small_group` num agregado `my_team` pequeno) e `limits` fixos. |

### **Erros**

As recusas da consulta são objetos JSON com um `code` estável. Falhas de validação da requisição (um `granularity`, `compare`, `sort_by` ou `order` desconhecido, uma data mal formada) voltam como 422 no formato `{message, errors}` do Laravel; recusas de acesso (403/404) trazem só `message`:

```json theme={null}
{
  "message": "The period is too long for the requested metrics.",
  "type": "error",
  "status": 422,
  "code": "window_too_large",
  "details": { "max_window_days": 93, "requested_days": 120 }
}
```

| **Status** | **Code** | **Quando** |
| :- | :- | :- |
| 401 | | Token ausente ou inválido. |
| 403 | | Sem acesso à API no workspace, não membro, Mission Control desabilitado ou sem `mission-control:view`. Só `message`, sem `code`; a mesma resposta em todos os casos. |
| 404 | | O workspace de `x-workspace-id` não existe. |
| 403 | `person_data_not_allowed` | `group_by[]=person` ou ids de pessoas sem `mission-control:person-data:view`. Use `filters[person][]=me` ou `my_team`. |
| 403 | `filter_outside_scope` | Id de pessoa ou time fora do seu escopo. |
| 422 | `window_too_large`, `period_before_coverage`, `invalid_period`, `invalid_timezone`, `unsupported_timezone`, `unknown_metric`, `metric_not_queryable`, `unsupported_dimension`, `unsupported_filter`, `invalid_filter`, `invalid_sort`, `invalid_cursor`, `no_team`, `invalid_page_size`, `too_many_dimensions`, `too_many_groups`, `row_limit_exceeded` | Consulta inválida ou grande demais; `details` traz o limite ou o valor ofensivo. `no_team`: `my_team` sem time ativo. |
| 503 | `usage_rollup_disabled`, `data_not_ready` | Dados de uso ainda não disponíveis: para este workspace (`usage_rollup_disabled`, `details.reason`: `workspace_not_enabled` ou `workspace_backfill_pending`; `details` vazio (sem `details.reason`) quando os dados de uso estão desligados para todos os workspaces) ou de forma geral (`data_not_ready`, o histórico de uso ainda não foi construído). Tente mais tarde; a resposta nunca são zeros. |


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