Guia da API

Guia completo de integração da API Lastreo — fluxos, verificação de médicos e estudantes de medicina, webhooks e exemplos. Para a referência interativa de endpoints e schemas, veja a API Reference.

Documentação da API Lastreo

Versão: 1.63 Data da Última Atualização: 30/05/2026

1. Introdução

O que é o Lastreo?

Lastreo é uma plataforma de assistência clínica projetada para conectar pacientes e equipes de saúde através de múltiplos canais: chat integrado no aplicativo (in-app), WhatsApp e Telegram. Sua missão é facilitar o acompanhamento contínuo, o registro de dados de saúde em tempo real e a comunicação eficiente, com um módulo especializado em Esclerose Múltipla.

Para Quem é Este Documento?

Esta documentação é um guia técnico para desenvolvedores que precisam integrar aplicativos com a API do Lastreo. Contém os endpoints, fluxos de requisição e modelos de dados necessários para a integração.

Changelog

Versão Data Alterações
1.74 29/06/2026 client_user_ref agora garante idempotência de re-tentativas. Ao criar uma sessão de verificação hospedada (POST /api/v1/client/verification-sessions), passar um client_user_ref estável (o ID da pessoa no seu sistema) faz com que re-tentativas da mesma pessoa reusem a mesma identidade em vez de criar um cadastro novo — e não há nova cobrança por re-verificar a mesma pessoa. Recomendado para fluxos em que o usuário pode recomeçar a verificação (após erro, abandono ou múltiplas tentativas). Sem client_user_ref, cada sessão é tratada como uma pessoa distinta (comportamento inalterado). Vale para kind: "physician" e kind: "student". Zero impacto no consumidor App EM.
1.73 21/06/2026 Verificação bronze inclui declaração de identidade. No fluxo hospedado, a verificação rápida (bronze) passa a exigir que o médico aceite uma declaração, sob as penas da lei, de que é o titular do CRM informado — camada de responsabilização (o registro do aceite, com data/hora e origem, fica selado para auditoria). É uma etapa dentro da página hospedada; sua integração não muda (mesma criação de sessão e mesmos webhooks). Continua valendo: bronze confirma que o registro profissional existe e está regular; para vínculo de identidade por biometria use prata, e por assinatura digital use ouro. Zero impacto no consumidor App EM.
1.72 21/06/2026 Verificação é produzida apenas pelo fluxo hospedado. A PRODUÇÃO de qualquer tier passa a acontecer só na superfície hospedada do Lastreo (onde o próprio médico confirma a identidade). POST /client/doctors/{id}/verify-tier passa a responder needs_doctor_action para bronze/prata/ouro ainda não verificados (registra a pendência; a cobrança ocorre na conclusão hospedada) — antes o bronze retornava produced na hora. POST /client/doctors apenas registra/vincula o médico (não produz bronze). O reconhecimento cross-tenant (médico já verificado na rede) continua imediato e gratuito por API — o efeito de rede é preservado. Para verificar um médico ainda não verificado, crie uma sessão (POST /client/verification-sessions) e direcione-o ao embed_url. Ação necessária: se você tratava outcome: "produced" no verify-tier para bronze, passe a tratar needs_doctor_action + fluxo hospedado. Zero impacto no consumidor App EM.
1.71 21/06/2026 Verificação hospedada agora cobre os três tiers. A página/iframe hospedado (POST /api/v1/client/verification-sessions) passa a apresentar o método de acordo com o required_tier da sessão: bronze (confirmação rápida só com CRM + UF + nome, sem documento), prata (carteira + selfie, já existente) ou ouro (assinatura digital ICP-Brasil — o médico baixa um termo, assina com o certificado AR-CFM e reenvia, tudo dentro do iframe). Antes o iframe só fazia prata. O Lastreo Link (reuso de identidade já verificada) continua sempre oferecido. Sem required_tier, o padrão permanece prata (zero impacto em integrações existentes). Os webhooks verification.approved carregam o tier final (bronze/prata/ouro) como antes. Zero impacto no consumidor App EM.
1.70 20/06/2026 Verificação bronze mais precisa. A aprovação automática (bronze) passa a ser sempre ancorada na confirmação do registro profissional oficial (situação regular + nome conferido), e o casamento de nome ficou mais tolerante a variações legítimas (nome do meio omitido, ordem dos sobrenomes) — menos médicos legítimos reprovados, sem afrouxar a checagem. Sem mudança no contrato da API (mesmos endpoints, schemas e tiers). Zero impacto no consumidor App EM.
1.69 19/06/2026 Cobertura bronze ampliada. A verificação bronze passa a confirmar o médico também pelo registro profissional oficial (situação regular + nome conferido), ampliando a cobertura para quem não tem atividade assistencial ativa registrada (ex.: atuação exclusivamente privada) — antes esses casos exigiam prata/ouro. Sem mudança no contrato da API (mesmos endpoints, schemas e tiers); apenas mais médicos passam a ser elegíveis a bronze automático. Zero impacto no consumidor App EM.
1.68 18/06/2026 Piso de tier na verificação hospedada (required_tier). POST /api/v1/client/verification-sessions passa a aceitar required_tier (bronze | prata | ouro; aliases basic/silver/strong/gold) — o tier mínimo que a sessão aceita. Com piso definido: o Lastreo Link só conclui se a identidade reusada tiver tier ≥ piso (abaixo disso, o médico é direcionado à verificação completa); e a verificação feita dentro do fluxo hospedado (carteira + selfie = prata) não satisfaz piso ouroouro depende de identidade já-ouro via Lastreo Link (a assinatura ICP-Brasil é fora do fluxo hospedado). O campo vale só para kind: "physician" e é devolvido em GET /client/verification-sessions/{id}. Sem required_tier, o comportamento é inalterado. Zero impacto no consumidor App EM.
1.67 18/06/2026 Lastreo Link — reconhecimento exclusivamente por e-mail. O endpoint do fluxo hospedado POST /embed/v/{token}/recognize agora aceita apenas email no corpo; o campo cpf (antes opcional) foi descontinuado. O reconhecimento entre clientes usa o e-mail verificado como chave e envia o código de confirmação para esse mesmo e-mail — chave e canal de prova de posse coincidem. Sem impacto para quem usa a página hospedada (ela sempre pediu o e-mail); se você chamava o endpoint diretamente enviando cpf, passe a enviar email. Zero impacto no consumidor App EM.
1.66 12/06/2026 GET /api/v1/client/verification-sessions/{id} agora preenche final_tier para estudantes. Antes vinha null em sessões kind=student (o tier só aparecia no webhook ou em /client/students). Agora final_tier reflete o tier final da sessão independentemente do tipobronze/prata/ouro para médico, verified/verified_strong para estudante — e a resposta passa a incluir kind (student | physician). Você lê o resultado direto do GET, sem lookup adicional. Aditivo (médico inalterado; estudante deixa de vir null).
1.65 12/06/2026 Verificação de estudante — método documento mais flexível. O comprovante de matrícula agora aceita PDF (além de imagem). Selfie e documento com foto passam a ser opcionais: o tier verified é concedido a partir do comprovante (curso de Medicina + instituição reconhecida + nome conferido); enviar selfie + documento com foto eleva o resultado para verified_strong (identidade vinculada por biometria). Tudo acontece dentro da verificação hospedada — sem mudança na sua integração; apenas garanta que seu código trate verified_strong como estudante verificado (assim como verified).
1.64 09/06/2026 Verificação de estudante de medicina (identidade que evolui para médico). A verificação hospedada (POST /api/v1/client/verification-sessions) agora aceita kind: "student" (default "physician"). Numa sessão de estudante, a página hospedada oferece dois caminhos — e-mail institucional (código) ou comprovante de matrícula — e confirma que a pessoa é estudante de Medicina em instituição reconhecida. O tier resultante é verified (ou verified_strong com identidade jurídica forte). Liste os estudantes do seu tenant via GET /api/v1/client/students. Os webhooks verification.approved/verification.rejected passam a disparar também para estudantes, com kind: "student" no data. Ciclo de vida: quando o estudante obtém o CRM e se verifica como médico, a MESMA identidade Lastreo migra para médico (sai de /client/students, aparece em /client/doctors com tier bronze/prata/ouro). Guia completo no Fluxo 18.6. Zero impacto no consumidor App EM e no fluxo de médico (sessões sem kind continuam sendo de médico).
1.63 28/05/2026 Valores de tier de verificação agora são bronze / prata / ouro. Os campos que retornam o tier — final_tier (sessões de verificação hospedada), tier (webhooks verification.submitted/approved/rejected), verification_tier (médicos em GET /api/v1/client/doctors e no snapshot de compliance) — passam a emitir prata (antes basic) e ouro (antes strong). bronze é inalterado. As chaves de by_tier no snapshot de compliance passam de basic/strong para prata/ouro. Os nomes antigos continuam aceitos na ENTRADA (POST /client/doctors/{id}/verify-tier, override de admin): basic/silverprata, strong/goldouro. Ação necessária: se você compara o tier como string no seu lado (ex.: if (tier === "basic")), atualize para os novos valores prata/ouro.
1.62 28/05/2026 Endpoints de integração /client/* aceitam X-API-KEY (server-to-server). Antes só Bearer JWT de client_admin (dashboard). Agora os endpoints de integração — POST/GET /api/v1/client/verification-sessions, POST/GET /api/v1/client/doctors, POST /api/v1/client/doctors/{id}/verify-tier, GET /api/v1/client/verifications/usage, GET /api/v1/client/usage, GET /api/v1/client/usage/by-patient, GET /api/v1/client/compliance/snapshot — aceitam X-API-KEY: lk_... (a forma recomendada para o backend do seu sistema chamar o Lastreo: revogável, escopada ao tenant, sem credencial de login no servidor) ou Bearer JWT (dashboard). Crie a API key no dashboard em Developer → API Keys (mostrada uma vez). Endpoints de gerenciamento de conta (api-keys, webhooks, integrações, push-configs, devices) seguem exclusivos do dashboard via JWT — não se gerencia uma API key usando uma API key. Zero impacto no consumidor App EM.
1.61 28/05/2026 Correlação de webhooks de verificação por sessão (estilo client_reference_id do Stripe). Quando você cria uma sessão de verificação hospedada (POST /api/v1/client/verification-sessions), pode passar um client_user_ref — o identificador do médico no seu próprio sistema. A partir de agora, os webhooks de verificação originados daquela sessão carregam no data os campos session_id e client_user_ref, permitindo correlacionar o webhook ao seu usuário sem nenhum lookup reverso — independentemente da ordem em que o webhook e a resposta de criação chegam. session_id é exatamente o mesmo campo session_id (string pública vs_…) que o POST /client/verification-sessions devolveu no corpo da resposta — NÃO o id numérico (PK interna). Eventos afetados: verification.submitted, verification.approved, verification.rejected. Isolamento multi-tenant garantido: como o médico é uma entidade global (o mesmo CRM pode existir em vários clientes Lastreo), o evento de verificação é entregue a todos os clientes que conhecem aquele médico — mas session_id/client_user_ref são incluídos somente no webhook do cliente dono da sessão. Os demais clientes recebem o mesmo evento sem esses campos. Eventos que não vêm de uma sessão hospedada (ex.: cadastro bronze via POST /api/v1/client/doctors, verificação ICP-Brasil feita diretamente pelo médico) não trazem esses campos — continue usando o user_id do médico. Exemplo de data recebido pelo cliente dono: {"user_id": 42, "tier": "prata", "verified_crm": "123456", "verified_uf": "SE", "session_id": "vs_ab12cd34", "client_user_ref": "seu-sistema:medico:789"}. Nenhuma ação necessária se você não usa sessões hospedadas (campos só aparecem quando há client_user_ref na sessão).
1.60 28/05/2026 Billing de verificação por tier. Endpoints novos para client_admin: GET /api/v1/client/verifications/usage?days=N (contagem de verificações por tier no período + total, quota mensal do plano, overage e estimativa de billing mensal em BRL) e POST /api/v1/client/doctors/{doctor_id}/verify-tier com body {"tier": "bronze"\|"prata"\|"ouro"} (aliases legacy basic/strong/silver/gold também aceitos). Regra de cobrança: você paga pela verificação de um tier quando ela é produzida pela primeira vez para aquele médico; se ele já tem aquele tier (ou superior) porque já foi verificado antes na rede Lastreo, o reconhecimento é gratuito. Subir de tier conta como verificação nova. O verify-tier responde recognized (grátis), produz o tier na hora (bronze), ou needs_doctor_action para prata/ouro (o médico completa pelo fluxo próprio e a cobrança ocorre na aprovação). Preços vigentes em /docs-public/pricing.html. Zero impacto no consumidor App EM (endpoints do dashboard B2B).
1.59.1 27/05/2026 BYOK (chave de IA própria) passa a ser obrigatório. Todo tenant precisa configurar uma integração de IA em /dashboard/integrations/ (aba IA / Modelo) antes de usar o chat. Sem BYOK: o chat retorna um erro estruturado pedindo a configuração; POST /chat/send com upload de mídia retorna HTTP 422; e o resumo automático de conversa é silenciosamente omitido (o chat de texto segue funcionando). Para upload de mídia e resumo de conversa, a chave precisa ser de um provider compatível com a Files API do Gemini (openai_compatible apontando para o endpoint do Gemini, ou google_native); outros providers atendem o chat de texto mas não mídia/resumo. Zero impacto para quem já tem BYOK configurado.
1.59 27/05/2026 Lastreo Link — reuso da identidade verificada entre clientes. Um médico já verificado em qualquer cliente Lastreo pode confirmar a identidade em um cliente novo via código enviado por email e herda o tier na hora, sem reenviar documentos (opt-in explícito do médico, LGPD Art. 7). Endpoints do fluxo hospedado: POST /embed/v/{token}/recognize (informa o e-mail cadastrado, dispara o código), POST /embed/v/{token}/recognize/confirm (valida o código e herda a identidade — o webhook de aprovação carrega via_lastreo_link: true), POST /embed/v/{token}/link-consent (opt-in/opt-out do reuso). Efeito de rede: cada cliente novo amplia a base de médicos reconhecíveis pelos próximos. Zero impacto no consumidor App EM.
1.58 26/05/2026 Verificação hospedada (modal embed estilo Stripe Elements). Crie uma sessão via POST /api/v1/client/verification-sessions (recebe embed_url) e consulte o resultado via GET /api/v1/client/verification-sessions/{id}. A página hospedada é um wizard de 4 passos (identificação → carteira → selfie → resultado) com tema customizável (theme_primary_color), branding opcional (hide_branding, para white-label) e redirect ao concluir (completion_redirect_url). SDK JS drop-in em /dashboard/sdk/lastreo.js (Lastreo({embedUrl}).mount(...) ou .openModal(...)). A foto da carteira e a selfie vão direto para o Lastreo — nunca passam pelo seu backend. Sob LGPD, você deixa de ser controlador do dado biométrico. Zero impacto no consumidor App EM.
1.57 26/05/2026 Verificação prata com decisão automática. A submissão de tier prata (POST /doctors/me/verification/basic/submit) passa por uma avaliação automática que pode aprovar, rejeitar ou encaminhar para revisão humana — sem que documento ou biometria saiam da infraestrutura Lastreo (zero data egress). Os webhooks verification.approved / verification.rejected passam a carregar auto_approved / auto_rejected e um indicador de confiança da decisão. Nenhum subprocessador novo; nenhum dado sai do servidor Lastreo. Zero impacto no consumidor App EM.
1.56 26/05/2026 Compliance snapshot. Novo endpoint GET /api/v1/client/compliance/snapshot retorna uma prova-de-tratamento estruturada (médicos por tier, registros oficiais consultados com data da última atualização, atividade de auditoria do período, DSRs e incidentes, atestações LGPD) — um JSON que você pode anexar a contratos comerciais ou apresentar em inquérito da ANPD. Acompanha reorganização do dashboard B2B em torno de verificação + compliance. Zero impacto no consumidor App EM.
1.55 26/05/2026 Refinamento interno da verificação bronze (melhor detecção de registros profissionais com status irregular). Sem mudança de contrato da API. Zero impacto no consumidor.
1.54 26/05/2026 Cadastro de médico pelo cliente B2B com verificação automática. POST /api/v1/client/doctors (role client_admin): envie {full_name, crm, uf, specialty?, email?} e o médico é criado já com tentativa de verificação automática. Se elegível, retorna verification_tier=bronze + status=approved em instantes; caso contrário fica pendente para prata/ouro. A resposta inclui bronze_attempted, bronze_eligible e bronze_reason para você decidir o fluxo. Cadastros repetidos do mesmo médico (por email ou por CRM/UF) atualizam em vez de duplicar. Zero impacto no consumidor existente (endpoint novo).
1.53 26/05/2026 Tier bronze — verificação automática sem documento físico. Novo tier bronze (abaixo de basic/strong). Endpoint POST /api/v1/doctors/me/verification/bronze (rate-limited): cruza o CRM/UF declarados com registros oficiais e aprova na hora quando há correspondência sem pendências, derivando a especialidade automaticamente. Casos que não passam seguem para os fluxos prata/ouro. O webhook verification.approved pode agora trazer tier=bronze. Zero impacto no consumidor existente (tier novo; basic/strong inalterados).
1.52 25/05/2026 Ferramentas internas de apoio à revisão de verificações prata (uso administrativo Lastreo). Endpoints internos apenas para admin; zero impacto no consumidor App EM.
1.51 24/05/2026 Configuração de push (FCM) por evento. Endpoints /api/v1/client/*: GET /push-configs (catálogo de eventos alert.created + medication_reminder.due com a config do tenant), PUT /push-configs/{event_type} (enabled + custom_title/custom_body opcionais), DELETE /push-configs/{event_type} (volta ao default), GET /devices (device tokens FCM dos usuários do tenant), POST /push-test (push de teste para um device). Eventos de médico (verification.approved/rejected) não são configuráveis (médico é global; push sempre dispara). Gerenciável em /dashboard/events/. Zero impacto no consumidor App EM (default enabled=true preserva o comportamento atual).
1.50 24/05/2026 Push nativo (FCM) em aprovação/rejeição de verificação. Quando a verificação de um médico é aprovada ou rejeitada, o Lastreo dispara push para o device token registrado (POST /api/v1/users/me/device-tokens), com data {type:"verification", approved, tier, doctor_user_id} para deep-link. O webhook verification.rejected passou a ser emitido também (antes só o approved). Zero impacto no consumidor App EM (sem device token, vira no-op).
1.49 24/05/2026 Mudança interna de configuração de autenticação serviço-a-serviço. SERVICE_API_KEY continua válida indefinidamente. Zero impacto no consumidor App EM.
1.48 24/05/2026 Atribuição de uso de IA por tenant e por paciente. GET /api/v1/client/usage passa a refletir corretamente o consumo do tenant (inclui chamadas de médico atendendo paciente do tenant). Endpoint novo GET /api/v1/client/usage/by-patient?days=N&limit=M retorna ranking de pacientes por consumo de IA + bloco unattributed para chamadas sem paciente-alvo. Zero impacto no consumidor App EM (analytics).
1.47 20/05/2026 Painel de integrações BYOK + visibilidade de médicos. /dashboard/integrations/ com abas IA / WhatsApp / Telegram (forms não-destrutivos — o segredo só é atualizado se preenchido). Página /dashboard/doctors/ read-only: a verificação de médico é centralizada no Lastreo (1 CRM = 1 médico, entidade global); o cliente recebe o resultado por webhook, mas não aprova/rejeita. Endpoint GET /api/v1/client/doctors lista os médicos verificados que atendem pacientes do tenant (com verification_status, verification_tier, verified_crm, verified_uf, verified_specialty, patient_count_in_tenant). Zero impacto no consumidor App EM.
1.46 20/05/2026 Roteamento de webhook de mensageria por tenant (BYOK). O webhook do WhatsApp passa a identificar o tenant pelo phone_number_id do payload e validar a assinatura com o segredo do próprio tenant. Endpoint novo /webhooks/telegram/{path_token} por tenant. O envio de mensagens usa as credenciais do tenant. Suporte a mais um provider de IA. Zero impacto no App EM (sem integração própria, segue no padrão).
1.45 20/05/2026 BYOK — Bring Your Own Key (Fase 1). Cliente pluga a própria chave de IA (OpenAI / Mistral / modelo local compatível com OpenAI / Gemini) e o chat passa a rodar nela. Endpoints /api/v1/client/integrations/{ai,whatsapp,telegram} (GET/PUT/DELETE), com os segredos criptografados at rest. Zero impacto no consumidor App EM.
1.44 20/05/2026 Páginas públicas + request access. Páginas em /docs-public/: pricing, legal (ToS + DPA + AUP + Privacy), request-access. Endpoint público POST /api/v1/public/access-request (rate-limited, sem auth, com anti-spam). Endpoints admin para revisar pedidos. Zero impacto no consumidor App EM.
1.43 (frontend) 20/05/2026 Dashboard self-service B2B (frontend). https://lastreo.com/dashboard/ — login + páginas de overview, API keys, webhooks, uso, erros e configurações. Zero impacto no consumidor App EM.
1.43 20/05/2026 Dashboard self-service B2B (backend). Role client_admin + endpoints /api/v1/client/* para o cliente gerenciar o próprio tenant: /me, /api-keys (CRUD + revoke), /webhooks (CRUD + deliveries + retry + test), /usage, /errors. Zero impacto no consumidor App EM.
1.42 20/05/2026 Ambiente sandbox. https://lastreo.com/sandbox/ — isolado de produção, com stubs para IA/FCM/email/mensageria (não enviam de verdade). Troque a base URL e teste fluxos completos sem afetar produção nem consumir cota de IA. Zero impacto no consumidor App EM (produção segue em /api/v1/...).
1.41 19/05/2026 Status page + changelog público. /docs-public/status.html e /docs-public/changelog.html. Endpoint público GET /status agrega estado operacional + estatísticas de webhook 24h + incidentes recentes (sem expor detalhes sensíveis). Zero impacto no consumidor.
1.40 19/05/2026 Webhooks B2B. Cada cliente configura webhooks (URL + segredo + lista de eventos). Assinatura HMAC SHA-256 no header X-Lastreo-Signature: t=<ts>,v1=<hex> — valide com o seu segredo. Retry em 1m/5m/30m/2h/6h (5 tentativas). Eventos publicáveis: verification.approved/rejected/submitted, alert.created, assessment.created, symptom.recorded, medication_reminder.due, patient.created/merged/deleted, dsr.created, incident.notified. Zero impacto no consumidor App EM (sem webhook configurado, sem efeito).
1.39 19/05/2026 Observabilidade interna (rastreamento de erros, uso administrativo Lastreo). Zero impacto no consumidor.
1.38 19/05/2026 Segurança técnica. Dados sensíveis (CPF, telefone) criptografados em repouso; TLS no banco de dados; backup automatizado e criptografado com retenção. Endpoints GET /health (liveness) e GET /health/ready (readiness com checagem de DB). Zero impacto no consumidor.
1.37 19/05/2026 Consent tracking versionado (LGPD Art. 8 + 18 IX). Endpoints públicos: GET /consents/current (versão vigente por tipo) e GET /consents/{type}/{version} (conteúdo). Titular: POST /users/me/consents, POST /users/me/consents/{id}/revoke, GET /users/me/consents. Auto-consent no /auth/register para documentos vigentes. Zero impacto no consumidor.
1.36 19/05/2026 Notificação de incidente de segurança (LGPD Art. 48). O Lastreo, como operador, notifica os clientes afetados por um incidente de dados; o webhook incident.notified sinaliza o cliente em tempo real. Zero impacto no consumidor.
1.35 19/05/2026 Direitos do titular automatizados (LGPD Art. 18 + 20). Endpoints: POST /data-subject-requests (titular cria; alguns tipos são processados automaticamente), GET /users/me/data-subject-requests, GET /data-subject-requests/{id}; a fila é gerida pelo admin. GET /subprocessors lista pública de sub-operadores (Art. 18 VII). 9 direitos cobertos. Zero impacto no consumidor.
1.34 19/05/2026 Expansão do registro de auditoria interno em rotas críticas (forense + LGPD). Zero impacto no consumidor.
1.33 19/05/2026 Registro de auditoria (base de compliance LGPD). Endpoints: GET /admin/audit-log (admin) e GET /users/me/audit-log (titular — LGPD Art. 18 II + VII). Ações sensíveis ficam registradas com ator, alvo e timestamp, de forma imutável. Zero impacto no consumidor App EM.
1.32 19/05/2026 Isolamento cross-tenant aplicado em todos os endpoints clínicos secundários (assessments, health-registries, alerts, medication-reminders, exports, dashboards, gestão de pacientes). Zero impacto no consumidor App EM — as queries seguem retornando os mesmos resultados; acesso cross-tenant retorna 404.
1.31 19/05/2026 Paciente passa a ser escopado por cliente. Zero impacto no consumidor App EM: listagens e leituras de paciente filtram pelo cliente atual; acesso cross-tenant retorna 404. Médico permanece global (1 CRM = 1 conta Lastreo). Email de paciente único por cliente; email de médico único globalmente.
1.30 19/05/2026 Fundação multi-tenant interna. Zero impacto no consumidorX-API-KEY continua idêntico; nenhum endpoint mudou shape de request/response. Compromisso de estabilidade /v1 documentado.
1.29 19/05/2026 Verificação profissional de médicos em dois caminhos: ouro (assinatura digital ICP-Brasil AR-CFM, aprovação imediata e automatizada) e prata (envio de foto da carteira CRM + selfie para análise manual em até 24h). verification_tier (strong/basic/null) adicionado a UserOut e ao status de verificação. Caminho ouro: POST /doctors/me/verification/terms (sem body — usa full_name do perfil), POST /doctors/me/verification/submit, GET /doctors/me/verification/status. Caminho prata: POST /doctors/me/verification/basic/submit, GET /doctors/me/verification/basic. Ver Fluxo 17
1.28 14/04/2026 Perfil: UserOut agora inclui phone_number, date_of_birth, biological_sex, cpf, address_city, address_state, crm e medical_specialty (todos opcionais). Novos endpoints: PATCH /users/me (usuário edita próprio perfil), PATCH /doctors/me/patients/{id} (médico edita paciente provisório), POST /auth/change-email + POST /auth/confirm-email-change (troca de email autenticada com código de confirmação)
1.27 05/04/2026 Pacientes: médico agora pode remover paciente da lista (DELETE /doctors/me/patients/{id}). Se o paciente for provisório, é apagado junto com todos os seus dados clínicos; se for real, apenas desassocia (conta preservada)
1.26 04/04/2026 Pacientes: médico pode criar paciente provisório com apenas o nome (POST /doctors/me/patients/provisional) e mesclar com conta real posteriormente (POST /doctors/me/patients/{id}/merge). UserOut agora inclui is_provisional e email pode ser null. Bugfixes no pipeline de chat: tool calling corrigido, unicode corrigido em respostas de ferramentas, mensagens internas filtradas do histórico
1.25 11/03/2026 Chat: arquitetura split send + SSE — POST /send retorna imediatamente com ID, resposta da IA via GET /stream (Server-Sent Events). Suporte a local_id para idempotência e correlação cliente-servidor
1.24 10/03/2026 Chat: paginação por cursor (before_id/before), ordenação DESC (mais recente primeiro). Auth: endpoint de alteração de senha (change-password)
1.23 10/03/2026 Base URL atualizada para HTTPS com domínio estável (lastreo.com)
1.22 10/03/2026 Migração de servidor: nova Base URL, seção de conexão adicionada
1.21 02/03/2026 Push Notifications (FCM): Fluxo 16 — gerenciamento de device tokens para notificações push nativas Android/iOS
1.20 25/02/2026 Chat In-App: documentação sobre gerenciamento de contexto de conversa (janela deslizante + resumo automático)
1.16 20/02/2026 Chat In-App (POST /send, GET /history, DELETE /history — alternativa REST ao WhatsApp/Telegram para chat direto no App EM)
1.15 20/02/2026 Alertas clínicos (API + threshold automático + notificação médicos), lembretes de medicação (CRUD + scheduler), 4 novos tipos Health Connect (SLEEP, NUTRITION, HYDRATION, HEART_RATE), export FHIR R4
1.14 20/02/2026 Health Registries: upsert via external_id (deduplicação Health Connect), DELETE individual e DELETE ALL (LGPD)
1.13 19/02/2026 Adicionados: Fluxo 10 (Analytics e Dashboards — dashboard do médico, tendências de sintomas, correlação saúde×exercício), Fluxo 11 (Export de Dados Clínicos — CSV e PDF)
1.12 19/02/2026 Adicionado: Fluxo 9 (Verificação de Email), campo email_verified na resposta do usuário, envio automático de código de verificação no registro
1.11 13/02/2026 Melhorias de performance e estabilidade no processamento de mensagens
1.10 13/02/2026 Adicionados: Fluxo 7 (Registros de Saúde / Health Connect), Fluxo 8 (Recuperação de Senha), endpoints de batch e summary para health registries
1.09 08/12/2025 Adicionados: campos EDSS atualizados, Fluxo 5 e 6 (Paciente e Médico)

Base URL

https://lastreo.com

Todos os endpoints deste documento são relativos a esta URL. Exemplo: POST /auth/loginPOST https://lastreo.com/auth/login

Nota: Conexões HTTP são automaticamente redirecionadas para HTTPS.

Estabilidade da API e compromisso com o consumidor

A partir da v1.30, o Lastreo é uma API B2B multi-tenant. Internamente, requisições são identificadas por aplicação cliente (via X-API-KEY), mas isso é transparente para o consumidor — seu código não precisa mudar para acompanhar essa evolução.

Compromissos hard que valem para qualquer release até o fim da vida da v1:

2. Primeiros Passos (Guia Rápido para Desenvolvedores)

Para começar a testar a API, siga estes dois passos simples para criar uma conta de teste e vincular seu canal de mensagens.

1. Crie sua Conta de Desenvolvedor: * Use o endpoint POST /auth/register (descrito no Fluxo 1) para criar uma nova conta de paciente para você. * Após o registro, faça login com POST /auth/login para obter seu access_token e refresh_token. Você precisará deles para gerenciar a sessão.

2. Vincule seu Canal de Mensagens: * Com seu access_token em mãos, siga as instruções do Fluxo 2, escolhendo o guia específico para a plataforma que deseja vincular (Telegram ou WhatsApp).

3. Conceitos Fundamentais

Para entender como o Lastreo funciona, é importante conhecer alguns conceitos centrais da plataforma.

3.1. Perfis de Usuário

Existem dois tipos principais de usuários no sistema: * Paciente (paciente): O perfil padrão. Representa o indivíduo cujos dados de saúde estão sendo monitorados. Pacientes podem registrar seus próprios sintomas e avaliações. * Médico (medico): Um profissional de saúde. Este perfil tem permissões elevadas para visualizar os dados dos pacientes aos quais está associado e registrar avaliações clínicas, como a EDSS.

3.2. Contas Provisórias (Onboarding via Bot)

O Lastreo permite que um novo usuário comece a interagir com o bot no WhatsApp ou Telegram antes mesmo de criar uma conta completa no aplicativo. * Quando uma mensagem de um novo número é recebida, o sistema cria automaticamente uma conta provisória. * O usuário pode imediatamente começar a registrar sintomas e usar as funcionalidades básicas do bot. * Posteriormente, ao criar uma conta no aplicativo, o usuário pode "reivindicar" seu histórico de conversas através de um processo de verificação, unificando a conta provisória com sua nova conta completa (ver Fluxo 3).

3.3. Canais de Contato e Papéis

Um único usuário pode interagir com o Lastreo através de múltiplos canais (ex: chat in-app, WhatsApp e Telegram). Para máxima flexibilidade, especialmente para profissionais de saúde: * Papel por Canal (channel_role): Um usuário com perfil de medico pode designar um papel específico para cada canal que vincula. * Exemplo: Um médico pode vincular seu WhatsApp pessoal com channel_role: "paciente" para monitorar sua própria saúde, e vincular seu Telegram de trabalho com channel_role: "medico" para interagir com o Lastreo sobre seus pacientes. * O bot Lastreo adaptará sua persona e suas funcionalidades com base no papel do canal que iniciou a conversa.

3.5. Verificação de Email (Novo na v1.12)

O Lastreo implementa verificação de email para garantir que os usuários possuem acesso ao email cadastrado. A verificação não bloqueia o acesso ao sistema — o usuário pode fazer login, acessar seu perfil, usar o chatbot, registrar sintomas, assessments e health registries normalmente.

Funcionalidades que requerem email verificado: * Vincular canais de contato (WhatsApp/Telegram) — Fluxos 2 e 3 * Funcionalidades exclusivas de médico (associar pacientes, etc.)

Funcionalidades que NÃO requerem email verificado: * Login, perfil, chat in-app, chatbot via mensageiros, sintomas, assessments, health registries

O campo email_verified (booleano) é retornado na resposta do GET /api/v1/users/me e indica se o email do usuário foi verificado. Ver Fluxo 9 para os endpoints de verificação.

3.4. Uma Estrutura Flexível para Dados de Saúde

O Lastreo utiliza dois modelos de dados para registros de saúde:

Os registros de saúde são salvos de forma granular (cada caminhada individual, cada sessão). A agregação (soma de passos por dia, média semanal) é feita na consulta via endpoint de summary.

4. Fluxos da API (Referência Técnica)

Fluxo 1: Autenticação de Usuário

Este fluxo descreve o ciclo de vida completo da autenticação, incluindo o login e a renovação de sessão.

1.1. Registro de Novo Usuário

1.2. Login de Usuário

1.3. Uso do Access Token

1.4. Gerenciamento de Sessão e Renovação de Token (Refresh Token)

Para equilibrar segurança e uma boa experiência de usuário, utilizamos um sistema de dois tokens.

Fluxo de Renovação (Ação do Frontend):

  1. Armazenamento: Após o login, o access_token pode ser guardado em memória, enquanto o refresh_token deve ser armazenado de forma segura e persistente no dispositivo (ex: Keychain/Keystore).

  2. Detecção de Expiração: Quando uma chamada à API falhar com o status 401 Unauthorized, o frontend deve assumir que o access_token expirou.

  3. Renovação Silenciosa: Em vez de deslogar o usuário, o frontend deve fazer uma chamada para o novo endpoint de renovação:

    • Endpoint: POST /auth/refresh
    • Corpo da Requisição: json { "refresh_token": "<o_refresh_token_salvo_no_dispositivo>" }
  4. Recebimento de Novos Tokens: O backend responderá com um novo par de access_token e refresh_token.

    • Resposta de Sucesso: json { "access_token": "NOVO_eyJ...", "refresh_token": "NOVO_a1b2c3d4...", "token_type": "bearer" }
  5. Atualização e Retentativa: O frontend deve substituir os tokens antigos pelos novos e, em seguida, tentar novamente a chamada original à API que havia falhado.

  6. Falha na Renovação: Se a chamada para /auth/refresh também falhar com 401, significa que a sessão do usuário realmente expirou. Neste caso, o usuário deve ser deslogado e redirecionado para a tela de login.

1.5. Troca de Email (Novo na v1.28)

A alteração do email associado à conta é feita em duas etapas (solicitação + confirmação por código enviado ao novo email), protegendo contra mudanças acidentais ou mal-intencionadas. O endpoint PATCH /users/me não permite trocar email — use este fluxo.

Resumo para o frontend: após confirm-email-change retornar 200, limpe os tokens locais e redirecione para a tela de login.


Fluxo 2: Vinculação de Canal de Contato

Este fluxo é iniciado pelo usuário dentro do aplicativo.

Princípio: O usuário deve iniciar a conversa com o bot. A confirmação é feita inteiramente dentro do Telegram.

2.2. Vinculação via WhatsApp (Fluxo com Código de Verificação)

Princípio: O backend pode iniciar uma conversa enviando um código para o usuário.


Fluxo 3: Onboarding do Bot e Reivindicação de Conta

Distinção Importante: Este fluxo é diferente da "Vinculação de Canal" (Fluxo 2). * Vinculação (Fluxo 2): Para um usuário que já tem uma conta completa e quer adicionar um novo canal de contato que nunca foi usado antes. * Reivindicação (Fluxo 3): É uma ação única para um usuário que acabou de criar sua conta completa e quer "puxar" o histórico de um canal que ele já usava com uma conta provisória.

Este fluxo conecta o histórico de um usuário que começou pelo bot a uma conta completa criada no aplicativo.

Tratamento de Conflito (Número Reciclado)

Se o usuário tentar vincular um número que já possui uma conta provisória (retorno 400), o frontend deve oferecer duas opções:

  1. Importar Histórico: Segue o fluxo de Reivindicação descrito acima.
  2. Começar do Zero (Número Reciclado): Se o usuário disser que não quer os dados antigos (ex: comprou um chip novo), o frontend deve chamar novamente o endpoint de Vinculação (/link-confirm), mas adicionando o campo "force_link": true.
    • Isso apagará a conta provisória antiga e vinculará o número à conta atual do usuário, garantindo a privacidade e limpando dados de terceiros.

Fluxo 4: Registro de Dados Clínicos

Este é o fluxo principal para registrar qualquer tipo de avaliação de saúde.


Fluxo 5: Funcionalidades do Paciente

Endpoints para um paciente gerenciar sua própria conta e visualizar seus dados.


Fluxo 6: Funcionalidades do Médico

Endpoints para um médico gerenciar e visualizar os dados de seus pacientes.


Fluxo 7: Registros de Saúde (Health Connect) (Atualizado na v1.17)

Este fluxo gerencia dados de saúde contínuos vindos do Health Connect. Tipos suportados: STEPS, EXERCISE_SESSION, SLEEP, NUTRITION, HYDRATION, HEART_RATE. Os registros são armazenados de forma granular — cada caminhada individual ou sessão de exercício é um registro separado.

Formato flat (v1.17): Todos os dados são enviados em formato flat dentro de data, sem wrappers intermediários. O campo data.uid é usado como chave de upsert (deduplicação automática) e data.last_modified para resolução de conflito de versão.

7.1. Enviar um Registro de Saúde (Individual / Upsert)

7.2. Enviar Registros em Lote (Batch)

Para sincronização eficiente, especialmente quando o Health Connect acumula vários registros entre sincronizações.

7.3. Listar Registros de Saúde (com Filtros)

7.4. Resumo Agregado (Summary)

Retorna totais agregados por período, ideal para gráficos e dashboards.

7.5. Remover um Registro de Saúde por UID (Atualizado na v1.17)

Remove um registro de saúde específico pelo uid (o mesmo valor usado no data.uid na criação).

7.6. Remover TODOS os Registros de Saúde (LGPD)

Remove todos os registros de saúde de um paciente. Útil para compliance com LGPD (direito ao apagamento).


Fluxo 8: Recuperação de Senha (Novo na v1.10)

Permite que um usuário redefina sua senha caso a tenha esquecido.

8.1. Solicitar Código de Recuperação

8.2. Redefinir Senha com Código

Fluxo Completo para o Frontend (Esqueci a Senha): 1. Usuário clica em "Esqueci minha senha" na tela de login. 2. Frontend solicita o email e chama POST /auth/forgot-password. 3. Exibe tela para inserir o código de 6 dígitos. 4. Usuário insere o código + nova senha, frontend chama POST /auth/reset-password. 5. Redireciona para login em caso de sucesso.

8.3. Alterar Senha (Usuário Autenticado) (Novo na v1.24)

Para quando o usuário sabe a senha atual e deseja trocá-la (ex: tela de configurações do app).

Fluxo Completo para o Frontend (Alterar Senha): 1. Na tela de configurações, usuário clica em "Alterar senha". 2. Frontend solicita senha atual + nova senha + confirmação da nova senha. 3. Frontend chama POST /auth/change-password com Bearer Token. 4. Exibe mensagem de sucesso ou erro.


Fluxo 9: Verificação de Email (Novo na v1.12)

A verificação de email confirma que o usuário possui acesso ao email cadastrado. Um código de verificação é enviado automaticamente após o registro (Fluxo 1.1). O usuário também pode solicitar um novo código a qualquer momento.

9.1. Solicitar Código de Verificação

9.2. Verificar Email com Código

Fluxo Completo para o Frontend: 1. Após o registro, o backend já envia automaticamente um código de verificação. 2. Frontend exibe tela para inserir o código de 6 dígitos (pode ser na primeira tela após o registro ou em configurações). 3. Usuário insere o código, frontend chama POST /auth/verify-email. 4. Em caso de sucesso, atualizar o estado local do email_verified para true. 5. Se o código expirou, o usuário pode solicitar um novo com POST /auth/send-verification.

Nota: A verificação de email não é bloqueante — o usuário pode navegar e usar a maioria das funcionalidades sem verificar. A verificação é necessária apenas para vincular canais (WhatsApp/Telegram) e funcionalidades de médico. Ver seção 3.5 para detalhes.


Fluxo 10: Analytics e Dashboards (Novo na v1.13)

Endpoints para visualização de dados agregados, tendências e correlações. Úteis para dashboards no app.

10.1. Dashboard do Médico

Visão geral consolidada dos pacientes do médico: totais, atividade recente e últimos sintomas reportados.

10.2. Tendências de Sintomas do Paciente

Análise de tendências: sintomas mais frequentes e evolução ao longo do tempo.

10.3. Correlação Exercício × Sintomas

Cruza dados de exercício (passos + sessões) com sintomas no mesmo período, permitindo visualizar se atividade física impacta os sintomas.


Fluxo 11: Export de Dados Clínicos (Novo na v1.13)

Endpoints para exportar dados do paciente em formatos padrão (CSV e PDF). Úteis para compartilhar com outros profissionais ou para backup.

11.1. Exportar Sintomas em CSV

11.2. Relatório Clínico Completo em PDF

Gera um relatório profissional em PDF com todos os dados clínicos do paciente.


Fluxo 12: Alertas Clínicos (Novo na v1.15)

Sistema de alertas para notificar médicos sobre eventos clínicos relevantes. Alertas são gerados automaticamente pelo sistema e os médicos associados ao paciente são notificados.

12.1. Tipos de Alerta

Cada alerta possui um campo source que indica sua origem:

E um campo severity com três níveis: baixa, media, alta.

12.2. Listar Alertas do Médico

12.3. Contagem de Alertas Não-Lidos (Badge)

Ideal para exibir um badge/contador no app.

12.4. Marcar Alerta Como Lido

12.5. Listar Alertas de um Paciente


Fluxo 13: Lembretes de Medicação (Novo na v1.15)

CRUD para gerenciar lembretes de medicação. O paciente recebe lembretes automaticamente nos horários configurados via seus canais ativos (WhatsApp/Telegram).

13.1. Criar Lembrete de Medicação

13.2. Listar Lembretes de Medicação

13.3. Atualizar Lembrete de Medicação

13.4. Deletar Lembrete de Medicação


Fluxo 14: Export FHIR R4 (Novo na v1.15)

Export de dados clínicos em formato FHIR R4 (Fast Healthcare Interoperability Resources). Útil para interoperabilidade com sistemas de saúde e prontuários eletrônicos.

14.1. Exportar Bundle FHIR


Fluxo 15: Chat In-App (v1.16 — Multimédia na v1.19)

Interface de chat REST integrada ao aplicativo, como alternativa ao WhatsApp/Telegram. O chat in-app utiliza a mesma inteligência artificial e as mesmas ferramentas disponíveis nos outros canais. A diferença é que a resposta é retornada diretamente na resposta HTTP, sem necessidade de plataformas externas.

Características: * Canal in_app criado automaticamente no primeiro uso — não precisa de vinculação manual * Mesma IA, mesmas ferramentas, mesmo histórico persistente * Resposta síncrona via HTTP (sem dependência de WhatsApp/Telegram) * Proteção contra mensagens simultâneas (lock per-user) * Suporte multimédia: imagens, documentos (PDF), áudio e vídeo

Gerenciamento de Contexto da Conversa:

A IA mantém o contexto da conversa utilizando uma janela deslizante com as mensagens mais recentes. Conforme a conversa avança, o contexto mais antigo é automaticamente resumido e preservado, garantindo que informações importantes não sejam perdidas mesmo em conversas longas. Isso é totalmente transparente para o usuário — a IA sempre tem acesso ao contexto relevante da conversa.

Ao limpar o histórico do chat (DELETE /api/v1/chat/history), todo o contexto é removido, incluindo os resumos acumulados. A próxima conversa começa do zero, sem nenhuma referência a interações anteriores.

15.1. Enviar Mensagem no Chat

15.2. Receber Resposta da IA (SSE)

15.4. Mídia no Chat — Modelo de Cache Local

O Lastreo não armazena arquivos de mídia no servidor. Ao enviar um arquivo via /chat/send, o servidor processa o conteúdo (envia à IA para análise), salva apenas os metadados no banco (id, filename, content_type, category, size) e descarta os bytes.

Responsabilidade do frontend: 1. Ao enviar mídia com sucesso, salvar o arquivo localmente no dispositivo, indexado pelo media.id retornado na resposta do /chat/send. 2. Ao exibir o histórico, verificar se o media.id existe no cache local: * Se existir: exibir o arquivo (thumbnail, player de áudio/vídeo, preview de PDF). * Se não existir (cache limpo, troca de dispositivo): exibir placeholder — ex: "📎 exame_ressonancia.jpg (imagem, 245 KB) — arquivo disponível apenas no dispositivo original". 3. Mensagens da IA que analisaram mídia incluem o contexto da análise no texto da resposta, então o conteúdo semântico não se perde mesmo sem o arquivo.

Por que este modelo: * Zero consumo de armazenamento no servidor * Conformidade LGPD simplificada (dados sensíveis permanecem no dispositivo do usuário) * Mesmo modelo utilizado por WhatsApp, Telegram e Signal

Não existe endpoint GET /chat/media/{id} — arquivos não são servidos pelo servidor.

15.5. Obter Histórico do Chat

Query Parameters (todos opcionais):

Parâmetro Tipo Padrão Descrição
limit int 50 Número máximo de mensagens por página (1–200)
before_id int Retorna mensagens com id menor que este valor (cursor recomendado)
before ISO 8601 Retorna mensagens com timestamp anterior a este valor

Paginação por cursor: Na primeira chamada, não passe nenhum cursor. A resposta inclui next_cursor_id — passe-o como before_id na próxima chamada para carregar a página seguinte (mensagens mais antigas). Repita até has_more: false.

15.6. Limpar Histórico do Chat (LGPD)

Fluxo Completo para o Frontend: 1. Ao abrir a tela de chat, carregar a primeira página com GET /api/v1/chat/history?limit=30 (mensagens mais recentes primeiro). 2. Quando o usuário fizer scroll para cima e has_more for true, carregar a próxima página com GET /api/v1/chat/history?limit=30&before_id={next_cursor_id}. 3. Para enviar mensagem: 1. Gerar um local_id único (ex: UUID) para a mensagem. 2. Exibir a mensagem do usuário na UI imediatamente (optimistic rendering). 3. Chamar POST /api/v1/chat/send com text, file (opcional) e local_id. 4. Ao receber a resposta 200, substituir o local_id temporário pelo id real retornado pelo servidor. 5. Imediatamente conectar ao GET /api/v1/chat/stream?token=<jwt> via EventSource. 6. Exibir indicador de "digitando..." enquanto recebe eventos status: processing. 7. Ao receber message_complete, exibir a resposta da IA e fechar a conexão SSE. 8. Se receber error, exibir mensagem de erro e fechar a conexão. 4. Se receber 409 no /chat/send, aguardar 2-3 segundos e retentar automaticamente (outra mensagem está em processamento). 5. Reenvio (retry): Se a rede falhar durante o envio, reenviar com o mesmo local_id. O servidor detecta a duplicata e retorna status: "accepted" sem reprocessar. 6. Fallback: Se a conexão SSE cair antes de receber a resposta, a IA continua processando. A resposta estará disponível via GET /chat/history na próxima consulta. 7. Se media estiver presente na resposta do send, salvar o arquivo localmente no dispositivo indexado pelo media.id (ver seção 15.4 — o servidor não armazena nem serve arquivos de mídia).

Nota sobre canais: O canal in_app é criado automaticamente e não pode ser vinculado manualmente via Fluxo 2. A vinculação manual é apenas para WhatsApp e Telegram.


Fluxo 16: Device Tokens (Push Notifications) (Novo na v1.21)

O App EM pode registrar um token FCM (Firebase Cloud Messaging) para receber notificações push nativas no dispositivo Android ou iOS. Notificações são enviadas automaticamente em dois eventos:

  1. Alerta clínico gerado — o médico recebe notificação push dos alertas dos seus pacientes.
  2. Lembrete de medicação — o paciente recebe notificação no horário configurado.

O token deve ser registrado após o login e re-registrado sempre que o FCM SDK gerar um novo token (ex: reinstalação do app, limpeza de dados). Um usuário pode ter múltiplos tokens ativos simultaneamente (um por dispositivo).


16.1 Registrar Token de Dispositivo

POST /api/v1/users/me/device-tokens

Registra ou atualiza um token FCM para o usuário logado. Se o token já existir no banco (ex: outro usuário fez login no mesmo dispositivo), ele é reatribuído ao usuário atual (upsert por token).

Autenticação: Bearer Token obrigatório.

Request Body:

{
  "token": "fcm_token_gerado_pelo_sdk",
  "platform": "android"
}
Campo Tipo Obrigatório Descrição
token string Sim Token FCM gerado pelo Firebase SDK
platform string Sim Plataforma: "android" ou "ios"

Response 201 Created:

{
  "id": 42,
  "platform": "android",
  "created_at": "2026-03-02T12:00:00Z"
}

Guarde o id retornado — ele é necessário para desregistrar o token no logout.

Erros: - 401 Unauthorized — Não autenticado. - 422 Unprocessable Entityplatform inválido (aceita apenas "android" ou "ios").


16.2 Desregistrar Token de Dispositivo

DELETE /api/v1/users/me/device-tokens/{token_id}

Remove o token FCM do banco. Deve ser chamado no logout ou quando o usuário desativar notificações.

Autenticação: Bearer Token obrigatório.

Parâmetro Tipo Descrição
token_id integer ID do token retornado no registro (campo id)

Response 204 No Content

Erros: - 401 Unauthorized — Não autenticado. - 404 Not Found — Token não encontrado ou pertence a outro usuário.


16.3 Setup Android (Firebase Messaging)

Passo a passo para configurar o Firebase Cloud Messaging no projeto Android.

Pré-requisito: O arquivo google-services.json (fornecido separadamente) deve estar na pasta app/ do projeto.

1. build.gradle (nível do projeto):

plugins {
    // ... outros plugins
    id("com.google.gms.google-services") version "4.4.4" apply false
}

2. build.gradle (nível do app):

plugins {
    id("com.android.application")
    id("com.google.gms.google-services")  // deve ser o último plugin
}

dependencies {
    // Firebase BoM (gerencia versões automaticamente)
    implementation(platform("com.google.firebase:firebase-bom:34.10.0"))
    implementation("com.google.firebase:firebase-messaging")
}

3. AndroidManifest.xml — registrar o serviço:

<service
    android:name=".LastreoFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

4. Implementar o serviço (LastreoFirebaseMessagingService.kt):

class LastreoFirebaseMessagingService : FirebaseMessagingService() {

    // Chamado quando o Firebase gera/renova o token
    override fun onNewToken(token: String) {
        super.onNewToken(token)
        // Enviar o novo token ao backend:
        // POST /api/v1/users/me/device-tokens { token, platform: "android" }
        // Se havia um token anterior, o backend faz upsert automaticamente
    }

    // Chamado quando uma notificação chega com o app em foreground
    override fun onMessageReceived(message: RemoteMessage) {
        super.onMessageReceived(message)

        // message.data contém os campos enviados pelo backend:
        // - "alert_id", "patient_id", "source" (para alertas clínicos)
        // - "reminder_id", "type" (para lembretes de medicação)

        // Exibir notificação local ou atualizar a UI
    }
}

5. Obter o token no login (na Activity/ViewModel):

FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
    // Registrar no backend:
    // POST /api/v1/users/me/device-tokens { token: token, platform: "android" }
    // Salvar o "id" retornado localmente para usar no logout
}

6. No logout — desregistrar:

// Chamar antes de limpar a sessão:
// DELETE /api/v1/users/me/device-tokens/{id_salvo}

Nota: Em Android 13+ (API 33), é necessário solicitar a permissão POST_NOTIFICATIONS em runtime antes de exibir notificações. Adicionar <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> no manifest.


Notas de Integração


Fluxo 17: Verificação Profissional de Médicos (Novo na v1.29)

Contexto. Contas criadas com role: "medico" precisam comprovar identidade profissional antes de acessar dados clínicos de pacientes. A verificação tem dois caminhos que o médico pode escolher dependendo do que tem em mãos:

Os dois caminhos liberam o mesmo conjunto de funcionalidades hoje. A diferenciação por verification_tier existe para que recursos futuros que exijam valor jurídico forte (ex.: prescrição digital, laudos assinados) possam exigir tier: "ouro" especificamente.

Estados possíveis no perfil do médico:

Campo Valores Significado
verification_status "pending" médico ainda não foi verificado
"approved" médico aprovado — pode usar funcionalidades clínicas
"rejected" última tentativa (tier ouro) falhou; ver last_rejection_reason
null usuário não é médico
verification_tier "ouro" aprovado via assinatura AR-CFM
"prata" aprovado via análise manual
null não aprovado ainda

Endpoints bloqueados para médicos não-aprovados (403):

Todos os endpoints doctors/me/* (exceto os de verificação abaixo), /patients/search, /patients/{id}, /patients/{id}/assessments (EDSS em particular), listagem/criação/remoção de pacientes, dashboard, alertas, /admin/ai-usage. O erro retornado tem detail com instrução para completar a verificação.


17.A — Tier Ouro (AR-CFM / ICP-Brasil)

Médico assina digitalmente um PDF personalizado com seu certificado e-CPF emitido pela AR-CFM (Autoridade de Registro do Conselho Federal de Medicina), certificadodigital.cfm.org.br. Como a AR-CFM só emite certificados para médicos com CRM ativo, a validação criptográfica da assinatura prova simultaneamente a autenticidade da identidade profissional.

A1. Gerar Termo de Verificação

Endpoint: POST /api/v1/doctors/me/verification/terms Auth: Bearer token do médico (mesmo com verification_status: "pending") Rate limit: 5 por hora Body: nenhum — o termo é gerado usando full_name do perfil do médico (atualize-o antes via PATCH /users/me se necessário).

Resposta (sucesso 200): Content-Type: application/pdf — binário do PDF. Header Content-Disposition: attachment; filename="lastreo-termo-verificacao-{user_id}.pdf". O PDF contém:

Validade do termo: 24 horas, uso único. Gerar um novo termo invalida automaticamente termos anteriores não-usados deste mesmo médico.

Erros: - 403 — não é médico - 422full_name está vazio no perfil; atualize via PATCH /users/me

A2. Assinar o PDF com e-CPF AR-CFM

O médico usa qualquer software de assinatura digital compatível com ICP-Brasil (ex.: Assinador Serpro, Adobe Acrobat Reader, Assinador da Valid) para assinar o PDF (padrão PAdES) com seu certificado digital emitido via AR-CFM.

Observação técnica: o certificado precisa conter o OID 2.16.76.1.4.2.2.1 (número de CRM) populado. Certificados e-CPF comuns (emitidos por outras ARs, não a AR-CFM) não contêm esse OID e serão rejeitados.

A3. Submeter o PDF Assinado

Endpoint: POST /api/v1/doctors/me/verification/submit Auth: Bearer token do médico Rate limit: 3 por hora Content-Type: multipart/form-data Campo: file — o PDF assinado (máximo 10 MB)

Exemplo (curl):

curl -X POST https://lastreo.com/api/v1/doctors/me/verification/submit \
  -H "Authorization: Bearer <token>" \
  -F "[email protected]"

Resposta (aprovado, 200):

{
  "verification_status": "approved",
  "verification_tier": "ouro",
  "verified_full_name": "BRUNO FERNANDES",
  "verified_crm": "987654",
  "verified_uf": "SP",
  "verified_specialty": "NEUROCIRURGIA",
  "rejection_reason": null
}

Dados verificados (nome, CRM, UF, especialidade, CPF) são preenchidos automaticamente no perfil do médico quando estiverem vazios. O médico passa a ter acesso imediato a todos os endpoints clínicos.

Erros (a conta é marcada como rejected em qualquer falha; audit log gravado com cert fingerprint, IP, motivo):

Código Quando ocorre Detail típico
400 PDF malformado, sem assinatura, conteúdo alterado após assinatura "Assinatura inválida: ..."
413 PDF maior que 10 MB "PDF muito grande (limite 10 MB)."
422 Certificado revogado "Certificado revogado: ..."
422 Certificado expirado "Certificado expirado: ..."
422 Cadeia de certificação não conecta à raiz ICP-Brasil "Cadeia de certificação inválida: ..."
422 Certificado não contém OID de CRM (não é AR-CFM) "Certificado não contém OID de CRM..."
422 Código do PDF não encontrado / expirado / já usado "Código de verificação não encontrado no PDF..."
422 Nome do certificado não bate com o nome do perfil "Nome do certificado ('X') não coincide com o nome do perfil ('Y')..."
429 Excedeu 3 tentativas por hora "Rate limit exceeded"
504 Verificação de revogação (OCSP/CRL) indisponível "Tempo esgotado ao validar a assinatura..."

17.B — Tier Prata (Análise manual)

Para médicos sem certificado digital AR-CFM. A submissão fica em fila e é revisada manualmente pela equipe Lastreo em até 24h. Apenas uma submissão em revisão por médico de cada vez — submeter de novo cancela a anterior automaticamente.

B1. Submeter Verificação Prata

Endpoint: POST /api/v1/doctors/me/verification/basic/submit Auth: Bearer token do médico Rate limit: 2 por dia Content-Type: multipart/form-data

Campo Tipo Obrigatório Descrição
crm string sim Número do CRM (somente dígitos, opcionalmente uma letra ao final). Max 20 chars.
uf string sim UF do CRM, sigla 2 letras (ex: SP).
full_name string sim Nome completo exatamente como consta na carteira CRM. 2–255 chars.
cpf string não CPF (XXX.XXX.XXX-XX ou só dígitos).
specialty string não Especialidade. Max 200 chars.
crm_card_image file sim Foto da carteira CRM (frente legível). JPEG/PNG/WebP, máx 8 MB.
selfie_image file sim Selfie segurando a carteira CRM com o rosto e o documento visíveis. JPEG/PNG/WebP, máx 8 MB.

As imagens passam por validação (Pillow), são re-codificadas para remover EXIF (privacidade) e armazenadas com acesso restrito.

Resposta (200) — DoctorBasicVerificationOut:

{
  "id": 42,
  "status": "pending_review",
  "crm_declared": "123456",
  "uf_declared": "SP",
  "full_name_declared": "Dr. Joao Silva",
  "cpf_declared": null,
  "specialty_declared": "Neurologia",
  "reviewer_notes": null,
  "reviewed_at": null,
  "created_at": "2026-05-19T10:32:11.123456+00:00"
}

Erros:

Código Motivo
403 usuário não é médico
422 CRM/UF/CPF em formato inválido, ou imagem não-imagem
413 imagem maior que 8 MB (já tratado dentro do 422 com mensagem explicativa)
429 excedeu 2 submissões por dia

B2. Consultar Estado da Submissão Prata

Endpoint: GET /api/v1/doctors/me/verification/basic Auth: Bearer token do médico

Retorna o DoctorBasicVerificationOut da submissão mais recente, ou 404 se nunca submeteu.

status pode ser "pending_review" (aguardando), "approved" (aprovada — o perfil do médico estará com verification_status=approved e verification_tier=prata), ou "rejected" (rejeitada — motivo em reviewer_notes).


17.C — Status agregado

Endpoint: GET /api/v1/doctors/me/verification/status Auth: Bearer token do médico

Mostra o estado canônico do perfil do médico, independente de qual caminho ele usou:

{
  "verification_status": "approved",
  "verification_tier": "ouro",
  "verified_full_name": "BRUNO FERNANDES",
  "verified_crm": "987654",
  "verified_uf": "SP",
  "verified_specialty": "NEUROCIRURGIA",
  "verification_submitted_at": "2026-05-19T10:32:11.123456+00:00",
  "verification_approved_at": "2026-05-19T10:32:11.987654+00:00",
  "last_rejection_reason": null
}

last_rejection_reason é preenchido apenas quando verification_status: "rejected" (rejeição do tier ouro). Rejeições do tier prata aparecem no estado da submissão (GET /verification/basic), não aqui — pois o perfil do médico permanece em "pending" enquanto não há aprovação.


Resumo para o Frontend

  1. Ao detectar verification_status: "pending" ou "rejected", exibir tela de onboarding com dois caminhos: - "Verificação imediata (AR-CFM)" — explica o que é, link para certificadodigital.cfm.org.br, botão "Gerar termo" que chama POST /verification/terms e baixa o PDF. - "Verificação por análise" — formulário com CRM, UF, nome, foto da carteira, selfie. Submete via POST /verification/basic/submit.
  2. Para tier ouro: após download, orientar o médico a assinar o PDF e fazer upload via POST /verification/submit. Em caso de erro, mostrar detail e permitir retry (até 3/hora).
  3. Para tier prata: após submissão, mostrar tela "Verificação em análise — aguardar até 24h" e fazer polling de GET /verification/basic ou usar push notification quando aprovado.
  4. GET /verification/status pode ser chamado ao abrir o app para sincronizar estado canônico.
  5. verification_tier é informativo no frontend — não precisa diferenciar UI por tier hoje.

Fluxo 18: Verificação Hospedada (Embed) (Guia consolidado — v1.58+)

O fluxo hospedado é a forma recomendada de verificar a identidade de um médico sem que documentos e biometria passem pelo seu backend. Você cria uma sessão no servidor, embeda uma página hospedada pelo Lastreo (iframe), e o médico interage diretamente com o Lastreo. Sob LGPD, você deixa de ser controlador do dado biométrico — o Lastreo é o operador desse dado.

Visão geral (4 passos):

  1. Server-side: seu backend chama POST /api/v1/client/verification-sessions (opcionalmente com required_tier) e recebe um embed_url.
  2. Frontend: você embeda o embed_url (via SDK drop-in ou iframe manual).
  3. Médico: completa a verificação no método correspondente ao required_tier da sessão — bronze (CRM + UF + nome), prata (carteira + selfie) ou ouro (assinatura digital ICP-Brasil) — ou reutiliza a identidade via Lastreo Link, tudo dentro do iframe.
  4. Resultado: você recebe o desfecho por postMessage e/ou redirect (UI), e confirma server-side via GET .../verification-sessions/{session_id} e/ou webhooks.

18.1. Criar a sessão (server-side)

POST /api/v1/client/verification-sessions

Autenticação: X-API-KEY: lk_... (recomendado para chamadas server-to-server) ou Bearer JWT de client_admin.

Request body (todos os campos são opcionais):

Campo Tipo Default Descrição
client_user_ref string null Identificador do médico/estudante no seu sistema. Volta nos webhooks da sessão (correlação sem lookup reverso) e garante idempotência: re-tentativas da mesma pessoa com o mesmo client_user_ref reusam a mesma identidade — sem cadastro duplicado nem nova cobrança. Recomendado sempre que o usuário puder recomeçar a verificação.
kind string "physician" Tipo de verificação: "physician" (médico, padrão) ou "student" (estudante de medicina). Em sessões student, a página oferece e-mail institucional ou comprovante de matrícula — os campos allow_silver/allow_gold aplicam-se só a médico. Ver 18.6.
allow_silver bool true Permite o caminho "carteira CRM + selfie" (resultado tier prata).
allow_gold bool true Permite o tier ouro na sessão. O ouro é atingido por reuso de identidade já-ouro via Lastreo Link; a assinatura ICP-Brasil em si é feita fora do fluxo hospedado.
required_tier string null Tier da sessão: bronze | prata | ouro (aliases basic/silver/strong/gold aceitos). Dirige o método que o iframe apresenta ao médico: bronze = confirmação rápida (CRM + UF + nome, sem documento); prata = carteira + selfie; ouro = assinatura digital ICP-Brasil (o médico baixa um termo, assina com o certificado AR-CFM e reenvia, dentro do iframe). Também é o piso aceito pelo Lastreo Link: o reuso de identidade só conclui se o tier reusado for este. Só vale para kind: "physician". Sem valor, o padrão é prata. Devolvido em GET /client/verification-sessions/{id}.
theme_primary_color string null Cor primária do wizard, formato #RRGGBB.
hide_branding bool false Oculta o branding "Verificado por Lastreo" (white-label).
completion_redirect_url string null Se informado, ao concluir o iframe redireciona o navegador para esta URL com ?session_id=&status=&tier=.
allowed_origins array null Origens permitidas para embedar o iframe.
expires_in_minutes int 60 Validade do link, entre 10 e 240.

Response 201:

{
  "id": 11,
  "session_id": "vs_Wx6drlhZuwS1UK8vXYhqt2AL",
  "embed_url": "https://lastreo.com/dashboard/v/?t=PQPqkZtz...E4gi",
  "expires_at": "2026-05-28T23:15:30Z",
  "status": "pending"
}

⚠️ Use o embed_url VERBATIM. Ele já contém um token de uso único na query (?t=...), entregue uma única vez nesta resposta. É esse token que autoriza a sessão.

session_id (vs_...) NÃO é o token. É um identificador público, usado apenas para (a) consultar o resultado server-side (GET .../verification-sessions/{session_id}) e (b) correlacionar webhooks. Nunca monte a URL do iframe a partir do session_id — isso resulta em "Sessão inválida ou expirada", porque o session_id não autoriza nada. Igualmente, id (inteiro) é uma PK interna — não use em URLs.


18.2. Renderizar no frontend

Opção A — SDK drop-in (recomendado). Sirva o script e passe o embed_url:

<script src="https://lastreo.com/dashboard/sdk/lastreo.js"></script>
<div id="lastreo-verify"></div>
<script>
  // embedUrl vem do POST /client/verification-sessions (server-side).
  const lastreo = Lastreo({ embedUrl: EMBED_URL_DO_SEU_BACKEND });

  // (A1) Inline, dentro de um container seu:
  lastreo.mount('#lastreo-verify', {
    onComplete: ({ status, session_id, tier }) => { /* ... */ },
    theme: { primaryColor: '#0f766e' },  // opcional
  });

  // (A2) Modal full-screen com overlay + botão de fechar já incluídos:
  const modal = lastreo.openModal({
    onComplete: ({ status, session_id, tier }) => { /* ... */ },
    onClose: () => { /* usuário fechou */ },
  });
  // modal.close();  // fechar programaticamente, se precisar
