{"openapi":"3.0.3","info":{"title":"EntregaMaps — API de integracao","version":"1.0.0","description":"API para sistemas de delivery (PDV, ERP, marketplace) enviarem pedidos ao\nEntregaMaps, que monta as rotas e devolve a baixa quando a entrega e confirmada.\n\n## Como funciona\n\n1. Seu sistema envia o pedido em `POST /api/v1/pedidos` (endereco em texto basta —\n   o EntregaMaps resolve a coordenada).\n2. O pedido entra no **pool**, esperando ser roteirizado.\n3. O gestor monta uma rota com varios pedidos e oferece a um entregador,\n   que aceita a rota inteira. (Ou o entregador digita o numero do pedido e assume.)\n4. Na porta do cliente, o entregador confirma a entrega.\n5. O EntregaMaps chama o **webhook** do seu sistema com `pedido.entregue`,\n   para voce dar baixa do seu lado.\n\n## Link para o cliente\n\nLogo depois de criar o pedido, pegue o link de rastreio em\n`GET /api/v1/pedidos/{id}/acompanhamento` e mande ao cliente no WhatsApp ou por SMS.\nE o mesmo link do painel: mostra a situacao da entrega e, quando ele for o proximo da\nrota, o entregador andando no mapa. Nao expoe os outros pedidos nem os valores da\noperacao, e vale ate 30 minutos apos a entrega.\n\n## Mudou alguma coisa no pedido?\n\nEnquanto nao foi entregue, use `PATCH /api/v1/pedidos/{id}` para corrigir valor, troco,\ntelefone ou ponto de referencia — a correcao chega na hora ao entregador. Endereco\ndiferente e outro pedido: cancele e mande de novo.\n\n## Autenticacao\n\nTodas as rotas `/api/v1` exigem a chave de API no cabecalho:\n\n```\nAuthorization: Bearer em_sua-chave-aqui\n```\n\nA chave e criada no painel gerencial, em **Integracoes**, e aparece **uma unica vez**.\n\n## Webhook\n\nConfigure a URL (https) ao criar a integracao. O EntregaMaps envia:\n\n```json\n{ \"evento\": \"pedido.entregue\", \"enviadoEm\": 1786460000000, \"dados\": { } }\n```\n\nCom os cabecalhos:\n\n- `X-EntregaMaps-Evento: pedido.entregue`\n- `X-EntregaMaps-Assinatura: sha256=<hmac>`\n\nA assinatura e o HMAC-SHA256 do corpo cru usando o **segredo** devolvido na criacao.\nConfira antes de processar — e o que garante que a chamada veio daqui.\n\nResponda **2xx** para confirmar. Em 5xx ou timeout, tentamos de novo 3 vezes\n(5s, 10s, 15s). Em 4xx desistimos, entendendo que o pedido foi recusado.","contact":{"name":"Suporte EntregaMaps"}},"servers":[{"url":"https://entregas.joelmirsantana.site","description":"Producao"}],"tags":[{"name":"Pedidos","description":"Enviar e acompanhar pedidos"},{"name":"Entregadores","description":"Quem esta disponivel"},{"name":"Rotas","description":"Acompanhar a rota montada"},{"name":"Acompanhamento","description":"O link de rastreio que o cliente recebe"}],"components":{"securitySchemes":{"ChaveDeApi":{"type":"http","scheme":"bearer","description":"Chave criada no painel, em Integracoes. Formato: `em_...`"}},"schemas":{"PedidoEntrada":{"type":"object","required":["endereco"],"properties":{"idExterno":{"type":"string","description":"Identificador do pedido no SEU sistema. Reenviar o mesmo idExterno nao duplica — devolve o pedido que ja existe. Use para reenviar com seguranca apos timeout.","example":"PED-2026-00184"},"numeroPedido":{"type":"string","description":"Numero que o entregador ve e digita. Se vazio, usa o idExterno.","example":"184"},"localizador":{"type":"string","description":"Localizador do pedido no iFood (8 digitos). So para pedido do iFood; deixe vazio nos demais.","example":"48213097"},"origem":{"type":"string","enum":["ifood","outro"],"description":"De onde veio o pedido. Se omitido, deduz pelo localizador."},"endereco":{"type":"string","description":"Endereco completo em texto. Alternativa: enviar rua/numero/bairro/cidade separados, que costuma acertar mais.","example":"Avenida Piaui, 1802, Zona 7, Cianorte - PR"},"rua":{"type":"string","example":"Avenida Piaui"},"numero":{"type":"string","example":"1802"},"bairro":{"type":"string","example":"Zona 7"},"cidade":{"type":"string","example":"Cianorte"},"uf":{"type":"string","example":"PR"},"lat":{"type":"number","format":"double","description":"Se voce ja tem a coordenada, envie — evita erro de geocodificacao.","example":-23.6612},"lng":{"type":"number","format":"double","example":-52.6053},"cliente":{"type":"string","example":"Maria Souza"},"telefone":{"type":"string","example":"44999998888"},"apelido":{"type":"string","description":"Referencia para achar o local (apartamento, portao, ponto de referencia).","example":"Ap 302, portao azul"},"valor":{"type":"number","format":"double","description":"Valor a receber na entrega. Zero ou vazio se ja foi pago.","example":74.9},"formaPagamentoPrevista":{"type":"string","description":"O que o cliente disse que vai usar. So informativo.","example":"dinheiro"},"temBebida":{"type":"boolean","description":"Marque quando o pedido tem bebida: o app lembra o entregador de conferir a sacola antes de sair da loja.","example":true},"entregadorId":{"type":"string","format":"uuid","description":"Opcional. Se informado, o pedido ja nasce com dono em vez de entrar no pool."}}},"Pedido":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"idExterno":{"type":"string","nullable":true},"numeroPedido":{"type":"string","nullable":true},"localizador":{"type":"string","nullable":true},"status":{"type":"string","enum":["pendente","entregue","cancelada"]},"endereco":{"type":"string"},"cliente":{"type":"string","nullable":true},"valor":{"type":"number","nullable":true},"temBebida":{"type":"boolean"},"lat":{"type":"number"},"lng":{"type":"number"},"precisao":{"type":"string","nullable":true,"enum":["exata","interpolada","aproximada","agenda","estimada","informada"],"description":"Confianca no ponto. `agenda` = ja conferido pela equipe na rua; `aproximada` = caiu no meio da rua."},"entregadorId":{"type":"string","nullable":true},"entregador":{"type":"string","nullable":true},"criadaEm":{"type":"integer","format":"int64"},"entregueEm":{"type":"integer","format":"int64","nullable":true},"pagamento":{"$ref":"#/components/schemas/Pagamento"}}},"Pagamento":{"type":"object","nullable":true,"description":"Preenchido na confirmacao da entrega.","properties":{"formas":{"type":"array","items":{"type":"object","properties":{"tipo":{"type":"string","enum":["online","pix","dinheiro","debito","credito"]},"valor":{"type":"number","nullable":true}}}},"recebido":{"type":"number","description":"Total que ficou em maos do entregador."},"misto":{"type":"boolean"}}},"Rota":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["oferecida","aceita","recusada","cancelada"]},"entregadorId":{"type":"string"},"entregador":{"type":"string","nullable":true},"criadaEm":{"type":"integer","format":"int64"},"aceitaEm":{"type":"integer","format":"int64","nullable":true},"concluidas":{"type":"integer"},"previsao":{"type":"object","properties":{"paradas":{"type":"integer"},"distancia":{"type":"number","nullable":true,"description":"metros"},"duracao":{"type":"number","nullable":true,"description":"segundos"}}},"paradas":{"type":"array","items":{"$ref":"#/components/schemas/Pedido"}}}},"Entregador":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"nome":{"type":"string"},"online":{"type":"boolean"},"emRota":{"type":"boolean"},"pendentes":{"type":"integer"},"entregues":{"type":"integer"}}},"PedidoEdicao":{"type":"object","description":"Todos os campos sao opcionais — mande so o que mudou. Campo ausente fica como esta; mandar `null` em `valor` limpa o valor. O endereco nao pode ser alterado.","properties":{"valor":{"type":"number","nullable":true,"example":78.5},"formaPagamentoPrevista":{"type":"string","description":"Como o cliente disse que vai pagar. Texto livre, aparece para o entregador.","example":"dinheiro (troco para 100)"},"cliente":{"type":"string","example":"Maria Souza"},"telefone":{"type":"string","example":"44999998888"},"observacao":{"type":"string","description":"Ponto de referencia, recado do cliente, o que ajudar na porta.","example":"portao azul, tocar o interfone 2"},"numeroPedido":{"type":"string","example":"184"}}},"ListaPedidos":{"type":"object","properties":{"total":{"type":"integer","description":"Quantos vieram nesta resposta."},"pedidos":{"type":"array","items":{"$ref":"#/components/schemas/Pedido"}}}},"Acompanhamento":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"idExterno":{"type":"string","nullable":true},"url":{"type":"string","description":"Link pronto para mandar ao cliente, por WhatsApp ou SMS.","example":"https://entregas.joelmirsantana.site/acompanhar/9tK2xY-abc123"},"expiraApos":{"type":"string","example":"a entrega + 30 minutos"}}},"EventoWebhook":{"type":"object","description":"Corpo que o EntregaMaps envia para a sua URL de webhook.","properties":{"evento":{"type":"string","enum":["pedido.entregue"],"example":"pedido.entregue"},"enviadoEm":{"type":"integer","format":"int64","example":1786460000000},"dados":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"idExterno":{"type":"string","nullable":true},"numeroPedido":{"type":"string","nullable":true},"localizador":{"type":"string","nullable":true},"entregueEm":{"type":"integer","format":"int64"},"entregador":{"type":"string","nullable":true},"codigoCliente":{"type":"string","nullable":true,"description":"Codigo que o cliente informou na porta."},"semCodigoCliente":{"type":"boolean","description":"true quando o cliente nao soube informar o codigo."},"pagamento":{"$ref":"#/components/schemas/Pagamento"}}}}},"Erro":{"type":"object","properties":{"erro":{"type":"string","description":"Mensagem em portugues, pronta para log."},"codigo":{"type":"string","description":"Codigo estavel para tratar no seu sistema.","example":"endereco_nao_encontrado"},"dica":{"type":"string","description":"Como resolver, quando aplicavel."}}}},"responses":{"NaoAutorizado":{"description":"Chave de API ausente, invalida ou desativada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"NaoEncontrado":{"description":"Recurso nao existe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}}}},"security":[{"ChaveDeApi":[]}],"paths":{"/api/v1/pedidos":{"post":{"tags":["Pedidos"],"summary":"Enviar um pedido","description":"Cria o pedido no EntregaMaps. Basta o endereco em texto — a coordenada e resolvida aqui, consultando primeiro a agenda de enderecos ja conferidos pela equipe na rua.\n\nReenviar o mesmo `idExterno` devolve **200** com o pedido existente (e `duplicado: true`) em vez de criar outro. Isso torna o reenvio seguro depois de um timeout.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PedidoEntrada"},"examples":{"ifood":{"summary":"Pedido do iFood","value":{"idExterno":"PED-2026-00184","numeroPedido":"184","localizador":"48213097","rua":"Avenida Piaui","numero":"1802","bairro":"Zona 7","cidade":"Cianorte","uf":"PR","cliente":"Maria Souza","valor":0}},"proprio":{"summary":"Venda propria, a receber em dinheiro","value":{"idExterno":"BALCAO-991","numeroPedido":"991","origem":"outro","endereco":"Rua Ipiranga, 636, Zona 1, Cianorte - PR","cliente":"Joao Lima","telefone":"44999998888","valor":74.9,"formaPagamentoPrevista":"dinheiro"}},"comCoordenada":{"summary":"Com coordenada propria (mais preciso)","value":{"idExterno":"PED-77","numeroPedido":"77","endereco":"Rua Arco Iris, 444, Cianorte - PR","lat":-23.6598,"lng":-52.6041}}}}}},"responses":{"200":{"description":"Pedido ja existia (mesmo idExterno)."},"201":{"description":"Pedido criado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pedido"}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"},"422":{"description":"Endereco nao localizado. Envie lat/lng se ja tiver.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}}},"callbacks":{"pedidoEntregue":{"{$request.body#/webhookUrl}":{"post":{"summary":"pedido.entregue — chamamos a SUA URL","description":"Disparado quando o entregador confirma a entrega na porta do cliente.\n\nConfira o cabecalho `X-EntregaMaps-Assinatura` (HMAC-SHA256 do corpo cru, com o segredo da integracao) antes de dar baixa.\n\nResponda 2xx. Em 5xx ou timeout tentamos mais 3 vezes (5s, 10s, 15s).","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventoWebhook"},"example":{"evento":"pedido.entregue","enviadoEm":1786460000000,"dados":{"id":"6f1e2c40-9a11-4f2b-8d3e-77c1a0b5e912","idExterno":"PED-2026-00184","numeroPedido":"184","localizador":"48213097","entregueEm":1786459980000,"entregador":"Joelmir","codigoCliente":"4821","semCodigoCliente":false,"pagamento":{"formas":[{"tipo":"dinheiro","valor":74.9}],"recebido":74.9,"misto":false}}}}}},"responses":{"200":{"description":"Recebido — nao tentamos de novo."},"400":{"description":"Recusado por voce — desistimos sem repetir."},"500":{"description":"Falha sua — repetimos ate 3 vezes."}}}}}}},"get":{"tags":["Pedidos"],"summary":"Listar os seus pedidos","description":"Conferencia de fim de turno: devolve **somente** os pedidos enviados por esta chave, do mais novo para o mais antigo. Compare com a sua lista para achar webhook perdido.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pendente","entregue","cancelada"]},"description":"Filtra por situacao. Vazio traz todos."},{"name":"desde","in":"query","schema":{"type":"integer","format":"int64"},"description":"So pedidos criados a partir deste instante (epoch em milissegundos).","example":1786400000000},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Lista.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListaPedidos"}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"}}}},"/api/v1/pedidos/lote":{"post":{"tags":["Pedidos"],"summary":"Enviar varios pedidos","description":"Ate 100 por chamada. Cada pedido responde por si: os que derem erro voltam em `recusados`, sem derrubar os demais.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pedidos":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/PedidoEntrada"}}}}}}},"responses":{"201":{"description":"Ao menos um aceito.","content":{"application/json":{"schema":{"type":"object","properties":{"aceitos":{"type":"array","items":{"$ref":"#/components/schemas/Pedido"}},"recusados":{"type":"array","items":{"type":"object","properties":{"idExterno":{"type":"string","nullable":true},"erro":{"type":"string"}}}}}}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"},"422":{"description":"Nenhum pedido pode ser aceito."}}}},"/api/v1/pedidos/{id}":{"get":{"tags":["Pedidos"],"summary":"Consultar um pedido","description":"Aceita o `id` do EntregaMaps ou o seu `idExterno`. Serve para acompanhar por consulta quando voce nao quiser usar webhook.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"id do EntregaMaps ou idExterno do seu sistema"}],"responses":{"200":{"description":"Pedido encontrado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pedido"}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"},"404":{"$ref":"#/components/responses/NaoEncontrado"}}},"patch":{"tags":["Pedidos"],"summary":"Corrigir um pedido","description":"Para quando o cliente liga depois de pedir: muda o troco, some um item, chega um ponto de referencia. Vale enquanto o pedido **nao** foi entregue, e a correcao aparece na hora na tela do entregador — sem tirar a entrega da rota ja montada.\n\nO endereco nao entra aqui: destino diferente muda a rota de quem ja esta na rua. Nesse caso, cancele e mande outro pedido.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"id do EntregaMaps ou idExterno do seu sistema"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PedidoEdicao"},"examples":{"troco":{"summary":"Cliente avisou o troco","value":{"formaPagamentoPrevista":"dinheiro (troco para 100)"}},"valorEReferencia":{"summary":"Tirou um item e mandou referencia","value":{"valor":61.4,"observacao":"casa dos fundos, portao azul"}}}}}},"responses":{"200":{"description":"Pedido atualizado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pedido"}}}},"400":{"description":"Valor invalido.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"},"404":{"$ref":"#/components/responses/NaoEncontrado"},"409":{"description":"Pedido ja entregue — nao da mais para corrigir."}}},"delete":{"tags":["Pedidos"],"summary":"Cancelar um pedido","description":"So funciona enquanto o pedido nao foi entregue.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Cancelado."},"401":{"$ref":"#/components/responses/NaoAutorizado"},"404":{"$ref":"#/components/responses/NaoEncontrado"},"409":{"description":"Pedido ja entregue — nao da para cancelar."}}}},"/api/v1/pedidos/{id}/acompanhamento":{"get":{"tags":["Acompanhamento"],"summary":"Pegar o link de rastreio do cliente","description":"Devolve o link que voce manda ao cliente — o mesmo que o gestor copia no painel. Da para enviar junto com a confirmacao do pedido, no WhatsApp ou por SMS.\n\nO cliente **so** ve o mapa quando a entrega dele for a proxima da rota; antes disso a pagina mostra apenas a situacao. O link nao expoe os outros pedidos, o telefone do entregador nem os valores da operacao, e para de valer 30 minutos apos a entrega.\n\nChamar de novo devolve sempre o mesmo link — pode pedir quantas vezes precisar.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"id do EntregaMaps ou idExterno do seu sistema"}],"responses":{"200":{"description":"Link pronto para enviar.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Acompanhamento"},"example":{"id":"6f1e2c40-9a11-4f2b-8d3e-77c1a0b5e912","idExterno":"PED-2026-00184","url":"https://entregas.joelmirsantana.site/acompanhar/9tK2xY-abc123","expiraApos":"a entrega + 30 minutos"}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"},"404":{"$ref":"#/components/responses/NaoEncontrado"}}}},"/api/v1/entregadores":{"get":{"tags":["Entregadores"],"summary":"Listar entregadores","description":"Quem esta online e quantas entregas cada um tem na fila.","responses":{"200":{"description":"Lista.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Entregador"}}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"}}}},"/api/v1/rotas/{id}":{"get":{"tags":["Rotas"],"summary":"Consultar uma rota","description":"Situacao da rota e de cada parada dentro dela.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Rota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Rota"}}}},"401":{"$ref":"#/components/responses/NaoAutorizado"},"404":{"$ref":"#/components/responses/NaoEncontrado"}}}}}}