Revo Mobilepainel do app

Aplicativo do motorista · Versão 6 · Especificação da API

A entrega da versão 6, em três partes: o que já foi feito, as atualizações e a API para o backend.

Este guia é autossuficiente: começa pelo que já roda hoje, segue pelo que muda campo a campo e termina em cada rota, com o motivo de cada regra. Use o sumário ao lado para pular direto para o que interessa.

6

rotas /mobile/* — a API inteira, nenhuma escondida

100%

do fluxo operável sem sinal — o fato que explica as regras

45 s

o tempo que o aplicativo espera por cada resposta

0

baixas descartadas — recusa fica na fila, com o motivo visível

Parte 1 — O que já foi feito

O aplicativo inteiro, reescrito
Login, romaneio, baixa com foto e assinatura, coleta com conferência de volumes, ocorrências, fila offline, rastreamento e atualização remota — tudo já roda.
A camada que faz tudo valer no servidor de hoje
Um adaptador, mais os ajustes que só o campo revelou: o formato de data, o romaneio que a Swagger trata como "entrega única" e a lista que apagava serviços já feitos.
O acesso de demonstração
Transportadora 0000: funciona sem servidor nem VPN, para qualquer pessoa ver o aplicativo andando hoje.

Checklist ao vivo

Esta lista não é um retrato: é o mesmo checklist que a equipe marca no painel interno, filtrado ao que diz respeito ao backend — o Modo 2 (endpoint por endpoint), a observabilidade e a ciência do que já existe.

A API — endpoint por endpoint

0/9
  • Comece por aqui — o Modo 2 é a API inteira escrita do zero, não uma lista de melhoriasPendente
  • O modelo de dados — nove entidades, e as chaves que amarram tudoPendente
  • Regras que valem para a API inteira — envelope, erro, autenticação, datas e compressãoPendente
  • Sessão — abre o dia e carrega o aparelho para operar offline até a noitePendente
  • Alterações do romaneio — o delta, com marcador de versão e resposta vaziaPendente
  • Baixa — o resultado do serviço, com resposta repetível por idempotênciaPendente
  • Anexo em três passos — os bytes vão direto ao armazenamento, sem passar pelo TMSPendente
  • Posições — rastreamento em lote, porque offline elas se acumulamPendente
  • Dispositivo e push — o TMS avisa que o romaneio mudou, em vez de o app ficar perguntandoPendente

Observabilidade — o que a central enxerga

0/5
  • 7.1 — Última posição por motorista, guardando AS DUAS datasPendente
  • 7.2 — Último contato do app (qualquer requisição)Pendente
  • 7.3 — Booleano "deveria estar rastreando"Pendente
  • 7.4 — Carimbar o início do romaneioPendente
  • 7.5 — Definir os limites do alerta de posição desatualizadaPendente

Ciência — nada a implementar; só confirmar a leitura

0/3
  • Assinatura sobe como anexo — o campo inline não será usadoPendente
  • O app v6 já roda no backend de HOJE — a migração não depende de vocêsPendente
  • As três lições que derrubavam a baixa — duas de julho, uma de agosto/2026Pendente

Acesso de demonstração

Credenciais

Transportadora

0000

CPF

000.000.000-01

Placa

AAA-1122

Por que é seguro

O CPF é inválido de propósito e o modo demonstração nunca manda nada para um servidor: não existe risco de misturar teste com operação real.

Parte 2 — Atualizações

Responde a uma pergunta só: o que mudou desde a última vez que eu olhei?

Parte 3 — Só o que muda

Esta seção não é a especificação completa: é o mapa do que precisa mudar para o backend de hoje falar o contrato da v6. O detalhe endpoint por endpoint vem logo abaixo, e a referência medida contra o servidor real está em /contrato.

08/09/2026 — o caminho B ganhou chão

A equipe do TMS subiu o caminho B em wshomdev.grupoaleff.com.br. Com os romaneios 720/26 (coleta, 5 serviços) e 2303/26 (entrega, 9 serviços), o app 6.0.13 fez 105 chamadas reais; o resultado virou contrato medido em OpenAPI 3.1. Cinco rotas passam: sessão, anexos, posições, baixa com o schema do TMS desde 11/09, e alterações medida na tarde de 11/09. Detalhe completo em /contrato.

Caminho A — Adequação
O Swagger de hoje absorve a lista

Os endpoints atuais (GetDocumentos, AtualizaDocumento, CadastraLocalizacaoMotorista) ganham os campos que faltam, sem trocar de nome nem de formato.

  • · Menor mudança de infraestrutura: mesmo host, mesma autenticação.
  • · Risco: o Swagger atual também serve o app 5.x e a Play — todo campo novo tem que ser opcional e não pode mudar o que já existe.
  • · Erro de negócio em 4xx é impossível aqui sem quebrar o app da Play, que só entende 200.
Caminho B — Mundo ideal
As rotas novas, e o Swagger atual intocado

As seis rotas /mobile/* descritas neste guia nascem à parte, com o modelo de dados e as regras que o app 6.x realmente precisa.

  • · Swagger e app 5.x seguem exatamente como estão — zero risco de regressão para quem está em produção.
  • · Todas as regras deste guia (idempotência, erro em 4xx, lote de posições) valem sem gambiarra.
  • · É o caminho que este guia documenta endpoint por endpoint, e o que virou "contrato medido" em /contrato.

Os dois caminhos, lado a lado

Campo ou comportamentoCaminho A — AdequaçãoCaminho B — Mundo ideal
Latitude / longitude do serviçoAdicionar ao retorno existenteJá nasce no modelo do serviço
Regras da baixa e do rastreioDocumentar por fora, sem forçar no formato antigoRegras nativas do endpoint novo
Romaneio rebuscável + estado do serviço — o item delicadoDifícil: o formato atual não tem "estado por serviço"Nativo: GET /mobile/romaneio/{t}/alteracoes
Baixa duplicada recusadaPrecisa de campo extra e checagem manualIdempotência nativa do endpoint
Posições em loteEndpoint atual só aceita uma por chamadaPOST /mobile/posicoes já nasce em lote
Fotos separadas da baixaContinua base64 dentro do corpoPOST /mobile/anexos, arquivo por fora
Coleta com conferência de volumesSem campo equivalente hojeCampos coleta.* nativos na baixa
Erro de negócio em 4xxImpossível sem quebrar o app da PlayPadrão do endpoint, desde o primeiro dia

Como ler a comparação

A coluna A não é "pior": é o que dá para fazer sem tocar no que já está em produção. A coluna B é o que este guia documenta em detalhe daqui para baixo, porque é o que o aplicativo 6.x já fala.

Latitude e longitude já existem, mas vêm vazias

Medido em 10/08/2026: 0 de 427 serviços vieram com coordenada. O campo existe no contrato; falta o TMS preencher.

Posições em lote é capacidade nova do endpoint

Não é enviar uma posição de cada vez mais rápido: o corpo leva várias de uma vez.

{
  "placa": "AAA-1122",
  "romaneio": "4471",
  "posicoes": [
    { "lat": -23.55, "lon": -46.63, "precisaoM": 12, "em": "2026-09-11T14:02:00.000Z" },
    { "lat": -23.56, "lon": -46.64, "precisaoM": 9,  "em": "2026-09-11T14:03:00.000Z" }
  ]
}

Campos a criar (ou preencher) no retorno do login

CampoOndeMotivo
latitude / longitudeserviçoSem coordenada não há mapa nem rota no aplicativo.
parametros.{fotosObrigatorias, exigeNome, exigeDocumento, exigeAssinatura, intervaloPosicaoSeg, intervaloEnvioSeg}sessãoRegras de captura variam por transportadora; o app não pode ter isso fixo no código.
parametros.rastrearsessãoLiga o rastreamento por romaneio, não por documento — evita pedir permissão de GPS sem necessidade.
romaneio.numero estávelromaneioUm mesmo romaneio não pode trocar de número no meio do dia — foi o que picou 734/26 em 735/26 e 736/26 num incidente real.
estado do serviçoserviçoO app precisa saber se um serviço já foi baixado por outra via, sem inferir isso sozinho.
tipo do serviço + volumesPrevistos / pesoPrevistoserviçoSem isso a conferência de volumes na coleta não tem contra o que comparar.
motorista.nomesessãoUsado na tela e na assinatura; hoje falta em alguns retornos.
janelaTextoserviçoTexto pronto da janela de entrega — evita o app calcular formatação de horário sozinho.

Comportamentos que precisam mudar

Comportamento atualO que precisa virar
Reenvio pode duplicar a baixaIdempotência por chave única, deduplicada no servidor
Erro de negócio some dentro de um 200Erro de negócio sempre em 4xx, com código e campo
Romaneio rebaixado inteiro a cada consultaGET /alteracoes devolve só o que mudou desde a última vez
Foto e assinatura em base64 dentro da baixaAnexo sobe à parte, a baixa só cita o anexoId

Campos novos que o aplicativo passa a mandar na baixa

CampoFormatoMotivo
idempotenciaUUID gerado no aparelhoEvita duplicar a baixa em reenvio
fotos / assinaturafotos: [{seq, anexoId}]; assinatura: {anexoId}O arquivo já subiu por /mobile/anexos; a baixa só referencia
posicao.precisaoMmetrosPermite ao TMS descartar leitura de GPS ruim
coleta.*volumesConferidos, motivoDivergencia, documentos[]Suporta a conferência de volumes no fluxo de coleta

O único endpoint inteiramente novo: POST /mobile/anexos

Todos os outros traduzem algo que já existe hoje. Este não tem equivalente no backend atual — cada foto e cada assinatura sobem por ele, uma de cada vez, antes da baixa fechar.

As perguntas ainda em aberto estão reunidas em Perguntas em aberto. O ditado por voz — já embarcado no aplicativo — está descrito em Ditado por voz.

Três fatos que moldam tudo

O aplicativo é offline primeiro
Todo o fluxo do motorista — abrir o romaneio, dar baixa, registrar ocorrência — funciona sem rede. A tela nunca trava esperando o servidor.
A fila reenvia até conseguir
Cada baixa entra numa fila local. Ela insiste sozinha quando a rede volta; o motorista não reenvia nada na mão.
Só existe um momento de rede garantido
A sessão, de manhã. Tudo o resto — baixa, foto, posição — pode acontecer minutos ou horas depois, quando o sinal aparecer.

O que "offline" significa aqui

"Offline" não é um modo à parte que alguém liga: é o estado normal. O motorista roda o dia inteiro numa área sem sinal e só percebe a diferença quando a fila esvazia mais rápido. Por isso toda regra de API abaixo assume que a chamada pode chegar minutos, horas ou (num caso raro) dias depois do que aconteceu no chão.

O mapa das rotas

POST  /mobile/sessao                        abre o dia; devolve o romaneio inteiro
GET   /mobile/romaneio/{t}/alteracoes       o que mudou desde a última consulta
POST  /mobile/servicos/{servicoId}/baixa    o resultado do serviço
POST  /mobile/anexos                        fotos e assinatura, uma a uma
POST  /mobile/posicoes                      rastreamento, em lote

evoluções — exigem versão nova do aplicativo; nada depende delas:
POST  /mobile/dispositivos                  registra o aparelho para push
 →    push (FCM), do TMS para o aparelho    avisa que o romaneio mudou
 →    anexos com tipo "audio" + origem na baixa  ditado por voz — já no app 6.0.10, falta o TMS

O dia de um motorista, visto pela API

  1. 1.De manhã: POST /mobile/sessao abre o turno e devolve o romaneio inteiro, de uma vez.
  2. 2.Durante o dia: Baixa de cada serviço, anexo de cada foto ou assinatura, posição em lote e, quando o romaneio muda no TMS, a checagem de alterações.
  3. 3.O tempo todo: Sem sinal, nada trava. Quando o sinal volta, a fila manda o que estiver pendente, na ordem em que aconteceu.

Sete regras gerais

1. O envelope de resposta é sempre o mesmo

Sucesso vem em 200 ou 201 com "sucesso": true e os campos do endpoint. Erro de negócio vem em 4xx, nunca em 200 com "sucesso": false.

200 / 201  { "sucesso": true, …campos do endpoint }
4xx {
  "sucesso":  false,
  "codigo":   "RECEBEDOR_OBRIGATORIO",
  "mensagem": "Informe quem recebeu",
  "campo":    "recebedor.nome"
}

A ambiguidade já custou um dia inteiro

09/08/2026: 82 das 86 chamadas foram rejeitadas porque a data ia com o fuso -03:00, documentado como aceito. Só UTC era aceito de fato. Envelope e formato ambíguos custam campo — daí cada regra abaixo vir com o motivo, não só a forma.

2. Datas sempre em UTC, sempre com milissegundos

Formato único: AAAA-MM-DDTHH:mm:ss.sssZ. Nenhum endpoint aceita o deslocamento -03:00, mesmo onde a documentação antiga sugeria aceitar.

3. Toda gravação tem idempotência

Baixa e anexo levam uma chave gerada no aparelho. Reenviar a mesma chave nunca duplica: o servidor responde como se fosse a primeira vez.

4. O aplicativo espera até 45 segundos

Cada chamada tem 45 s de tempo-limite antes de voltar para a fila local e tentar de novo mais tarde.

5. Erro de negócio explica o motivo

Recusa vem com código estável, mensagem legível e o campo específico — nunca um 4xx genérico sem contexto.

6. Nada de paginação nas rotas que o app usa no dia a dia

Romaneio, alterações e catálogo de ocorrências vêm inteiros. O aparelho não implementa "próxima página" em nenhum fluxo do motorista.

7. O servidor é a fonte da verdade do estado do serviço

O aplicativo nunca decide sozinho se um serviço já foi entregue; ele reflete o que o servidor mandou na última sincronização.

O modelo de dados

servico.id é único e estável
Um serviço não troca de identidade entre chamadas. Reidentificar o mesmo serviço com um id novo quebra a idempotência e a fila local.
Idempotência é chave única, não log
O servidor guarda a chave e o resultado; uma repetição devolve o mesmo resultado, não um registro duplicado.
Anexo órfão é estado normal
Um anexoId pode existir sem baixa nenhuma que o cite ainda — a foto sobe antes de a baixa fechar. Isso não é erro.
motoristadispositivoromaneioserviçodocumentobaixaanexoposiçãocatálogo de ocorrências

Os endpoints, um por um

Cada rota abaixo abre com a mesma sequência: o que o app manda, o que precisa voltar e as regras que o campo já ensinou. A versão medida contra o servidor de homologação fica em /contrato.

POST/mobile/sessao
Sessão — abre o dia
Único momento de rede garantido. Devolve o romaneio inteiro, os parâmetros da transportadora e o catálogo de ocorrências.

O que o app manda

{
  "transportadora": "0000",
  "cpf": "000.000.000-01",
  "placa": "AAA-1122",
  "dispositivo": { "so": "android", "versaoApp": "6.0.20", "id": "..." }
}

O que precisa voltar

{
  "sucesso": true,
  "motorista": { "nome": "...", "cpf": "...", "transportadora": "0000", "telefoneCentral": "..." },
  "parametros": {
    "fotosObrigatorias": 1,
    "exigeNome": true,
    "exigeDocumento": true,
    "exigeAssinatura": true,
    "intervaloPosicaoSeg": 60,
    "intervaloEnvioSeg": 300,
    "rastrear": true
  },
  "ocorrencias": [{ "codigo": "01", "texto": "Cliente ausente", "tipo": "insucesso", "exigeFoto": false }],
  "romaneio": {
    "numero": "4471",
    "servicos": [
      {
        "id": "SV-1001",
        "tipo": "entrega",
        "ordem": 1,
        "cliente": "...",
        "remetente": "...",
        "logradouro": "...",
        "bairro": "...",
        "cidade": "...",
        "uf": "SP",
        "cep": "...",
        "latitude": -23.55,
        "longitude": -46.63,
        "janelaTexto": "08:00 – 12:00",
        "documentos": [{ "tipo": "NF-e", "numero": "...", "chave": "...", "parceiro": "..." }],
        "volumesPrevistos": 5,
        "pesoPrevisto": 120.5
      }
    ]
  }
}

As regras

  • ●O romaneio não pagina: vem inteiro na sessão.
  • ●Abrir uma sessão nova não invalida a fila offline pendente do aparelho.
  • ●Toda recusa de negócio explica o motivo — nunca um 4xx silencioso.

A forma de entrega do romaneio — as três garantias

10/08/2026, 14:17: 427 serviços chegaram de uma vez; às 14:19 a mesma recusa se repetiu 11 vezes, num padrão visto em 170 placas diferentes. Causa: o romaneio 734/26 foi picado em 735/26 e 736/26 no meio do turno (7 + 123 + 12 + 285 = 427 serviços), e 135 deles simplesmente desapareceram da consulta seguinte. As três garantias que evitam isso: o romaneio não pagina, uma sessão nova não invalida a fila local, e toda recusa de negócio explica o motivo.

GET/mobile/romaneio/{t}/alteracoes?romaneio={n}&desde={data}
Alterações do romaneio
O que mudou desde a última consulta — o app não rebaixa o romaneio inteiro a cada vez.

O que precisa voltar

{
  "sucesso": true,
  "incluidos": [],
  "alterados": [],
  "removidos": [],
  "sincronizadoEm": "2026-09-11T14:05:00.000Z"
}

As regras

  • ●"desde" é a data da última sincronização bem-sucedida do aparelho, não a de agora.
  • ●"removidos" traz só os ids: o app já tem o resto do serviço localmente.
  • ●Serviço já baixado localmente que volta como "alterado" não desfaz a baixa pendente na fila.
  • ●Resposta vazia (três listas em branco) é o caso comum: significa que nada mudou.
  • ●A ausência de paginação vale aqui também.

Evolução: marcador de versão

ETag / If-None-Match com resposta 304 quando nada mudou, para economizar corpo de resposta em consultas frequentes.

POST/mobile/servicos/{servicoId}/baixa
Baixa do serviço
O resultado do serviço — entregue, recusado, coletado — com idempotência e posição.

O que o app manda

{
  "idempotencia": "uuid-gerado-no-aparelho",
  "servicoId": "SV-1001",
  "resultado": "entregue",
  "executadoEm": "2026-09-11T14:10:00.000Z",
  "posicao": { "lat": -23.55, "lon": -46.63, "precisaoM": 12 },
  "recebedor": { "nome": "...", "documento": "...", "setor": "..." },
  "fotos": [{ "seq": 1, "anexoId": "..." }],
  "assinatura": { "anexoId": "..." },
  "ocorrencia": { "codigo": "01", "observacao": "...", "retornaHoje": false },
  "coleta": { "volumesConferidos": 5, "motivoDivergencia": null, "documentos": [] }
}

O que precisa voltar

200 { "sucesso": true, "baixaId": "B-88213", "registradoEm": "2026-09-11T14:10:03.000Z", "situacao": "registrada" }

As regras

  • ●"situacao" pode ser "registrada", "duplicada" ou "ignorada" — nunca um erro para reenvio da mesma chave.
  • ●Reenviar a mesma "idempotencia" sempre devolve a mesma "baixaId", nunca cria uma segunda baixa.
  • ●"fotos" e "assinatura" só citam anexoId: o arquivo já subiu por /mobile/anexos antes.
  • ●Ocorrência de insucesso exige "ocorrencia.codigo" do catálogo devolvido na sessão.
  • ●Campos de "coleta" só se aplicam quando o tipo do serviço é coleta.
  • ●"posicao" na baixa é best-effort: ausência dela não bloqueia o registro.
POST/mobile/anexos
Anexos — fotos e assinatura
O único endpoint sem equivalente no backend atual. Cada arquivo sobe sozinho, multipart, antes de a baixa citá-lo.

O que o app manda

multipart/form-data
  anexoId          gerado no aparelho
  servicoId
  baixaIdempotencia
  tipo             "foto" | "assinatura"
  seq
  formato          "jpeg" | "png"
  capturadoEm
  arquivo

O que precisa voltar

200 { "sucesso": true }

As regras

  • ●"anexoId" nasce no aparelho, não no servidor — a baixa pode citá-lo antes mesmo de o upload confirmar.
  • ●Um anexo sem baixa que o cite ainda é estado normal, não erro.
  • ●Reenvio do mesmo anexoId não duplica o arquivo armazenado.
  • ●Formato aceito hoje: jpeg e png para foto; a assinatura sobe como imagem também.

O único endpoint inteiramente novo: POST /mobile/anexos

Todos os outros traduzem algo que já existe hoje. Este não tem equivalente no backend atual — cada foto e cada assinatura sobem por ele, uma de cada vez, antes da baixa fechar.

Evolução: três passos, direto ao armazenamento

URL assinada válida por cerca de 30 minutos; o anexoId nasce no celular antes do upload; o TMS precisa ouvir o evento do storage para saber que o arquivo chegou.

POST /mobile/anexos/autorizacao        → devolve URL assinada
PUT  <url assinada>                     → sobe o arquivo direto no storage
POST /mobile/anexos/{id}/confirmacao    → avisa o TMS que terminou
POST/mobile/anexos (tipo "audio")
Ditado por voz
Evolução já embarcada no aplicativo 6.0.10; falta o lado do TMS. Permite ditar nome, documento ou observação em vez de digitar.

O que o app manda

multipart/form-data
  anexoId
  servicoId
  baixaIdempotencia
  tipo             "audio"
  campo            "nome" | "documento" | "observacao"
  transcricao
  duracaoSeg
  formato          "m4a"
  capturadoEm
  arquivo

As regras

  • ●A baixa estende os campos de origem: recebedor.nomeOrigem / nomeAudioAnexoId, recebedor.documentoOrigem / documentoAudioAnexoId, ocorrencia.observacaoOrigem.
  • ●"transcricao" vai junto no upload — o aparelho já transcreve localmente.
  • ●Formato de áudio é m4a (AAC).
  • ●Este endpoint já está em produção no app; falta o TMS aceitar e armazenar.

Já embarcado no app 6.0.10 — falta o TMS

O aplicativo já grava, transcreve e envia. O que falta é o servidor aceitar o tipo "audio" e decidir o que fazer com ele.

Para explicar em uma frase

É a mesma rota de anexo de sempre, só que com tipo "audio" e um campo de transcrição feita no aparelho.

O que precisamos ouvir do TMS antes de fechar

Três perguntas em aberto: um áudio sem transcrição confiável é aceito do mesmo jeito? A retenção do áudio segue a mesma regra das fotos ou tem prazo próprio por LGPD? O formato AAC/M4A serve, ou precisa ser WAV?

POST/mobile/posicoes
Posições — rastreamento em lote
Envia várias leituras de GPS de uma vez. Já houve lote real com 316 posições numa única chamada.

O que o app manda

{
  "placa": "AAA-1122",
  "romaneio": "4471",
  "posicoes": [
    { "lat": -23.55, "lon": -46.63, "precisaoM": 12, "em": "2026-09-11T14:02:00.000Z" }
  ]
}

O que precisa voltar

200 { "sucesso": true }

As regras

  • ●Guardem as duas datas: quando o GPS mediu ("em") e quando o servidor recebeu — elas não coincidem em campo.
  • ●Posição com data antiga dentro do lote é correta: é o aparelho reenviando o que ficou preso na fila.
  • ●Lote parcialmente inválido: aceitem o que der, não rejeitem o lote inteiro por uma leitura ruim.
  • ●Recusa aqui é silenciosa — não há tela de erro de rastreio para o motorista.
  • ●Caminhão parado não manda posição: intervaloPosicaoSeg e intervaloEnvioSeg controlam o ritmo, e "rastrear" (da sessão) liga isso por romaneio inteiro, não por documento — evita pedir permissão de localização em segundo plano sem necessidade, que no Android 11+ tem fricção própria.
POST/mobile/dispositivos
Dispositivos — registro para push
Evolução: registra o token do aparelho para o TMS avisar quando o romaneio mudar, em vez de o app só consultar por polling.

O que o app manda

POST /mobile/dispositivos
{ "tokenFcm": "...", "dispositivo": { "so": "android", "versaoApp": "6.0.20" } }

mensagem enviada pelo TMS ao FCM, quando o romaneio muda:
{ "tipo": "romaneio-alterado", "romaneio": "4471" }

As regras

  • ●A mensagem do FCM é de dados ("data message"), não de notificação — quem decide o que fazer é o aplicativo, não o sistema operacional.
  • ●Push é otimização, nunca garantia: o app continua consultando /mobile/romaneio/{t}/alteracoes por conta própria mesmo com push registrado.

Observabilidade — o que a central enxerga

1. Última posição recebida
Guardem duas datas: quando o GPS mediu e quando o servidor recebeu. A diferença entre elas já denuncia fila presa.
2. Último contato do aplicativo
Qualquer chamada bem-sucedida conta. O alarme de "aparelho mudo" se apoia nesta data, não só na de posição.
3. Deveria estar rastreando?
O TMS deriva isso sozinho: romaneio aberto e algum serviço ainda sem baixa. Não é um campo que o app manda.
4. Início do romaneio
Compara a hora prevista de saída com a hora da primeira chamada do dia — distingue "o app não subiu" de "o motorista está atrasado".

A quinta informação: o alarme que presta

Um farol de três cores, derivado das quatro informações acima: tudo certo quando a última posição é recente; sem posição há 30 minutos devendo rastrear vira aviso; sem posição há 60 minutos, ou aparelho mudo, vira alerta.

Perguntas em aberto

O que falta confirmar com o time do TMS antes de fechar o contrato definitivo.

  1. 1.Qual é o endereço base dos endpoints /mobile/*? A documentação define os caminhos, não o host.
  2. 2.Como se entra em homologação — existe uma transportadora 999 reservada para isso, como há uma 0000 para demonstração?
  3. 3.Qual é o mecanismo de autenticação? A validade do token precisa cobrir o turno inteiro do motorista, sem reautenticar no meio do dia.
  4. 4.As datas trafegam em UTC ou com o fuso -03:00? O incidente de 09/08/2026 (82 de 86 chamadas rejeitadas) veio exatamente dessa ambiguidade.
  5. 5.O upload de anexo em três passos (autorização, PUT no storage, confirmação) está aceito, e qual é o limite de corpo por foto — hoje gira em torno de 525 KB?
  6. 6.As três garantias da sessão (romaneio sem paginação, sessão nova não invalida a fila, recusa de negócio explica o motivo) estão confirmadas?
  7. 7.Quando a central cancela um serviço e o motorista já deu baixa nele antes de sincronizar, qual lado vale?
  8. 8.Quem cadastra os parâmetros do romaneio — fotosObrigatorias (0 a 10), exigeNome/Documento/Assinatura, os ritmos de rastreio?
  9. 9.O campo "rastrear" vem por romaneio, dentro da sessão, como este guia descreve?
  10. 10.De onde vem o catálogo de ocorrências — o código numérico é estável entre transportadoras?
  11. 11.Existe um projeto Firebase configurado para o push funcionar quando o endpoint de dispositivos estiver pronto?

Atualizações do aplicativo

Ver todas
App6.0.35

App 6.0.35 — botão do DANFE

O botão da nota na coleta passa à opção 1 escolhida em 02/10.

  • "Bipar código de barras do DANFE" numa linha, com o desenho do código de barras embaixo.
  • Sem a palavra QR, também na tela da câmera.
  • Suíte fechou 527 de 527.
App6.0.34

App 6.0.34 — alterações do romaneio e coleta sem volume

Os dois ajustes combinados em 01/10.

  • Romaneio com serviço pendente continua tendo as alterações consultadas, mesmo quando o TMS responde "não localizado".
  • Coleta feita não passa com 0 volumes; o app orienta usar "Não foi possível coletar".
  • Suíte fechou 527 de 527.
App6.0.33

App 6.0.33 — relatório Android de 30/09

Os sete itens do teste no Android: textos do login e da bipagem, código de transportadora com 2 dígitos, tipo do documento de viagem e o teclado que cobria os campos.

  • Login: mensagem inteira, botão "Receber serviços" e código com 2 dígitos.
  • Documento de viagem com tipo e número: RE, MDF-e, MDM, RC e MDO.
  • Bipagem sem MDF-e, sem subtítulo e sem o texto do rodapé; botão "Bipar código de barras ou o QR do DANFE".
  • Teclado: o campo em digitação fica sempre visível.
  • Suíte fechou 521 de 521.
App6.0.32

App 6.0.32 — o GPS para no último serviço e ao desconectar

O relatório de 29/09. O app mandava parar o GPS no fim do romaneio e no desconectar, mas conferia o estado numa leitura antiga e não parava. Agora para de verdade.

  • Último serviço baixado: o app para de ler a localização.
  • Desconectar: para na hora, com ou sem serviço pendente.
  • Central incluiu serviço depois: o rastreamento volta e para de novo na baixa.
  • Aparelho com o GPS preso pela versão anterior é liberado; posição lida depois do desconectar não sobe.
  • Suíte fechou 514 de 514.
App6.0.31

App 6.0.31 — som em todas as fotos, alerta de coleta nova em qualquer caminho, obrigatoriedade do recebedor pelo TMS

O relatório de 22/09. O clique da foto tocava em uma e pulava a seguinte: o vídeo enviado mostra 8 capturas e o som saiu em 5. O app mandava rebobinar e disparar no mesmo instante, e quando o disparo chegava primeiro tocava o fim do arquivo, que é silêncio. Agora espera o rebobinar e toca em todas. O alerta de coleta nova passou a tocar onde o serviço é detectado, o que cobre os dois relatos do dia: romaneio com uma coleta só e coleta inserida pela central. E a obrigatoriedade de nome, RG e assinatura passa a seguir o TMS: o servidor confirmou que parâmetro inativo não gera a linha no JSON, e o app lia esse silêncio como "exige".

  • Foto: o clique toca em todas as capturas; antes pulava uma a cada duas, em média.
  • Romaneio: o alerta toca no momento da detecção, inclusive em segundo plano e com uma coleta só no romaneio.
  • Recebedor: linha ausente no JSON passa a valer como parâmetro inativo; se o bloco da transportadora não chegar, o app volta a exigir os três.
  • Auditoria: a abertura de sessão registra qual padrão foi aplicado quando o TMS não manda a obrigatoriedade.
  • Suíte fechou 506 de 506.
App6.0.30

App 6.0.30 — som na foto e na coleta nova, voltar na tela de foto

Os quatro itens do relatório de ajustes de 21/09. A câmera passou a tocar um clique a cada foto, em coleta, entrega e ocorrência, e o som sai mesmo com o aparelho no silencioso, igual nas duas plataformas. Coleta ou romaneio novo agora avisa com som, além do aviso visual. A tela de foto ganhou a seta de voltar: quem bipou uma nota e percebeu que faltavam outras volta para a leitura de NF-e, remove a errada e segue, sem perder a baixa. E nome e documento do recebedor deixam de ser exigidos quando o TMS diz que não são — o app lia a obrigatoriedade do documento de um lugar só e, na falta, exigia. Homologação: TestFlight no iPhone, APK do Expo no Android.

  • Foto: clique curto a cada captura, nas três telas que tiram foto; funciona no silencioso e no Android.
  • Romaneio: alerta sonoro quando entra coleta ou romaneio novo, uma vez por lote.
  • Baixa: seta de voltar na tela de foto — dá para rever e remover NF-e bipada antes de baixar.
  • Recebedor: nome e documento só são exigidos se o TMS exigir; a obrigatoriedade passa a ser lida em qualquer grafia de chave e também no cadastro da transportadora.
  • Auditoria: a abertura de sessão registra de qual chave veio cada obrigatoriedade — nomes de chave, nenhum dado de pessoa.
  • Suíte fechou 502 de 502.
App6.0.29

App 6.0.29 — o app para de conferir dígito de RG

RG não tem regra nacional: cada estado emite do seu jeito, vários não têm dígito e o campo é um só, "RG OU CPF", sem a UF. O RG de São Paulo tem 8 números mais o dígito, e quem digitava só os 8 — que é o comum — recebia "Confira o RG: o dígito não bateu" num documento correto. Agora o app recusa só o que não pode ser documento nenhum: vazio, menos de 5 números, número repetido ou sequência. Onze números com dígito de CPF errado viram aviso, não erro. Nas 176 baixas de 11 a 21/09 o TMS nunca recusou uma baixa por causa do documento. Homologação: TestFlight no iPhone, APK do Expo no Android.

  • Recebedor: dígito de RG deixa de ser conferido — RG correto não dá mais alarme falso.
  • Recebedor: barra só o impossível (vazio, menos de 5 números, repetido, sequência).
  • Recebedor: 11 números com dígito de CPF errado viram aviso, não erro — pode ser RG de 11 posições.
  • Auditoria: 176 baixas de 11 a 21/09, nenhuma recusada pelo TMS por causa do documento.
  • Suíte fechou 496 de 496.
App6.0.28

App 6.0.28 — RG e CPF conferidos de verdade, teclado fecha no ditado e prazo da coleta no card

O campo RG ou CPF passa a decidir pelo tamanho: CPF confere os dígitos verificadores e RG de 8 ou 9 posições tem o dígito conferido pela conta de SP, como aviso, sem travar quem tem RG de outro estado. Obrigatório errado trava dizendo o motivo; opcional errado não trava e fica de fora da baixa. Tocar no microfone fecha o teclado. O card mostra o prazo da coleta, a auditoria conta esse campo e o tamanho dos anexos, e romaneio encerrado deixa de ser consultado em segundo plano. Homologação: TestFlight no iPhone, APK do Expo no Android.

  • Recebedor: 11 dígitos é CPF com dígito verificador; RG de 8 ou 9 posições conferido pela conta de SP, como aviso.
  • Recebedor: obrigatório errado trava com o motivo; opcional errado avisa e fica de fora da baixa.
  • Ditado: o microfone fecha o teclado.
  • Coleta: prazo (coletarAte) no card; auditoria conta o campo e o tamanho de cada anexo.
  • Romaneio encerrado sai da consulta em segundo plano.
  • Suíte fechou 500 de 500.

Testando a v6 e achou algo que este guia não explica? Veja as respostas prontas em Dúvidas.

Ver o contrato medidoBaixar o YAML