</script>

Opção B — iframe manual (se você não quiser o SDK):

<iframe src="EMBED_URL_DO_SEU_BACKEND"
        allow="camera; clipboard-write"
        style="border:0;width:480px;height:720px"></iframe>

⚠️ Sobre o botão de fechar do modal: o iframe renderiza apenas o conteúdo do wizard. Ele não pode fechar a si mesmo — fechar/esconder o modal é responsabilidade de quem o renderiza (o seu app). Se você monta o seu próprio modal/overlay (ou usa mount() num container seu), o botão de fechar é seu. Para ganhar overlay + botão "×" + auto-fechamento ao concluir sem implementar nada, use openModal() do SDK. Se preferir o seu próprio modal, adicione seu botão de fechar e, opcionalmente, escute o postMessage de conclusão (abaixo) para fechá-lo automaticamente.

A câmera (allow="camera") é necessária para a captura da selfie. O iframe precisa ser servido sobre HTTPS.


18.3. Receber o resultado (UI)

Ao concluir (sucesso ou falha), o iframe emite um postMessage para a janela-pai:

window.addEventListener('message', (e) => {
  if (e.data?.type === 'lastreo.verify.complete') {
    const { status, session_id, tier } = e.data;
    // status: "completed" (verificado) | "failed" (rejeitado)
    // tier:   "bronze" | "prata" | "ouro" | null
  }
});

