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

# API de Progresso do Jogador

> Leia nível, XP, moedas e posição no ranking dos seus colaboradores — feita para a faixa de identidade de uma tela inicial de super app.

# API de Progresso do Jogador

<Note>
  Esta página pressupõe as regras comuns em [Convenções da API](/pt/api/conventions) — autenticação, os dois formatos de erro, lotes e resolução de identidade. Aqui fica só o que é específico do progresso.
</Note>

A API de Progresso do Jogador permite que o seu backend leia onde cada colaborador está na gamificação da sua empresa: **em que nível está**, **quanto XP tem**, **quantas moedas pode gastar** e **qual a posição no ranking**.

Foi feita para a faixa do topo de uma tela inicial — aquela que cumprimenta a pessoa e mostra como ela está indo.

<Note>
  A **escada de níveis é configurada pela sua empresa**: quantos níveis, os nomes, o que cada um exige e como cada um aparece. Esta API devolve o que estiver configurado — ela não conhece escada nenhuma.
</Note>

## Como funciona

1. **Você recebe uma API Key** com o escopo `progress:read`
2. **Seu backend consulta** um ou vários colaboradores (por CPF ou e-mail)
3. **O SalesOS responde** com a escada **uma vez no topo**, e o estado de cada pessoa em seguida

***

## Autenticação

```
Authorization: P2S-SIGN-V1 API_KEY:TIMESTAMP:SIGNATURE
```

| Propriedade        | Detalhes                                               |
| ------------------ | ------------------------------------------------------ |
| **Escopo exigido** | `progress:read`                                        |
| **Método**         | Apenas `POST`                                          |
| **Limite de uso**  | Configurável por chave (padrão: 1000 requisições/hora) |

***

## Referência do endpoint

```
POST https://api.play2sell.com/functions/v1/progress-partner-api
```

Uma ação: `progress_status`.

### Esquema da requisição

<ParamField body="action" type="string" required>
  Deve ser `"progress_status"`
</ParamField>

<ParamField body="collaborators" type="array" required>
  Lista de referências de colaboradores (máximo 500)
</ParamField>

<ParamField body="period" type="string">
  Período do XP e do ranking: `daily`, `weekly`, `monthly` ou `all_time`. Ausente = `all_time`.
</ParamField>

<ParamField body="ranking_scope" type="string">
  Universo do ranking: `tenant` (toda a empresa) ou `org_unit` (a unidade da própria pessoa). Ausente = `tenant`.
</ParamField>

### Exemplo

```bash theme={null}
curl -X POST https://api.play2sell.com/functions/v1/progress-partner-api \
  -H "Authorization: P2S-SIGN-V1 API_KEY:TIMESTAMP:SIGNATURE" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "progress_status",
    "collaborators": [{ "cpf": "529.982.247-25" }],
    "period": "all_time"
  }'
```

**Resposta (200):**

```json theme={null}
{
  "data": {
    "timezone": "America/Sao_Paulo",
    "reference_date": "2026-08-14",
    "period": "all_time",
    "ranking_scope": "tenant",
    "levels": [
      { "order": 1, "key": "level_01", "name": "Iniciante",
        "requirements": [], "appearance": null },
      { "order": 2, "key": "level_02", "name": "Avançado",
        "requirements": [{ "type": "min_xp", "value": 500 }],
        "appearance": { "color": "#7B2D8E" } }
    ],
    "collaborators": [
      {
        "cpf": "52998224725",
        "found": true,
        "user_id": "8f14e45f-0000-0000-0000-000000000001",
        "name": "Maria Santos",
        "membership_status": "active",
        "level": {
          "order": 2, "key": "level_02", "name": "Avançado",
          "appearance": { "color": "#7B2D8E" }
        },
        "next_level": {
          "order": 3, "key": "level_03", "name": "Lendário",
          "requirements": [{ "type": "min_xp", "value": 2000 }],
          "appearance": null
        },
        "xp": {
          "period": "all_time", "current": 1200,
          "all_time": 1200, "monthly": 300, "daily": 0
        },
        "coins": { "balance": 640, "source": "playcoin" },
        "ranking": { "scope": "tenant", "period": "all_time", "position": 1, "total": 240 }
      }
    ],
    "total": 1,
    "found": 1
  },
  "meta": {
    "request_id": "1f6c1b2e-0000-4a1b-8c2d-000000000001",
    "timestamp": "2026-08-14T13:45:00.000Z"
  }
}
```

***

## Campos

### A escada (topo da resposta)

| Campo                   | Significado                                                    |
| ----------------------- | -------------------------------------------------------------- |
| `levels[]`              | A escada de níveis da sua empresa, do primeiro ao último       |
| `levels[].order`        | Posição na escada — é a ela que `level.order` se refere        |
| `levels[].name`         | O nome do nível **como a sua empresa o configurou**            |
| `levels[].requirements` | O que aquele nível exige (ex.: `min_xp`, `min_missions_count`) |
| `levels[].appearance`   | Configuração visual do nível — veja o aviso abaixo             |

