{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"f25a7e0d-6789-428b-a83e-b22a7b151a2b","name":"API do Navitrine","description":"A API do Navitrine deixa o sistema da sua loja conversar com a vitrine: publicar o\ncatálogo, manter preço e disponibilidade em dia e receber os pedidos que os clientes\nfizerem.\n\nEla é feita para ser usada por quem já tem um sistema — ERP, PDV, cardápio digital —\ne quer que ele seja a fonte do que aparece na vitrine.\n\n## Primeiros passos\n\n1. O lojista gera um **token de acesso** no painel do Navitrine, em\n   *Configurações → Integrações → API*, e escolhe o que ele pode fazer (os escopos).\n2. Guarde o token: ele aparece **uma única vez**. Se perder, gere outro — o antigo\n   continua valendo até ser revogado.\n3. Confirme que está tudo certo chamando `GET /me`. A resposta diz de qual loja é o\n   token e o que ele pode fazer.\n\n```bash\ncurl {{baseUrl}}/me \\\n  -H \"Authorization: Bearer {{token}}\"\n```\n\n## Comece por aqui: conta de desenvolvedor\n\nVocê não precisa de um lojista para começar. Crie sua conta e saia com a credencial:\n\n```bash\ncurl -X POST {{baseUrl}}/dev/registrar \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"nome\":\"ERP da Silva\",\"email\":\"dev@erpdasilva.com.br\",\"password\":\"uma-senha-boa-2026\"}'\n```\n\nA resposta traz uma credencial `nvt_test_` e uma **loja de testes**: uma loja de\nmentira que não aparece na vitrine, não é cobrada e não avisa lojista nenhum. É onde\nvocê erra à vontade — sobe catálogo torto, apaga tudo, simula pedido.\n\nNela existem duas rotas que não existem em produção: `POST /sandbox/pedidos`, que\nsimula um pedido e dispara o webhook (em produção, o pedido só nasce de um cliente\ncomprando), e `POST /sandbox/limpar`, para recomeçar do zero.\n\nQuando um lojista contratar você, ele gera no painel dele uma credencial `nvt_live_`\nda loja real. **Uma não vale no lugar da outra**: chave de teste apontando para a loja\nque vende é recusada, e o contrário também. É o que impede o acidente de subir\ncatálogo de homologação em quem está vendendo.\n\n## Autenticação\n\nTodas as chamadas levam o token no cabeçalho:\n\n```\nAuthorization: Bearer {{token}}\n```\n\n**O token já diz de qual loja se trata** — nenhuma rota pede o id da loja. Isso\ntambém significa que um token nunca alcança o catálogo ou os pedidos de outra loja.\n\nCada token carrega escopos, e a rota recusa (403) o que estiver fora deles:\n\n| Escopo | Permite |\n| --- | --- |\n| `catalogo:ler` | ler categorias e itens |\n| `catalogo:escrever` | criar, editar e remover categorias e itens |\n| `pedidos:ler` | listar e consultar pedidos |\n| `webhooks:gerenciar` | configurar para onde os eventos são enviados |\n\n## Como manter o catálogo em dia\n\nHá dois caminhos, e o segundo é o recomendado para quem tem sistema próprio:\n\n- **Item a item** — `POST /itens`, `PATCH /itens/{id}`, `DELETE /itens/{id}`. Bom para\n  alterações pontuais feitas por uma tela.\n- **Em lote, pela sua referência** — `POST /itens/lote` envia até 500 itens de uma vez,\n  identificados por `referencia_externa` (o código do item no *seu* sistema). O que não\n  existe é criado, o que existe é atualizado, e você nunca precisa guardar o id do\n  Navitrine. É assim que uma carga de catálogo inteira roda todo dia sem virar 500\n  chamadas.\n\nPara sincronizar só o que mudou, use `atualizado_desde` na listagem:\n\n```\nGET /itens?atualizado_desde=2026-08-21T03:00:00Z&perPage=100\n```\n\n## Pedidos\n\nO cliente fecha o pedido na vitrine e ele fica disponível aqui. Você recebe de duas\nformas, que podem conviver:\n\n- **Consultando** (`GET /pedidos?desde=...`) de tempos em tempos — simples e suficiente\n  para a maioria.\n- **Recebendo o evento** no seu endereço, configurado em `PUT /webhooks`. Chega mais\n  rápido e evita consulta em vão.\n\nTodo pedido tem `numero` (sequencial por loja, o que o lojista enxerga) além do `id`.\n\n## Webhooks\n\nConfigurado o endereço, o Navitrine envia `POST` com o evento no corpo e assina a\nrequisição:\n\n```\nX-Navitrine-Event: pedido.criado\nX-Navitrine-Delivery: 018f3c1e-...\nX-Navitrine-Signature: sha256=3a7bd3e2360a...\n```\n\nA assinatura é o HMAC-SHA256 do **corpo cru** com o seu segredo. Compare com o que\nvocê calcular, em comparação de tempo constante — sem isso qualquer um pode fingir\nser o Navitrine.\n\nResponda **2xx em até 10 segundos**. Qualquer outra coisa (ou demora) vira nova\ntentativa: 1min, 5min, 30min, 2h e 6h depois. O mesmo evento pode chegar duas vezes —\nuse o `X-Navitrine-Delivery` para ignorar repetido.\n\n## Paginação\n\nAs listagens devolvem sempre o mesmo envelope:\n\n```json\n{ \"data\": [], \"page\": 1, \"perPage\": 50, \"total\": 137 }\n```\n\n`page` começa em 1 e `perPage` vai até 200.\n\n## Escrita sem duplicar\n\nEm `POST`, mande `Idempotency-Key` com um valor único seu (um uuid serve). Repetindo a\nchamada com a mesma chave em até 24h, a resposta é a da primeira — é o que salva a\nintegração quando a conexão cai depois de o pedido já ter sido criado.\n\n## Limites de uso\n\n120 requisições por minuto por token, e `POST /itens/lote` conta como uma. Toda\nresposta traz `RateLimit-Limit`, `RateLimit-Remaining` e `RateLimit-Reset`; ao estourar,\na resposta é **429** com `Retry-After`.\n\n## Formatos\n\n- Datas em ISO 8601, UTC (`2026-08-21T14:32:00.000Z`).\n- Dinheiro em **string** com duas casas (`\"49.90\"`) — converter para float antes de\n  somar é como se perde centavo.\n- Campos de texto vazios chegam como `null`, não como `\"\"`.\n\n## Erros\n\nToda falha responde com o mesmo corpo:\n\n```json\n{\n  \"statusCode\": 400,\n  \"path\": \"/api/v1/itens\",\n  \"timestamp\": \"2026-08-21T14:32:00.000Z\",\n  \"message\": \"Categoria não pertence a esta loja\",\n  \"errors\": { \"categoria_id\": [\"Categoria não encontrada\"] }\n}\n```\n\nA `message` é em pt-BR e pode ser mostrada a quem opera o seu sistema. `errors` só\naparece quando a falha é de validação, com o motivo por campo.\n\n**Decida pelo `statusCode`, nunca pelo texto da `message`.** O texto melhora com o\ntempo — a mensagem que você casar com uma expressão regular hoje muda amanhã sem\nque isso seja uma quebra de contrato.\n\n### O que cada código significa\n\n| Código | O que aconteceu | O que fazer |\n| --- | --- | --- |\n| **400** | Corpo ou parâmetro inválido. `errors` traz o motivo por campo. | Corrigir e reenviar. Repetir igual dá o mesmo erro. |\n| **401** | Token ausente, inválido, revogado, ou da loja que foi excluída. | Conferir o cabeçalho; se persistir, gerar outra credencial. |\n| **403** | Token válido, mas barrado: falta o escopo, a loja está sem assinatura paga, o plano estourou o limite de itens, ou a rota é só de sandbox. | A `message` diz qual dos casos. Nenhum se resolve repetindo. |\n| **404** | O recurso não existe **ou não é desta loja** — os dois respondem igual, de propósito: distinguir contaria a você o que existe na loja dos outros. | Conferir o id. |\n| **409** | Conflito com o que já existe: seção com o mesmo nome, item com a mesma `referencia_externa`, e-mail já cadastrado, ou `Idempotency-Key` repetida com corpo diferente. | Ler a `message`: cada caso pede uma correção diferente. |\n| **429** | Passou de 120 requisições no minuto. | Esperar os segundos de `Retry-After` e repetir. |\n| **5xx** | Falha nossa. | Repetir com espera crescente. Se insistir, falar com o suporte com o `timestamp` da resposta. |\n\nErro de rede ou 5xx num `POST` é o caso em que a `Idempotency-Key` paga sozinha o\ntrabalho de gerá-la: repetir com a mesma chave não cria nada duas vezes.\n\n## Limites de tamanho\n\nO que a API recusa com **400** antes de tocar no banco:\n\n| Onde | Campo | Limite |\n| --- | --- | --- |\n| Item | `nome` | 1 a 200 caracteres |\n| Item | `descricao` | até 2000 caracteres |\n| Item | `referencia_externa` | 1 a 120 caracteres |\n| Item | `preco`, `preco_promocional` | decimal com até 2 casas, como `\"49.90\"` |\n| Item | `foto_url` | URL válida |\n| Seção | `nome` | 1 a 120 caracteres |\n| Seção | `ordem` | inteiro ≥ 0 |\n| Carga em lote | `itens` | 1 a 500 por chamada |\n| Listagens | `perPage` | 1 a 200 (padrão 50) |\n| Listagens | `page` | inteiro ≥ 1 |\n| Horário | `dia_semana` | 0 (domingo) a 6 (sábado) |\n| Horário | `abre`, `fecha` | `HH:MM`, e `fecha` depois de `abre` |\n| Webhook | `url` | URL **https** |\n| Sandbox | `observacoes` | até 500 caracteres |\n\nTexto é aparado nas pontas antes de medir, então espaço sobrando não derruba a\nchamada.\n\n## Versionamento e depreciação\n\nA versão está no caminho: **`/api/v1`**. Enquanto for `v1`, o que está documentado\naqui continua funcionando como está descrito.\n\n- **Mudança que quebra integração ganha caminho novo** (`/api/v2`). Nunca trocamos o\n  comportamento de uma rota `v1` por baixo de quem já a usa.\n- Quando existir uma `v2`, a `v1` fica de pé por **no mínimo 6 meses** depois do\n  anúncio, e avisamos por e-mail no endereço da conta de desenvolvedor.\n- Campo em vias de sair é marcado com `deprecated: true` neste contrato **antes** de\n  parar de existir, e continua sendo devolvido enquanto a versão viver.\n\n## O que pode mudar sem aviso\n\nEstas mudanças **não** são consideradas quebra, e sua integração precisa aguentá-las:\n\n- **Campo novo numa resposta.** Ignore o que não conhece; não recuse a resposta por\n  causa de campo que não esperava.\n- **Campo opcional novo num corpo de requisição.** O que você já manda continua valendo.\n- **Valor novo num campo de lista fechada** (`forma_pagamento`, `situacao` da entrega).\n  Trate valor desconhecido com um caminho padrão, em vez de estourar.\n- **Texto de `message` e de `errors`.** Melhoram sem aviso — case pelo `statusCode`.\n- **Ordem dos itens** em listagem sem ordenação documentada.\n\nE o contrário, que **é** quebra e portanto só acontece numa versão nova: remover\ncampo, mudar tipo de campo, tornar obrigatório o que era opcional, mudar o\nsignificado de um código de status.\n\nCampo desconhecido que você mandar no corpo é **ignorado**, não recusado — o que\nfacilita a vida de quem manda o mesmo objeto para vários destinos.\n\n\nContact Support:\n Name: Suporte Navitrine","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"56898986","team":28504494,"collectionId":"f25a7e0d-6789-428b-a83e-b22a7b151a2b","publishedId":"2sBYArVss6","public":true,"publicUrl":"https://documenter-api.postman.tech/view/56898986/2sBYArVss6","privateUrl":"https://go.postman.co/documentation/56898986-f25a7e0d-6789-428b-a83e-b22a7b151a2b","customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"0138C6"},"documentationLayout":"classic-single-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"system_default","themes":[{"name":"dark","logo":"https://content.pstmn.io/29c352f0-8d51-431f-be5a-9dfdb957ead2/bmF2aXRyaW5lLWljb25lLTEwMjQucG5n","colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"0138C6"}},{"name":"light","logo":"https://content.pstmn.io/29c352f0-8d51-431f-be5a-9dfdb957ead2/bmF2aXRyaW5lLWljb25lLTEwMjQucG5n","colors":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"0138C6"}}]}},"version":"8.12.3","publishDate":"2026-08-22T10:40:13.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":"https://content.pstmn.io/29c352f0-8d51-431f-be5a-9dfdb957ead2/bmF2aXRyaW5lLWljb25lLTEwMjQucG5n","logoDark":"https://content.pstmn.io/29c352f0-8d51-431f-be5a-9dfdb957ead2/bmF2aXRyaW5lLWljb25lLTEwMjQucG5n"}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/5e8efe65fdba25382dfa31b9f518bc61c3f716f986d382b7eaff8b4b8c1f3264","favicon":""},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://documenter.gw.postman.com/view/metadata/2sBYArVss6"}