Skip to main content

Convenções da API

Toda API do SalesOS segue as regras desta página. Leia uma vez e as páginas de cada endpoint ficam curtas: elas contam apenas o que é específico delas.
Esta página é o contrato ao qual nos prendemos. Onde um endpoint se afasta dela, a página dele diz isso explicitamente — exceção silenciosa é defeito, e queremos saber.

URLs base

https://api.play2sell.com
Todo endpoint vive em /functions/v1/<nome>. Não existe superfície REST em /v1/... — se encontrar uma página descrevendo isso, ela está desatualizada; avise a gente.

Autenticação

Dois esquemas, e são disjuntos — um endpoint aceita um ou outro, nunca os dois para o mesmo chamador.

Parceiro (servidor a servidor)

A assinatura é um HMAC sobre {api_key_id}.{timestamp}.{raw_body}. Veja Autenticação para o helper signedRequest.
  • Timestamps com mais de 300 segundos são rejeitados (proteção contra replay)
  • Assine os bytes crus do corpo, antes de qualquer reserialização
  • Cada chave pertence a uma única empresa; um documento de outra empresa responde found: false

Modo self (sessão federada)

Usado quando o seu app já tem o usuário final autenticado. A resposta cobre apenas esse usuário.
Enviar uma lista collaborators junto com um token de usuário é rejeitado com SELF_MODE_NO_COLLABORATORS. Consultas em lote exigem uma API Key de parceiro — do contrário, qualquer usuário autenticado poderia ler dados de outras pessoas por CPF.

Formatos de erro

As requisições falham em duas camadas diferentes, e elas respondem diferente. Trate as duas — é o erro de integração mais comum que vemos.

Camada de autenticação

Antes de a requisição chegar à lógica do endpoint:
error é uma string. Códigos comuns: header_missing, header_malformed, invalid_key, signature_mismatch, timestamp_expired.

Camada do endpoint

Depois que a autenticação passou:
error é um objeto. details aponta o item problemático pelo index quando a requisição trouxe uma lista.
error é string num caso e objeto no outro. Código que assume error.code vai ler undefined em toda falha de autenticação — e código que assume error string vai imprimir [object Object] nas falhas de validação. Ramifique pelo tipo:
Sabemos que não é o ideal. Está documentado em vez de escondido porque as duas camadas sobem separadas, e um parceiro descobrir isso em produção é pior do que ler aqui.

Pagamentos

A API de Pagamentos responde em RFC 7807 problem+json:
É um serviço separado, com convenções próprias. instance é o id da requisição — cite-o ao abrir um chamado.

Códigos de status

Ausência não é erro. Nenhuma campanha vigente, ninguém em plantão, nenhuma missão hoje — tudo responde 200 com estrutura vazia. Um endpoint que devolvesse 404 para “nada hoje” faria a sua tela dizer que algo quebrou quando o dia apenas começou.

Lotes e identidade

Endpoints de parceiro recebem um array collaborators e respondem na mesma ordem, um item por item enviado.

Resolução de identidade

A precedência é user_id > cpf > email. Quando mais de um vem, o primeiro presente vence — os outros são ignorados, não usados como alternativa.
  • CPF é aceito em qualquer formato; os dígitos são normalizados. Precisa ter exatamente 11 dígitos.
  • Pessoa desconhecida responde "found": false. Isso não é erro, e mantém o array alinhado com a sua requisição.
  • "ambiguous": true aparece quando mais de uma pessoa casou — trate como não resolvido.

Limites

Os limites de lote são por ação e ficam declarados em cada página, porque acompanham o payload que cada ação produz. Como regra: ação de status permite 500; ação que expande uma lista por pessoa permite 100 ou menos.
Dado compartilhado — metadados da campanha, turnos da empresa — sai uma vez no topo da resposta, não repetido por pessoa. Num lote de 500 pessoas isso é a diferença entre uma resposta enxuta e uma de megabytes.

Configuração é da empresa, nunca do seu código

Esta é a regra que mais quebra integração meses depois de ela subir. Nomes, rótulos, quantidades, limiares e moedas são configurados por empresa e devolvidos na resposta. Não são constantes.
Renderize o que a resposta trouxer. Uma tela que fixa um rótulo funciona até o dia em que o cliente renomeia — e aí ela mente, em silêncio, sem erro nenhum.

Fusos e datas

Todo “hoje” é calculado no fuso da empresa, nunca em UTC. A resposta declara qual usou:
Timestamps são ISO 8601 em UTC. Converta para exibição usando o timezone da mesma resposta — não o do aparelho.

Limites de uso

Configurável por chave, com padrão de 1000 requisições/hora. No 429, a resposta traz retry_after em segundos. Espere; não fique tentando.

Versionamento

Contratos são estendidos, não quebrados. Podemos acrescentar campos a qualquer momento, então faça um parse permissivo e ignore o que não conhecer. Comportamento novo que muda um payload existente sobe opt-in, atrás de uma flag na requisição (por exemplo include_day). Omitir a flag mantém a resposta que você já trata.

Segurança

  • As APIs de parceiro são somente leitura, salvo quando a página disser o contrário — nunca resgatam, nunca alteram saldo, nunca aceitam termos
  • As requisições são assinadas por HMAC e registradas para auditoria; documentos e e-mails nunca vão para os logs
  • Nunca chame estas APIs pelo lado do cliente: a chave ficaria exposta

Próximos passos

Autenticação

Criar chaves e assinar requisições

API de Check-in

Presença no plantão e a trilha de turnos do dia

API de Missões

Progresso, pontos conquistados e pontos disponíveis

API de Campanhas

Vitrine de prêmios e saldo disponível