(O SDK já faz esse addEventListener por você e entrega via onComplete.)

Se você passou completion_redirect_url ao criar a sessão, o iframe também redireciona o navegador para essa URL ao concluir, acrescentando ?session_id=&status=&tier=.

⚠️ postMessage e redirect são sinais de UI (convenientes para atualizar a tela). A fonte de verdade é server-side — confirme sempre via 18.4 antes de liberar acesso/conceder privilégios.


18.4. Confirmar server-side (fonte de verdade)

GET /api/v1/client/verification-sessions/{session_id}

Use o session_id (vs_...) da criação. Retorna o estado canônico da sessão:

{
  "id": 11,
  "session_id": "vs_Wx6drlhZuwS1UK8vXYhqt2AL",
  "client_user_ref": "seu-sistema:medico:789",
  "status": "completed",
  "final_tier": "prata",
  "doctor_user_id": 42,
  "declared_full_name": "...",
  "declared_crm": "123456",
  "declared_uf": "SE",
  "expires_at": "2026-05-28T23:15:30Z",
  "started_at": "2026-05-28T22:46:10Z",
  "completed_at": "2026-05-28T22:49:02Z",
  "created_at": "2026-05-28T22:45:30Z"
}

Valores de status: pending (criada, médico não começou) · in_progress (preenchendo) · processing (em análise) · completed (verificado, ver final_tier) · failed (rejeitado) · expired (passou de expires_at) · cancelled.

