16 KiB
Atomenta API - Store Management & External Guide (Pedi Foods Edition)
Este documento é o guia definitivo e completo para parceiros e aplicações externas (como pedifoods.com.br) que consomem a API da plataforma Atomenta para gestão de lojas. Esta API reflete 100% das funcionalidades do painel administrativo.
🔐 Autenticação e Headers
Todas as chamadas devem usar autenticação híbrida.
Headers Obrigatórios:
- Accept:
application/json - Atomenta-Token:
550e8400-e29b-41d4-a716-446655440008(Escopo: Store Management) - Authorization:
Bearer <JWT_TOKEN>
🏬 Gestão de Identidade e Lojas
1. Listar Lojas do Usuário
GET /api/store/list - Retorna todas as lojas vinculadas ao token do usuário.
2. Informações Completas da Loja (Settings)
GET /api/store/:storeId/info - Retorna a configuração completa da loja, incluindo dados bancários, horários e flags de pagamento.
Resposta Exemplo:
{
"error": false,
"result": {
"isOpen": true,
"statusLabel": "Aberto Agora",
"isManualOpen": true,
"fantasyName": "Pizzaria do Arantes",
"razaoSocial": "Loverde Co LTDA",
"document": "12.345.678/0001-99",
"documentType": "CNPJ",
"email": "loja@loverde.com.br",
"phone": "11988776655",
"paymentMethods": {
"paymentOnDelivery": true,
"acceptCash": true,
"acceptCreditVisa": true,
"acceptCreditMaster": true,
"acceptCreditElo": true,
"acceptVoucherAlelo": true,
"acceptPix": true
},
"bankInfo": {
"bankName": "Banco do Brasil",
"accountType": "Corrente",
"agency": "1234",
"account": "56789-0",
"pixKey": "12345678000199"
},
"openingHours": {
"monday": [{"open": "18:00", "close": "23:00"}],
"friday": [{"open": "11:00", "close": "15:00"}, {"open": "18:00", "close": "00:00"}]
},
"address": {
"street": "Av. Brasil, 1000",
"latitude": -23.55052,
"longitude": -46.633308
}
}
}
📊 Dashboard Real-time (Portal Parity)
3. Dashboard e Monitoramento
GET /api/store/:storeId/dashboard
Resposta Detalhada (100% Parity):
{
"error": false,
"result": {
"orderFlow": {
"urgencys": [ { "id": "ORD-123", "clientName": "Daniel", "minutes": 45, "status": "PREPARING" } ],
"received": [ /* Pedidos Pendentes */ ],
"inProgress": [ /* Pedidos Em Preparo */ ],
"readyTo": [ /* Pedidos Prontos para Entrega/Retirada */ ],
"inRoute": [ /* Pedidos em Rota */ ],
"delivered": [ /* Pedidos Finalizados na Sessão */ ]
},
"payments": {
"totalSelledToday": 2450.00,
"growthToday": 15.5,
"avgTicket": 65.20,
"growthPeriod": 8.5
},
"alerts": {
"pendingOver3Minutes": 2,
"delayedInProgress": 1
}
}
}
🍴 Catálogo e Menu (Complex Payloads)
3.1 Catálogo Consolidado (App)
GET /api/store/:storeId/catalog
Resposta:
{
"error": false,
"code": "STORE_CATALOG_RETRIEVED",
"result": [
{
"id": "cat_lanches",
"name": "Lanches",
"isPizzaCategory": false,
"products": [
{
"id": "prod_xburger",
"type": "prepared",
"name": "X-Burger",
"description": "Pão, carne e queijo",
"image": "/uploads/products/xburger.jpg",
"price": "25.00",
"addons": "yes",
"addonGroups": []
}
]
},
{
"id": "cat_pizzas",
"name": "Pizzas",
"isPizzaCategory": true,
"pizzaConfig": {
"sizes": [{ "id": "broto", "name": "Broto", "slices": 4, "maxFlavors": 1 }],
"doughs": [{ "id": "tradicional", "name": "Tradicional", "active": true }],
"crusts": [{ "id": "catupiry", "name": "Catupiry", "active": true, "priceModifier": "10.00" }]
},
"products": [
{
"id": "prod_pizza_calabresa",
"type": "pizza",
"name": "Pizza Calabresa",
"description": "Molho, mussarela e calabresa",
"image": "/uploads/products/pizza-calabresa.jpg",
"price": "0.00",
"pizzaPrices": {
"broto": "35.00",
"grande": "55.00"
},
"addons": "yes",
"addonGroups": []
}
]
}
]
}
Regra de identificação de pizza:
- Item pizza:
products[].type === "pizza". - Configuração de montagem vem em
category.pizzaConfig. - Preço por tamanho vem em
product.pizzaPrices.
4. Listar Categorias do Catálogo
GET /api/store/:storeId/catalog/categories
Resposta:
{
"error": false,
"code": "CATEGORIES_RETRIEVED",
"result": [
{ "id": "cat_1", "name": "Pizzas", "isActive": true }
],
"message": "Categorias recuperadas com sucesso"
}
5. Criar Categoria (Ex.: Pizza)
POST /api/store/:storeId/catalog/categories
{
"name": "Pizzas Salgadas",
"isPizzaCategory": true,
"pizzaConfig": {
"sizes": [
{ "id": "small", "name": "Broto", "slices": 4, "maxFlavors": 1 },
{ "id": "large", "name": "Grande", "slices": 8, "maxFlavors": 3 }
],
"doughs": [ { "id": "tradicional", "name": "Tradicional", "price": 0 } ],
"crusts": [ { "id": "catupiry", "name": "Borda de Catupiry", "price": 10.00 } ]
}
}
6. Atualizar Categoria
PUT /api/store/:storeId/catalog/categories/:id
7. Excluir Categoria
DELETE /api/store/:storeId/catalog/categories/:id
8. Produtos Tipo Combo ou Pizza
POST /api/store/:storeId/catalog/products
{
"type": "pizza",
"name": "Pizza de Calabresa",
"categoryId": "cat_pizzas",
"pizzaPrices": {
"small": "35.00",
"large": "55.00"
},
"addonGroups": [
{
"name": "Remover Ingredientes",
"minSelectors": 0, "maxSelectors": 5,
"items": [ { "name": "Sem Cebola", "price": 0 } ]
}
]
}
📦 Histórico e Detalhes do Pedido
9. Histórico com Filtros
GET /api/store/:storeId/orders/history?start=2024-01-01&end=2024-01-31&q=Ana
Objeto de Pedido Completo (result.list[0]):
{
"id": "order_guid",
"shortId": "1234",
"clientName": "Arantes Loverde",
"totalValue": 120.50,
"netValue": 112.40,
"pediFoodsFee": 1.00,
"status": "COMPLETED",
"createdAt": "2024-01-08T15:00:00Z",
"confirmOtp": "12345678",
"deliveryEstimate": "35-50 min",
"deliveryTypeLabel": "Entrega Própria",
"timeline": [
{ "status": "PENDING", "time": "15:00:00", "message": "Pedido criado" },
{ "status": "ACCEPTED", "time": "15:02:00", "message": "Chef aceitou o pedido" },
{ "status": "COMPLETED", "time": "15:45:00", "message": "Entregue ao cliente" }
],
"items": [
{ "name": "Pizza Grande", "price": 55.00, "choices": ["Borda Catupiry", "Meio Calabresa", "Meio Mussarela"] }
]
}
Important
O campo
confirmOtp(8 dígitos) é o código que o motoboy deve utilizar para iniciar a confirmação. OcustomerOtp(4 dígitos do cliente) NÃO é retornado via API por questões de segurança.
### 10. Detalhes de um Pedido Individual
**GET** `/api/store/:storeId/orders/:orderId`
Retorna o objeto completo do pedido (parity 100% com o painel).
---
## 💰 Financeiro Detalhado
### 11. Resumo de Performance e Gateway
**GET** `/api/store/:storeId/financial/summary`
**Resposta:**
```json
{
"error": false,
"result": {
"performance": {
"totalSelledAllTime": 150230.50,
"avgTicket": 72.00
},
"gateway": {
"balance": { "balance": 1500.00, "available": 1200.00 },
"transfers": [
{ "id": "TRANS-1", "date": "2024-01-05", "value": 500.00, "status": "DONE" }
]
}
}
}
⭐ Reviews e Avaliações
12. Métricas e Respostas
GET /api/store/:storeId/reviews
Resposta:
{
"error": false,
"result": {
"metrics": {
"averageRate": "4.1",
"totalReviews": 260,
"starsDistribution": { "5": 121, "4": 60, "3": 23, "2": 15, "1": 39 },
"itemFeedback": {
"flavor": 207,
"ingredients": 94,
"packaging": 35,
"temperature": 29,
"appearance": 23
},
"improvementFeedback": {
"quantity": 128,
"temperature": 89,
"packaging": 42,
"ingredients": 23,
"flavor": 13
},
"deliveryFeedback": {
"positive": 102,
"negative": 60
}
},
"list": [
{
"id": "rev_1",
"clientName": "Ana",
"rate": 5,
"message": "Melhor pizza!",
"reply": "Obrigado Ana!",
"repliedAt": "2024-01-08T16:00:00Z"
}
]
}
}
9. Contestar Avaliação
POST /api/store/:storeId/reviews/:reviewId/dispute
{ "reason": "Cliente agressivo e mensagem falsa sobre o produto." }
🖼️ Upload de Ativos e Galeria
POST /api/store/:storeId/assets/upload (Form-data: file) -> Retorna URL absoluta.
GET /api/store/:storeId/assets -> Retorna lista de URLs absolutas de todas as imagens da loja (logo, capa e produtos).
🏷️ Reordenação de Catálogo
POST /api/store/:storeId/catalog/products/reorder (Payload: { "ids": ["p1", "p2", ...] })
POST /api/store/:storeId/catalog/categories/reorder (Payload: { "ids": ["c1", "c2", ...] })
🛵 Fluxo de Entrega Pedi Foods (2-Step OTP)
| Campo | Tipo | Descrição |
|---|---|---|
otp |
String | Legacy OTP (4 digits). |
confirmOtp |
String | Novo: Código de 8 dígitos para o motoboy. (Use este para o fluxo de 2 etapas) |
deliveryEstimate |
String | Tempo estimado de entrega (ex: "30-45 min"). |
pediFoodsFee |
Number | Taxa de serviço Pedi Foods calculada. |
8. Entrega e Confirmação (Motoboy Flow)
Novos endpoints públicos para confirmação de entrega em duas etapas.
8.1. Página de Confirmação
GET /delivery/confirm/:orderId
Renderiza a página para o motoboy iniciar o processo.
8.2. Validar Motoboy (Passo 1)
POST /delivery/confirm/:orderId/validate-motoboy
Valida o código de 8 dígitos (confirmOtp).
Payload:
{ "otp": "12345678" }
8.3. Validar Cliente (Passo 2)
POST /delivery/confirm/:orderId/validate-customer
Valida o código de 4 dígitos (customerOtp) e finaliza o pedido (COMPLETED).
Payload:
{ "otp": "1234" }
Para garantir a segurança da entrega, o sistema utiliza um fluxo de confirmação em duas etapas via página pública:
- URL de Confirmação:
https://atomenta.loverde.com.br/delivery/confirm/:orderRealId - Passo 1 (Motoboy): O entregador insere o
confirmOtp(8 dígitos) visível no painel da loja. - Passo 2 (Cliente): Após validar o código do motoboy, o sistema solicita o
customerOtp(4 dígitos) que o cliente possui em seu app/notificação. - Finalização: A validação bem-sucedida do segundo código altera o status do pedido para
COMPLETEDautomaticamente.
Endpoints utilizados pela página pública (CORS habilitado para domínios parceiros):
POST /delivery/confirm/:orderId/validate-motoboy{ "otp": "String(8)" }POST /delivery/confirm/:orderId/validate-customer{ "otp": "String(4)" }
🛒 Checkout e Criação de Pedido
10.0 Validar Endereço de Entrega (Checkout)
POST /api/store/:storeId/delivery/validate-address
Endpoint para validar cobertura de entrega no checkout, quando o cliente troca o endereço antes do pagamento.
Payload:
{
"address": {
"street": "Avenida das Andorinhas",
"number": "477",
"neighborhood": "Jardim Andorinhas",
"city": "Campinas",
"state": "SP",
"zip": "13101-400",
"lat": -22.918,
"lng": -47.01813
}
}
Resposta Exemplo:
{
"error": false,
"code": "DELIVERY_ADDRESS_VALIDATED",
"result": {
"deliveryAllowed": true,
"reasonCode": "DELIVERY_ALLOWED",
"reasonMessage": "Endereço válido para entrega",
"deliveryMode": "KM",
"distance": 1.3,
"deliveryFee": 8,
"deliveryTime": "35 min",
"sameCity": false,
"matchedKmRange": { "from": 1, "to": 2, "price": 8, "time": 35 },
"matchedNeighborhood": null
}
}
Regras:
KM: aprova somente até o limite da última faixa +0.5 kmde tolerância.NEIGHBORHOOD: reprova se a cidade do endereço for diferente da cidade da loja.NEIGHBORHOOD: aprova com bairro configurado ou com fallback de mesma cidade.
10. Criar Novo Pedido (Public)
POST /api/public/orders
Este endpoint é utilizado pelo front-end de checkout (Pedi Foods) para criar o pedido no sistema da loja.
Payload:
{
"storeId": "store_123456",
"userId": "user_guid_or_guest",
"clientName": "João Silva",
"clientPhone": "11999999999",
"deliveryType": "DELIVERY", // ou "PICKUP"
"address": {
"street": "Rua das Flores",
"number": "123",
"neighborhood": "Centro",
"city": "São Paulo",
"state": "SP",
"zip": "01000-000",
"complement": "Apt 10",
"lat": -23.55,
"lng": -46.63
},
"paymentMethod": "PIX", // "CREDIT_CARD", "DEBIT_CARD", "CASH"
"itemsTotal": 50.00,
"deliveryFee": 5.00,
"serviceFee": 0.00,
"discount": 0.00,
"total": 55.00,
"items": [
{
"id": "prod_1",
"name": "Pizza",
"price": 50.00,
"qty": 1,
"image": "...",
"addons": [
{
"addonId": "addon_bacon",
"name": "Bacon",
"price": 4.00,
"qty": 2
}
]
}
]
}
Regras para items[].addons:
qtydo adicional é suportado (ex.: 2x bacon/ovo).- Se
qtynão for enviado ou vier inválido, a API assume1. qtymínimo efetivo é1.
Resposta Sucesso:
{
"error": false,
"result": {
"id": "order_guid",
"shortId": "1234",
"status": "PAYMENT_PENDING",
"paymentStatus": "PENDING",
"paymentMethod": "PIX",
"paymentPayload": {
"copyPaste": "000201010212...",
"qrCodeImage": "iVBORw0KGgoAAAANSUhEUgAA...",
"expirationDate": "2026-02-14T22:30:00.000Z"
},
"payment": {
"method": "PIX",
"status": "PENDING",
"pix": {
"copyPaste": "000201010212...",
"qrCodeImage": "iVBORw0KGgoAAAANSUhEUgAA...",
"expirationDate": "2026-02-14T22:30:00.000Z"
}
}
}
}
Observação de segurança: o Atomenta não retorna links de checkout/fatura do Asaas no response de criação de pedido.
10.1 Realtime de Status de Pedido (Socket.IO)
Para atualização em tempo real do checkout/app (sem depender de push), usar Socket.IO.
Socket endpoint:
ws://<host>:<port>/socket.io/(usarwss://em produção com TLS)
Auth no handshake:
- Enviar JWT no campo
auth.token. - Exemplo:
Bearer <JWT_TOKEN>.
Evento para o cliente:
order_update
Payload típico do evento:
{
"id": "order_guid",
"shortId": "1234",
"storeId": "store_123456",
"userId": "user_guid",
"status": "CONFIRMED",
"paymentStatus": "CONFIRMED",
"updatedAt": "2026-02-15T20:10:00.000Z"
}
10.2 Fallback de Status (Polling)
Caso não haja conexão socket, consultar status por HTTP até estado final.
Endpoint:
GET /api/public/orders/:orderId
Recomendação de intervalo:
- 0-60s:
3s - 60-180s:
5s - acima de 180s:
10s - parar em status final (
COMPLETED,CANCELED,REFUNDED).
11. Listar Lojas (Public App)
GET /api/public/stores
Endpoint utilizado pelo aplicativo Pedi Foods para listar todas as lojas disponíveis para o cliente.
Resposta Sucesso:
{
"error": false,
"result": [
{
"id": "company_guid",
"storeId": "store_123456",
"name": "Pizzaria do Arantes",
"logo": "https://...",
"cover": "https://...",
"category": "Restaurante",
"isOpen": true,
"statusLabel": "Aberto Agora",
"rating": 4.8,
"deliveryTime": "30-45 min",
"deliveryFee": 5.00
}
]
}
📝 Gestão de Contratos (Store)
12. Verificar Status do Contrato
GET /api/store/:storeId/contract/status
Retorna o ID e o status do contrato mais recente da loja.
Resposta Exemplo:
{
"error": false,
"result": {
"id": "contract_guid",
"status": "draft" // ou "signed"
}
}
13. Assinar Contrato
POST /api/store/:storeId/contract/sign
Assina o contrato draft atual da loja.
Payload:
{
"method": "typed",
"typedName": "João Silva", // Obrigatório se method === "typed"
"signatureDataUrl": "data:image/png;base64,..." // Obrigatório se method === "draw"
}
14. Visualizar PDF do Contrato
GET /api/store/contract/:contractId/pdf
Retorna o stream do arquivo PDF do contrato (draft ou assinado).