Status: Approved · v2 · SPEC-API-PLAYER-001
depends_on: SPEC-DOMAIN-PLAYER-001, SPEC-DOMAIN-MATCH-001
used_by: IS-MVP-05.1, IS-MVP-05.2, IS-MVP-05.3
API do jogador
Perfil próprio, privacidade, vínculos, convites, confirmações de guest e estatísticas.
Princípios e padrões
- Base path
/api/v1; JSON UTF-8; chaves em camelCase. - Toda resposta usa
ApiResponse<T>comok,data|erroremetacontendorequestIdetimestamp. - IDs são strings opacas; datas são ISO-8601 UTC; dinheiro é inteiro em centavos com moeda BRL.
- Listas usam
pageepageSizeno MVP; default 20, máximo 100; metadados ficam emmeta.pagination. - Endpoints públicos usam DTOs públicos específicos; entidades internas, memberships, saldos e dados privados nunca vazam.
- Erros de domínio são estáveis e acionáveis; stack traces e detalhes internos não são retornados.
- Alterações sensíveis usam
Idempotency-Key, confirmação recente quando necessário e audit log. - Uploads usam fluxo presigned; o backend valida propósito, MIME, tamanho e ownership antes de confirmar o asset.
Endpoints
| Método | Rota | Acesso | Request | Response | Regras principais |
|---|---|---|---|---|---|
| GET | /players/me | Jogador | — | PlayerMeResponse | Dados privados e completeness. |
| PATCH | /players/me | Jogador | UpdatePlayerProfileRequest | PlayerMeResponse | Posições, bio, contatos e availability. |
| PATCH | /players/me/privacy | Jogador | UpdatePlayerPrivacyRequest | PlayerPrivacyResponse | Matriz explícita. |
| GET | /players/me/team-links | Jogador | PlayerLinkQuery | TeamPlayerLinksResponse | Active/former (implementado IS-MVP-05.2 reusando o TeamPlayerLinkDto compartilhado — ver nota). |
| GET | /players/me/invites | Jogador | — | PlayerInvitesResponse | Pending ordenados por invitedAt (sem campo de expiração ainda — ver nota). |
| POST | /team-player-links/:linkId/respond | Jogador alvo | RespondPlayerInviteRequest | TeamPlayerLinkResponse | Aceita/rejeita (rota real — ver nota). |
| POST | /team-player-links/:linkId/end | Jogador (vínculo ativo) ou team.manageSquad | EndPlayerLinkRequest | TeamPlayerLinkResponse | Vira former; jogador só encerra o próprio vínculo ativo. |
| GET | /players/me/guest-confirmations | Jogador | — | GuestConfirmationsResponse | Possíveis históricos (IS-MVP-05.3). |
| POST | /players/me/guest-confirmations/:id/respond | Jogador | GuestConfirmationRequest | GuestConfirmationResponse | Confirm/contest (IS-MVP-05.3). |
| GET | /players/:playerId/stats | Público conforme privacy | StatsQuery | PlayerStatsResponse | Somente partidas validadas/confirmadas (IS-MVP-05.3). |
| GET | /players/:playerId/history | Público conforme privacy | HistoryQuery | PlayerHistoryResponse | Times/campeonatos permitidos (IS-MVP-05.3). |
IS-MVP-05.2:team-links/invitesreutilizamTeamPlayerLinksResponse/TeamPlayerLinkDto(comcategoryNamesopcional, resolvido só nesta visão) em vez de tipos duplicados. Responder/encerrar vínculo reutilizam o recurso/team-player-links/:linkId/...já parcialmente implementado porIS-MVP-04.4(SPEC-API-TEAM-TORCIDA-001) em vez de duplicar a mutação sob/players/me/invites/:linkId/...— as duas specs descreviam a mesma capacidade com rotas diferentes; esta reutiliza a família de rota já existente.TeamPlayerLinkDtonão tem campo de expiração; a ordenação usainvitedAtcomo proxy até um mecanismo de expiração existir.
IS-MVP-05.3:GuestConfirmationDtoreferencia a partida com campos descritivos (categoryName/opponentName/matchDate) em vez de ummatchId/publicRoutereal — o domínio de gestão de partidas (EP-MVP-06.1) ainda não existe, e apontar para uma página de partida inexistente seria pior que um rótulo textual. A detecção do candidato comparaCreateGuestPlayerRequest.privateContact(aceito desdeIS-MVP-04.4mas nunca persistido) com ocontactdo jogador já ativado; um match cria umaGuestConfirmationDtopendente. Confirmar converte o vínculoguestemregistered/active(reaproveitandoPublicPlayerRepositoryPort.updateTeamLinks,IS-MVP-05.2) e contribui uma linha determinística de stats (1 jogo, sem dado de partida real para compor uma quebra jogo a jogo) —recentMatches/championshipspermanecem vazios por falta de fonte real, não preenchidos com dado inventado.PlayerStatsDto/PlayerHistoryDtoreutilizamPublicPlayerStatLineDto/PublicPlayerTeamLinkDto+PublicPlayerChampionshipDto(IS-MVP-01.2) em vez de duplicar formas.
Autenticação e autorização
- Somente o próprio usuário altera perfil e privacy.
- Times só criam vínculos; não editam perfil do jogador.
- Stats públicas respeitam flags e guest confirmation.
Erros de domínio
| Código | HTTP | Quando ocorre | Ação esperada no cliente |
|---|---|---|---|
| PLAYER_PROFILE_REQUIRED | 409 | Role/perfil ausente | Ativar jogador. |
| PROFILE_PRIVATE | 403 | Seção privada | Ocultar. |
| GUEST_CONFIRMATION_MISMATCH | 422 | Evidência não corresponde (confirmação não pertence ao jogador) | Contestar/suporte. |
| INVITE_ALREADY_RESOLVED | 409 | Decisão anterior (convite ou confirmação de guest já resolvidos) | Atualizar. |
| GUEST_HISTORY_ALREADY_CLAIMED | 409 | Participação de convidado já associada a outro jogador (IS-MVP-05.3; listado em SPEC-DOMAIN-PLAYER-001 mas ausente desta tabela até agora) | Atualizar/contestar. |
Idempotência e concorrência
- Responder convite/guest confirmation é idempotente.
- Atualizações usam version para conflitos de edição.
Auditoria e efeitos colaterais
- Privacy, status e vínculos geram audit do próprio usuário.
- Invite response notifica time; contest guest gera pendência.
Exemplos
privacy
{
"profilePublic": true,
"contactsPublic": false,
"currentTeamsPublic": true,
"formerTeamsPublic": false,
"statsPublic": true,
"availabilityPublic": true
}
Mocks
- Perfis completos/incompletos, private sections, invite/guest states.
- Stats recalculadas em fixtures consistentes.
Testes obrigatórios
- Privacy matrix.
- Invite lifecycle.
- Guest confirm associates history once.
- Validated-only stats.
- Player cannot be managed by third party.
Critérios de aceite
- Painel próprio cobre todos os fluxos.
- Dados privados nunca entram em public DTO/card/search.
Machine summary
spec: SPEC-API-PLAYER-001
api_group: API do jogador
base_path: /api/v1
response_envelope: ApiResponse<T>
ids: string
dates: ISO-8601
money: integer_cents