final_tier: bronze · prata (caminho carteira+selfie) · ouro (assinatura ICP-Brasil) · null enquanto não concluído.

Alternativamente (recomendado para não fazer polling), configure webhooks e escute verification.submitted / verification.approved / verification.rejected — quando a sessão tem client_user_ref, esses eventos carregam session_id + client_user_ref no data (ver changelog v1.61).


18.5. Expiração e novas tentativas

O link vale expires_in_minutes (10–240, default 60). Após expirar, o wizard exibe "Sessão inválida ou expirada" — basta criar uma nova sessão e embedar o novo embed_url. O token é de uso único por sessão; não o reaproveite entre médicos.


Resumo para o Frontend

  1. Seu backend cria a sessão (POST /client/verification-sessions) e entrega o embed_url ao seu frontend.
  2. Embede o embed_url verbatim — via Lastreo({embedUrl}).mount(...)/.openModal(...) (recomendado) ou iframe manual com allow="camera".
  3. Nunca construa a URL do iframe a partir do session_id ou do id.
  4. Se você renderiza o próprio modal, o botão de fechar é seu (ou use openModal(), que já o inclui).
  5. Atualize a UI com o postMessage lastreo.verify.complete, mas confirme o resultado server-side (GET .../verification-sessions/{session_id} ou webhooks) antes de conceder acesso.