<Warning>
  **A quantidade de níveis é da sua empresa, não uma constante.** Monte a tela a partir do array. Uma escada pode ter nove degraus onde outra tem dez, e as duas estão certas.
</Warning>

### Por colaborador

| Campo                                          | Significado                                                                            |
| ---------------------------------------------- | -------------------------------------------------------------------------------------- |
| `level`                                        | O nível em que a pessoa está agora, com nome e aparência                               |
| `next_level`                                   | O próximo degrau e o que ele exige. **Ausente** quando a pessoa está no topo           |
| `xp.period`                                    | O período que você pediu, ecoado de volta                                              |
| `xp.current`                                   | XP naquele período — o número a exibir ao lado do nome                                 |
| `xp.all_time` · `monthly` · `weekly` · `daily` | A mesma pontuação em todos os períodos. **Período sem apuração vem ausente, não zero** |
| `coins.balance`                                | Moedas disponíveis para gastar                                                         |
| `ranking.scope`                                | O universo em que a posição foi calculada                                              |
| `ranking.position` · `total`                   | Posição e quantas pessoas há naquele universo                                          |

***

## Aparência do nível

A identidade visual do nível — a cor, e o que mais a sua empresa configurar — vem em `appearance`.

<Warning>
  **`appearance` pode vir `null`, e null não significa "sem cor".** Significa que ninguém configurou uma ainda. Nesse caso use um fallback seu, mas não fixe uma paleta indexada por nome de nível: no dia em que a empresa renomear um nível ou trocar as cores, a tela com paleta fixa segue mostrando a antiga, sem erro nenhum.
</Warning>

<Tip>
  Leia a cor da resposta mesmo quando ela parecer constante hoje. É exatamente por isso que ela viaja no payload em vez de morar no seu app.
</Tip>

***

## Períodos

O XP é guardado em quatro períodos, e a tela costuma mostrar um deles. Como "200 XP" num desenho não diz qual, esta API devolve **os quatro** mais o que você pediu.

| `period`   | Cobre                          |
| ---------- | ------------------------------ |
| `daily`    | Hoje, no fuso da empresa       |
| `weekly`   | A semana corrente              |
| `monthly`  | O mês corrente                 |
| `all_time` | Tudo desde a entrada da pessoa |

<Warning>
  Um período desconhecido é **recusado com 400**, não respondido com zeros. Uma resposta zerada faria a sua tela afirmar que a pessoa não tem XP — uma ausência que não é verdade.
</Warning>

<Warning>
  **Período que nunca foi apurado vem ausente, não como `0`.** No exemplo acima o `weekly` não aparece: aquela pessoa não tem linha de pontuação semanal. Já `daily: 0` é diferente — foi apurado, e deu zero.

  Trate os dois casos à parte. Escrever "0 XP nesta semana" para um período ausente diz à pessoa que ela não pontuou, quando a verdade é que ninguém apurou aquele período para ela.
</Warning>

***

## Ranking

Uma posição só significa algo junto do seu universo, então `scope`, `period` e `total` viajam sempre com ela.

| `ranking_scope` | Universo                           |
| --------------- | ---------------------------------- |
| `tenant`        | Toda a empresa                     |
| `org_unit`      | Apenas a unidade da própria pessoa |

<Tip>
  `total` é contra quantas pessoas a posição foi medida. "#12 de 240" se lê muito diferente de "#12 de 13" — mostre isso.
</Tip>

***

## Tratamento de erros

Veja [Convenções da API](/pt/api/conventions#formatos-de-erro) para os dois formatos e a tabela de códigos.

<AccordionGroup>
  <Accordion title="400 — VALIDATION_ERROR">
    Corpo inválido, lote acima de 500, CPF sem 11 dígitos, item sem `cpf` e sem `email`, ou `period` / `ranking_scope` desconhecido.
  </Accordion>

  <Accordion title="403 — FORBIDDEN">
    API Key válida, mas sem o escopo `progress:read`.
  </Accordion>
</AccordionGroup>

<Tip>
  **Empresa sem escada configurada não é erro.** A resposta vem com `levels: []` e status 200.
</Tip>

***

## Limites de uso

| Limite                                 | Valor |
| -------------------------------------- | ----- |
| Requisições por hora (padrão)          | 1000  |
| Máximo de colaboradores por requisição | 500   |

***

## Próximos passos

<CardGroup cols={2}>
  <Card title="API de Missões" icon="bullseye-arrow" href="/pt/api/integrations/missions">
    O progresso que gera o XP mostrado aqui
  </Card>

  <Card title="API de Campanhas" icon="gift" href="/pt/api/integrations/campaigns">
    Onde as moedas são gastas
  </Card>
</CardGroup>
