plicflixdevelopers
Entrar Criar conta

A API do plicflix

  • Endereço: https://api.plicflix.com
  • Formato: JSON (Content-Type: application/json), UTF-8. Erros sempre no formato {"erro": "mensagem"} e, quando há um motivo para máquinas, {"erro": "…", "codigo": "…"}.
  • Corpo: no máximo 64 KiB; campos desconhecidos são recusados (400).
  • Dinheiro: em centavos. Mês: AAAA-MM, fuso de Brasília.
  • Limites: cadastro, login e troca pelo navegador têm limite por IP (429 ao passar).
  • Para máquinas: /openapi.json (OpenAPI 3.1).

Rotas do estúdio (o SEU servidor)

Autenticação: Authorization: Bearer pk_… (a chave do painel). Só no servidor.

POST /v1/ingresso/trocar — a troca do token

POST /v1/ingresso/trocar
Authorization: Bearer pk_…
Content-Type: application/json

{"token":"pft_…"}
status corpo
200 {"jogador":{"id":"pf_…","nome":"Ana"},"jogo":"seu-slug","partida":"pt_…","assinante":true,"contexto":{"ref":"plicflix","idioma":"pt-BR","plataforma":"web"}}
401 token inválido, vencido (5 min), já trocado, de jogo de outro estúdio, ou chave inválida/estúdio inativo. Sempre a mesma mensagem, de propósito.
  • jogador.id: pf_ + 24 caracteres; fixo para essa pessoa no seu jogo e diferente em cada jogo.
  • jogador.nome: o apelido (até 24 letras); pode mudar.
  • assinante: false para testadores sem assinatura.

GET /v1/parceiro/jogos

Os seus jogos: {"parceiro":"Seu Estúdio","jogos":[{"slug","nome","url","tipo","ativo","situacao","motivo_recusa","status","status_url"}]}. situacao: rascunho, em_revisao, recusado ou publicado. status: o que a vigia viu (online, instavel, offline ou vazio).

PUT /v1/parceiro/jogos/{slug}

Edita a vitrine. Parcial: só os campos enviados mudam; os omitidos ficam como estão. As imagens e o vídeo só mudam pelo painel (onde a qualidade é conferida). Campos: nome, subtitulo, descricao, descricao_longa, estudio, generos[], tags[], classificacao, plataformas[], multijogador, cor, status_url. Regras em VITRINE. Não muda url, slug nem a situação.

GET /v1/parceiro/casos

Os casos de reclamação: {"casos":[{"id","jogo","mes","situacao","aberto_em","prazo","prova","prova_em","decidido_em","motivos":[…]}]}. situacao: aberto, em_analise, corrigido ou perdido.

POST /v1/parceiro/casos/{id}/prova

{"prova":"o que mudou e como conferir"} → 200 {"situacao":"em_analise"}. Fora do prazo: 409.

GET /v1/parceiro/repasses

O extrato: {"repasses":[{"mes":"2026-11","jogo":"seu-slug","jogadores":120,"segundos":431000,"pago_centavos":53210,"retido_centavos":0}]}.

Rota do navegador (jogos sem servidor)

POST /v1/ingresso/navegador

{"token":"pft_…"}, chamada pela página do jogo (o Plicflix.jogador() faz isso). Sem chave; o cabeçalho Origin precisa ser a origem do endereço cadastrado do jogo (senão 403). Resposta igual à da troca, mais "pelo_navegador": true. Veja MOTORES.

Entrar com Plicflix (OAuth 2.0 + PKCE)

O login fora do app (o seu site, o seu app nativo). O guia completo, com exemplos, está em OAUTH.

rota o quê
GET https://plicflix.com/oauth/authorize a página de autorizar: response_type=code, client_id (o slug), redirect_uri (cadastrado), state, code_challenge (S256, obrigatório), scope=perfil, prompt=consent (opcional)
POST /v1/oauth/token grant_type=authorization_code, code, redirect_uri, code_verifier, client_id. A chave pk_ é opcional (Basic, client_secret ou Bearer). Devolve {jogador:{id,nome}, jogo, assinante, sub, name, access_token, token_type, expires_in, scope}.
GET /v1/oauth/userinfo Authorization: Bearer pfa_… → as mesmas chaves, sem o token
POST /v1/oauth/revogar token=pfa_… → 200 (sempre)
GET /v1/parceiro/jogos/{slug}/oauth / PUT os redirect_uris do jogo ({"redirect_uris":[…]}, até 10), com a chave pk_
GET https://plicflix.com/.well-known/oauth-authorization-server a descoberta (RFC 8414); também em /v1/oauth/descoberta

Pública

rota o quê
GET /saude {"ok":true} se a API está de pé.
GET /v1/jogos/{slug}/status {"status":"online"|"instavel"|"offline"|"desconhecido","ms","em"} (o que a vigia viu).

Testar pela API

Para um teste automático do seu jogo sem o app, faça a parte do jogador pela API com uma conta testadora do seu jogo (passo 8 do COMECE). Autenticação do jogador: Authorization: Bearer <token da conta>.

API=https://api.plicflix.com
# 1. entrar (a conta já criada e com o e-mail confirmado; testadora do jogo)
TOK=$(curl -s -X POST $API/v1/entrar -d '{"email":"voce@estudio.com","senha":"…"}' | jq -r .token)
# 2. "tocar em Jogar": devolve a URL que o app abriria
curl -s -X POST $API/v1/jogos/SEU-SLUG/jogar -H "Authorization: Bearer $TOK" -d '{"plataforma":"web"}'
# → {"partida":"pt_…","url":"https://seu-jogo/?ref=plicflix#plicflix=pft_…&pf_idioma=pt-BR&pf_plataforma=web&pf_api=…", …}
# 3. abra essa URL num navegador automatizado (Playwright, Puppeteer) DENTRO de um iframe
#    numa página https de outro site, ou mande o token direto para a sua rota:
curl -s -X POST https://seu-jogo/api/plicflix/entrar -d '{"token":"pft_…"}'

O que o app faz durante a partida (para reproduzir num teste):

rota corpo quando
POST /v1/partidas/{partida}/carregou {"ms":1800,"falha":""} quando o jogo chama pronto() (falha: "", demorou, erro, desistiu)
POST /v1/partidas/{partida}/onde {"texto":"…","area":"…","ponto":{…}} quando o jogo chama onde()
POST /v1/partidas/{partida}/pulso {"ativo_ms":30000} a cada 30 s de jogo
POST /v1/partidas/{partida}/fim — ao sair

Uma partida vale até o fim ou até a mesma conta abrir outra (um jogador só joga uma coisa por vez): depois disso, as rotas dela respondem 410 {"erro":"partida encerrada"}.

As rotas da conta do jogador (POST /v1/contas, /v1/eu/confirmar, /v1/senha/esqueci etc.) estão no /openapi.json.

Os códigos de erro mais comuns

status quando
400 JSON inválido, campo desconhecido ou valor fora da regra (a mensagem diz qual)
401 sem chave/token, chave inválida, token do jogador vencido
403 sem permissão (ex.: troca pelo navegador de outra origem; e-mail do jogador não confirmado: codigo: "email_nao_confirmado")
404 jogo não existe, ou não publicado e você não é testador
409 conflito (ex.: prova fora do prazo)
410 partida encerrada (houve fim ou a conta abriu outra partida)
429 limite por IP; espere um minuto
5xx erro nosso; tente de novo com espera