18.6. Verificação de estudante de medicina (kind: "student")

O Lastreo verifica profissionais e estudantes de medicina. Para verificar um estudante, crie a sessão (18.1) passando kind: "student" — todo o resto da integração é idêntico ao fluxo de médico (embed → postMessage/redirect → confirmação server-side / webhook).

A diferença está dentro da página hospedada (conduzida pelo Lastreo): em vez de carteira CRM + selfie, o estudante escolhe um de dois caminhos — e-mail institucional (recebe um código; quando a instituição é uma escola médica reconhecida, aprova na hora) ou comprovante de matrícula (aceita PDF ou imagem). No caminho do comprovante, selfie e documento com foto são opcionais — quando enviados e a identidade é confirmada, o resultado sobe para verified_strong. Você não precisa saber qual caminho foi usado: o desfecho chega igual.

Tier do resultado (tier no postMessage, final_tier no GET da sessão, tier no webhook):

tier Significado
verified Estudante de medicina verificado (matrícula em Medicina confirmada).
verified_strong Verificado + identidade vinculada por biometria (selfie + documento com foto).
null Submissão recebida, aguardando revisão — você é avisado por webhook ao concluir.

No GET /api/v1/client/verification-sessions/{id} o tier do estudante vem em final_tier (verified/verified_strong) e o tipo da sessão em kind — não precisa consultar /client/students só para saber o resultado.

Criar a sessão:

curl -X POST https://lastreo.com/api/v1/client/verification-sessions \
  -H "X-API-KEY: lk_..." -H "Content-Type: application/json" \
  -d '{"kind": "student", "client_user_ref": "seu-sistema:aluno:123"}'
# -> { "session_id": "vs_...", "embed_url": "https://.../dashboard/v/?t=...", "status": "pending", ... }

Webhooks: verification.approved / verification.rejected disparam também para estudantes, com kind: "student" no data (e session_id / client_user_ref quando a sessão tem o ref — igual ao médico, ver v1.61). Exemplo de data: {"user_id": 51, "kind": "student", "tier": "verified", "session_id": "vs_ab12cd34", "client_user_ref": "seu-sistema:aluno:123"}.

Listar os estudantes do tenant: GET /api/v1/client/students (API key ou Bearer) — retorna os estudantes verificados via suas sessões: id, full_name, verified_full_name, email, verification_status, student_tier, verification_approved_at.

Ciclo de vida — o estudante vira médico automaticamente. Quando ele obtém o CRM e se verifica como médico (qualquer tier), a mesma identidade Lastreo deixa de ser estudante e passa a médico: some de GET /api/v1/client/students e aparece em GET /api/v1/client/doctors com tier bronze/prata/ouro. Você não precisa religar nada — capturar o estudante hoje é onboardar o médico de amanhã sem atrito.


5. Tratamento de Erros

A API utiliza códigos de status HTTP padrão para indicar o sucesso ou a falha de uma requisição. Em caso de erro (status 4xx ou 5xx), o corpo da resposta conterá um objeto JSON com a descrição do problema.

6. Referência Rápida de Endpoints

Método Endpoint Descrição Auth
POST /auth/register Registro de usuário -
POST /auth/login Login (retorna tokens) -
POST /auth/refresh Renovar tokens -
POST /auth/forgot-password Solicitar reset de senha -
POST /auth/reset-password Redefinir senha com código -
POST /auth/change-password Alterar senha (autenticado) Bearer
POST /auth/send-verification Solicitar código de verificação de email -
POST /auth/verify-email Verificar email com código -
GET /api/v1/users/me Perfil do usuário logado Bearer
GET /api/v1/patients/{id} Perfil de um paciente Bearer
GET /api/v1/patients/search?query= Buscar pacientes (médico) Bearer
GET /api/v1/patients/{id}/symptoms Sintomas do paciente Bearer
GET /api/v1/patients/{id}/assessments Avaliações clínicas Bearer
POST /api/v1/patients/{id}/assessments Criar avaliação clínica Bearer
GET /api/v1/patients/{id}/health-registries Listar registros de saúde Bearer
POST /api/v1/patients/{id}/health-registries Criar/upsert registro de saúde Bearer
DELETE /api/v1/patients/{id}/health-registries/{rid} Remover registro individual Bearer
DELETE /api/v1/patients/{id}/health-registries Remover todos os registros (LGPD) Bearer
POST /api/v1/patients/{id}/health-registries/batch Criar/upsert registros em lote Bearer
GET /api/v1/patients/{id}/health-registries/summary Resumo agregado Bearer
GET /api/v1/channels/me Listar canais vinculados Bearer
POST /api/v1/channels/link-request Solicitar vinculação Bearer
POST /api/v1/channels/link-confirm Confirmar vinculação Bearer
DELETE /api/v1/channels/{id} Desvincular canal Bearer
POST /api/v1/users/claim-request Solicitar reivindicação Bearer
POST /api/v1/users/claim-confirm Confirmar reivindicação Bearer
POST /api/v1/doctors/me/patients Vincular paciente existente Bearer
POST /api/v1/doctors/me/patients/provisional Criar paciente provisório Bearer
POST /api/v1/doctors/me/patients/{id}/merge Mesclar provisório em conta real Bearer
DELETE /api/v1/doctors/me/patients/{id} Remover paciente da lista do médico Bearer
GET /api/v1/doctors/me/patients Listar pacientes do médico Bearer
POST /api/v1/doctors/me/verification/terms Gerar PDF de termo de verificação profissional (tier ouro) Bearer
POST /api/v1/doctors/me/verification/submit Submeter PDF assinado com e-CPF AR-CFM (tier ouro) Bearer
POST /api/v1/doctors/me/verification/basic/submit Submeter foto CRM + selfie para análise manual (tier prata) Bearer
GET /api/v1/doctors/me/verification/basic Estado da submissão prata mais recente Bearer
GET /api/v1/doctors/me/verification/status Consultar estado canônico da verificação profissional Bearer
GET /api/v1/doctors/me/dashboard Dashboard do médico Bearer
GET /api/v1/patients/{id}/symptoms/trends Tendências de sintomas Bearer
GET /api/v1/patients/{id}/health-correlation Correlação exercício × sintomas Bearer
GET /api/v1/patients/{id}/export/symptoms Exportar sintomas em CSV Bearer
GET /api/v1/patients/{id}/export/report Relatório clínico em PDF Bearer
GET /api/v1/patients/{id}/export/fhir Export FHIR R4 Bundle Bearer
GET /api/v1/doctors/me/alerts Alertas dos pacientes do médico Bearer
GET /api/v1/doctors/me/alerts/unread-count Contagem de alertas não-lidos Bearer
PATCH /api/v1/doctors/me/alerts/{id}/read Marcar alerta como lido Bearer
GET /api/v1/patients/{id}/alerts Alertas de um paciente Bearer
POST /api/v1/patients/{id}/medication-reminders Criar lembrete de medicação Bearer
GET /api/v1/patients/{id}/medication-reminders Listar lembretes de medicação Bearer
PATCH /api/v1/patients/{id}/medication-reminders/{rid} Atualizar lembrete Bearer
DELETE /api/v1/patients/{id}/medication-reminders/{rid} Deletar lembrete Bearer
POST /api/v1/chat/send Enviar mensagem no chat (multipart: text + file + local_id) Bearer
GET /api/v1/chat/stream?token=<jwt> Receber resposta da IA via SSE Query param
Mídia: cache local no dispositivo (ver seção 15.4)
GET /api/v1/chat/history Histórico do chat in-app Bearer
DELETE /api/v1/chat/history Limpar histórico do chat (LGPD) Bearer
POST /api/v1/users/me/device-tokens Registrar token FCM para push notifications Bearer
DELETE /api/v1/users/me/device-tokens/{id} Desregistrar token FCM (logout / troca de device) Bearer

6.1 Endpoints B2B de Integração (/client/*)

Superfície para o backend do seu sistema integrar com o Lastreo (verificação de identidade médica, billing, uso). Os endpoints de integração aceitam X-API-KEY: lk_... (recomendado para server-to-server) ou Bearer JWT de client_admin. Os de gerenciamento de conta são exclusivos do dashboard (Bearer JWT) — ver changelog v1.62.

Método Endpoint Descrição Auth
POST /api/v1/client/verification-sessions Criar sessão de verificação hospedada (embed) API key ou Bearer
GET /api/v1/client/verification-sessions/{session_id} Estado canônico de uma sessão de verificação API key ou Bearer
GET /api/v1/client/doctors Listar médicos verificados que atendem o tenant API key ou Bearer
POST /api/v1/client/doctors Cadastrar/verificar médico (bronze inline) API key ou Bearer
GET /api/v1/client/students Listar estudantes de medicina verificados do tenant API key ou Bearer
POST /api/v1/client/doctors/{doctor_id}/verify-tier Solicitar tier de verificação para um médico API key ou Bearer
GET /api/v1/client/verifications/usage?days=N Uso de verificações por tier + billing estimado (BRL) API key ou Bearer
GET /api/v1/client/usage Agregação de uso de IA do tenant API key ou Bearer
GET /api/v1/client/usage/by-patient?days=N&limit=M Ranking de pacientes por consumo de IA API key ou Bearer
GET /api/v1/client/compliance/snapshot Snapshot de compliance/verificações do tenant API key ou Bearer
GET /api/v1/client/me Dados do tenant Bearer (dashboard)
POST /api/v1/client/api-keys Emitir API key (mostrada uma única vez) Bearer (dashboard)
POST /api/v1/client/api-keys/{id}/revoke Revogar API key Bearer (dashboard)
GET POST /api/v1/client/webhooks Listar / criar webhook (HMAC + retry) Bearer (dashboard)
PATCH DELETE /api/v1/client/webhooks/{id} Atualizar / remover webhook Bearer (dashboard)
GET /api/v1/client/webhooks/{id}/deliveries Histórico de entregas do webhook Bearer (dashboard)
POST /api/v1/client/webhooks/{id}/test Disparar evento de teste Bearer (dashboard)
GET PUT DELETE /api/v1/client/integrations/ai Config BYOK de IA do tenant Bearer (dashboard)
GET PUT DELETE /api/v1/client/integrations/whatsapp Config BYOK de WhatsApp do tenant Bearer (dashboard)
GET PUT DELETE /api/v1/client/integrations/telegram Config BYOK de Telegram do tenant Bearer (dashboard)
GET /api/v1/client/push-configs Catálogo de eventos + config de push por evento Bearer (dashboard)
PUT DELETE /api/v1/client/push-configs/{event_type} Configurar / resetar push de um evento Bearer (dashboard)
GET /api/v1/client/devices Device tokens FCM dos usuários do tenant Bearer (dashboard)
POST /api/v1/client/push-test Enviar push de teste para um device Bearer (dashboard)
GET /api/v1/client/errors Erros do tenant (filtrados) Bearer (dashboard)