Documentação da API
Guia completo para integrar seu sistema de delivery com o iFood através do iHub. Configure webhooks, vincule lojas e gerencie pedidos.
Introdução
O iHub atua como intermediário entre a API do iFood e o seu sistema de delivery. Após configurar seu webhook no painel, o iHub cuida de todo o polling, autenticação e reenvio — seu sistema só precisa receber requisições POST.
O fluxo funciona assim:
- Você registra sua conta e assina o plano.
- No painel, configura o domínio e a URL de webhook do seu sistema.
- Inicia o processo de vinculação de uma loja iFood (merchant) via API.
- A partir daí, o iHub envia todos os pedidos e eventos diretamente para seu webhook.
- Use o módulo Merchant para consultar status da loja, pausas, horários e demais operações da API de lojas do iFood.
Base URL
Todas as requisições à API devem usar o prefixo:
https://ihub.arcn.com.br/api
Autenticação
Todas as rotas protegidas exigem o header Authorization: Bearer {token}.
Chamadas do seu sistema para o iHub
Use o token secreto (UUID) exibido no painel após salvar as configurações. Esse token identifica seu cadastro na tabela de clientes.
- Envie:
Authorization: Bearer {seu_secret_token} - Nos endpoints que enviam
domainno JSON (ex.: vincular merchant, ações em pedido), o valor deve ser o mesmo domínio cadastrado no painel — caso contrário o iHub retorna403. - Nas rotas
GETde pedidos e em todo o módulo Merchant (/api/merchants/...), o domínio é obtido automaticamente a partir do token — não é necessário enviá-lo na URL ou no corpo.
Webhooks do iHub para o seu sistema
Na direção oposta (iHub → sua URL de webhook), o iHub envia o mesmo valor no header X-iFood-Hub-Signature para você validar a origem da requisição.
$hubSignature = $request->header('X-iFood-Hub-Signature');
// Compare com o token secreto que você armazenou (mesmo valor do painel)
if ($hubSignature !== $seuTokenArmazenadoComSeguranca) {
return response()->json(['message' => 'Unauthorized'], 401);
}
Ambiente sandbox
O sandbox existe para você integrar o sistema de delivery antes de autorizar uma loja real no iFood. Com o modo ativo, as rotas de produção (pedidos, merchant, shipping, reviews, analytics, OAuth) devolvem dados virtuais persistidos na sua conta — nenhuma chamada vai para a API do iFood.
Ative no painel (aba Sandbox) ou via POST /api/sandbox/bootstrap. A loja virtual ganha um merchant_id estável. O módulo Catalog não é simulado (é o fluxo mais complexo da API real).
Fluxo recomendado
- Cadastre domínio, webhook e copie o token secreto.
- Ative o sandbox no painel (cria a loja virtual automaticamente).
- Crie um pedido:
POST /api/sandbox/orders— o iHub enviaPLCcomorder_detailspara o seu webhook. - No seu sistema, confirme com
POST /api/ifood/action(action=confirm). O sandbox avança o status e disparaCFM. - Siga o ciclo:
startPreparation→readyToPickup→dispatch. Códigos de teste: retirada8472, entrega5482, drop3321.
Rotas de controle do sandbox
Todas exigem Authorization: Bearer {secret_token}.
| Método | Rota | Descrição |
|---|---|---|
POST | /api/sandbox/bootstrap | Ativa o modo e cria a loja virtual. |
GET | /api/sandbox | Estado atual: loja, pedidos, reviews, eventos disponíveis. |
POST | /api/sandbox/orders | Cria um pedido (scenario opcional) e dispara PLC. |
POST | /api/sandbox/trigger-event | Dispara um evento (code, order_id opcional). |
POST | /api/sandbox/reset | Limpa pedidos e estado simulado. Mantém a loja. |
curl -X POST https://ihub.arcn.com.br/api/sandbox/orders \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"scenario":"delivery_ifood"}'
Cenários de pedido
| scenario | O que simula |
|---|---|
delivery_ifood | Entrega pela frota iFood, pago online (padrão). |
delivery_merchant | Entrega própria, com pickupCode. |
takeout | Retirada no balcão. |
indoor | Consumo no local (mesa). |
scheduled | Pedido agendado. |
cash | Pagamento em dinheiro na entrega. |
handshake | Pedido com disputa de reembolso aberta. |
shipping_easy | Use também POST /api/shipping/{id}/orders para Easy Delivery. |
Eventos extras que você pode disparar: HSA (disputa), ADR (entregador), DDCR (código de entrega), DACR/DACA/DACD (troca de endereço), além do ciclo PLC → CFM → PSP → RTP → DSP → CON/CAN.
Gerar User Code
Primeiro passo para vincular uma loja iFood. Gera um código que o lojista deve inserir na página de vinculação do iFood.
Exemplo de requisição
curl -X POST https://ihub.arcn.com.br/api/auth/generate-user-code \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"userCode": "ABCD-EFGH",
"authorizationCodeVerifier": "um-codigo-verificador-longo",
"verificationUrl": "https://portal.ifood.com.br/...",
"verificationUrlComplete": "https://portal.ifood.com.br/...?code=ABCD-EFGH"
}
userCode ou redirecione o lojista para verificationUrlComplete. Após o lojista autorizar no portal do iFood, use authorizationCodeVerifier na próxima etapa.
Vincular Merchant
Após o lojista autorizar o acesso no portal do iFood, envie os dados de autorização para vincular a loja ao seu sistema.
Parâmetros
| Campo | Tipo | Descrição |
|---|---|---|
| domain | string | Domínio do seu sistema cadastrado no painel. |
| authorizationCode | string | Código de autorização retornado pelo iFood após o lojista aprovar. |
| authorizationCodeVerifier | string | Verificador obtido na etapa anterior (generate-user-code). |
| merchantId | string (UUID) · opcional | UUID da loja a vincular. Obrigatório quando o token OAuth inclui mais de uma loja ainda não vinculada. Se omitido, o iHub infere a loja pelo merchant_scope do JWT (loja nova em relação às já vinculadas). |
Exemplo de requisição
curl -X POST https://ihub.arcn.com.br/api/auth/link-merchant \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"domain": "app.meudelivery.com.br",
"authorizationCode": "codigo-do-ifood",
"authorizationCodeVerifier": "verificador-da-etapa-1"
}'
Resposta de sucesso
{
"message": "Merchant linked successfully",
"merchant": {
"id": 1,
"client_id": 5,
"merchant_id": "abcd-1234-efgh-5678",
"access_token": "...",
"refresh_token": "...",
"expires_at": "2026-04-15T00:00:00.000000Z"
},
"ifood_details": {
"id": "abcd-1234-efgh-5678",
"name": "Restaurante Exemplo",
"corporateName": "..."
}
}
Vincular todas as lojas do token
Quando o lojista autoriza acesso a várias lojas de uma vez (ou o token OAuth já inclui múltiplos merchants), use este endpoint para vincular todas as lojas presentes no merchant_scope do JWT — em uma única chamada.
Parâmetros
| Campo | Tipo | Descrição |
|---|---|---|
| domain | string | Domínio do seu sistema cadastrado no painel. |
| authorizationCode | string | Código de autorização retornado pelo iFood. |
| authorizationCodeVerifier | string | Verificador obtido em generate-user-code. |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/auth/link-all-merchants \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"domain": "app.meudelivery.com.br",
"authorizationCode": "codigo-do-ifood",
"authorizationCodeVerifier": "verificador-da-etapa-1"
}'
Resposta de sucesso
{
"message": "Merchants linked successfully",
"linked": ["uuid-loja-2", "uuid-loja-3"],
"updated": ["uuid-loja-1"],
"merchant_ids_in_token": ["uuid-loja-1", "uuid-loja-2", "uuid-loja-3"],
"merchants": [
{ "id": 10, "merchant_id": "uuid-loja-1", "expires_at": "2026-09-30T05:00:00+00:00" },
{ "id": 11, "merchant_id": "uuid-loja-2", "expires_at": "2026-09-30T05:00:00+00:00" }
]
}
updated (tokens renovados); novas entram em linked.
Recebendo Webhooks
Após vincular um merchant, o iHub envia automaticamente todos os eventos de pedidos para a URL de webhook configurada no seu painel via POST.
Headers enviados
| Header | Descrição |
|---|---|
| Content-Type | application/json |
| Accept | application/json |
| X-iFood-Hub-Signature | Seu token secreto (compare para validar autenticidade). |
HTTP 2xx para confirmar o recebimento. Caso contrário, o evento será marcado como falha.
Payload dos Webhooks
O corpo de cada webhook segue a estrutura de eventos do iFood:
| Campo | Tipo | Descrição |
|---|---|---|
| id | string | ID único do evento. |
| code | string | Código resumido do evento (ex.: PLC, CFM, CAN). |
| fullCode | string | Código completo (ex.: PLACED, CONFIRMED). |
| orderId | string | ID do pedido no iFood. |
| merchantId | string | ID da loja (merchant) no iFood. |
| createdAt | string | Timestamp ISO 8601 do evento. |
Pedido Novo (PLC)
Quando um novo pedido é criado (code: PLC), o iHub automaticamente busca os detalhes completos do pedido na API do iFood e os inclui no campo order_details — assim seu sistema não precisa fazer uma segunda requisição.
{
"id": "evt-abc-123",
"code": "PLC",
"fullCode": "PLACED",
"orderId": "order-xyz-789",
"merchantId": "merchant-aaa-111",
"createdAt": "2026-04-14T22:30:00Z",
"order_details": {
"id": "order-xyz-789",
"type": "DELIVERY",
"displayId": "1234",
"orderType": "DELIVERY",
"customer": {
"name": "João da Silva",
"phone": { "number": "11999999999" }
},
"deliveryAddress": {
"streetName": "Rua Exemplo",
"streetNumber": "100",
"neighborhood": "Centro",
"city": "São Paulo",
"state": "SP",
"postalCode": "01000-000",
"complement": "Apto 42",
"reference": "Próximo ao mercado"
},
"items": [
{
"id": "item-001",
"name": "X-Burger",
"quantity": 2,
"unitPrice": 25.90,
"totalPrice": 51.80,
"subItems": [],
"observations": "Sem cebola"
}
],
"payments": {
"methods": [
{ "method": "CREDIT", "type": "ONLINE", "value": 51.80 }
]
},
"total": {
"subTotal": 51.80,
"deliveryFee": 5.00,
"benefits": 0,
"orderAmount": 56.80
}
}
}
Eventos de Status
Eventos subsequentes (confirmação, despacho, cancelamento, etc.) seguem a mesma estrutura, sem o campo order_details:
| Código | fullCode | Descrição |
|---|---|---|
| PLC | PLACED | Novo pedido criado. |
| CFM | CONFIRMED | Pedido confirmado pelo restaurante. |
| PSP | PREPARATION_STARTED | Preparo iniciado. |
| DSP | DISPATCHED | Pedido despachado. |
| RTP | READY_TO_PICKUP | Pronto para retirada. |
| CAN | CANCELLED | Pedido cancelado. |
| CON | CONCLUDED | Pedido concluído. |
{
"id": "evt-abc-456",
"code": "CFM",
"fullCode": "CONFIRMED",
"orderId": "order-xyz-789",
"merchantId": "merchant-aaa-111",
"createdAt": "2026-04-14T22:32:00Z"
}
Executar Ação em Pedido
Use esta rota para confirmar, despachar, cancelar ou gerenciar pedidos no iFood.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| domain | string | Sim | Domínio do seu sistema. |
| merchantId | string | Sim | ID do merchant no iFood. |
| orderId | string | Sim | ID do pedido. |
| action | string | Sim | Ação a executar (ver tabela abaixo). |
| cancelCode | string | Se cancel | Código do motivo de cancelamento. |
| cancelReason | string | Se cancel | Descrição do motivo. |
Ações disponíveis
| Ação | Descrição |
|---|---|
| confirm | Confirma o recebimento do pedido. |
| startPreparation | Marca o início do preparo. |
| readyToPickup | Marca como pronto para retirada. |
| dispatch | Despacha o pedido para entrega. |
| cancel | Cancela o pedido (requer cancelCode e cancelReason). |
Exemplo — Confirmar pedido
curl -X POST https://ihub.arcn.com.br/api/ifood/action \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"domain": "app.meudelivery.com.br",
"merchantId": "abcd-1234-efgh-5678",
"orderId": "order-xyz-789",
"action": "confirm"
}'
Exemplo — Cancelar pedido
curl -X POST https://ihub.arcn.com.br/api/ifood/action \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"domain": "app.meudelivery.com.br",
"merchantId": "abcd-1234-efgh-5678",
"orderId": "order-xyz-789",
"action": "cancel",
"cancelCode": "501",
"cancelReason": "Falta de ingredientes"
}'
Resposta de sucesso
{
"success": true,
"message": "Order confirmed successfully"
}
Detalhes do Pedido
Busca os dados completos de um pedido diretamente na API do iFood. O cadastro é identificado pelo Authorization: Bearer; não é necessário informar o domínio na URL.
Exemplo
curl https://ihub.arcn.com.br/api/orders/abcd-1234-efgh-5678/order-xyz-789 \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Retorna o JSON completo com dados do pedido (itens, cliente, endereço, pagamento).
Motivos de Cancelamento
Obtém a lista de motivos de cancelamento válidos para um pedido. O domínio é inferido do token.
Exemplo
curl https://ihub.arcn.com.br/api/orders/abcd-1234-efgh-5678/order-xyz-789/cancellation-reasons \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Retorna um array de objetos com cancelCodeId e description. Use o código na ação cancel.
Validar Código de Retirada
Valida o código de retirada apresentado pelo entregador no momento da coleta do pedido. Utilizado em pedidos com entrega própria (self-delivery) onde o entregador precisa confirmar a retirada.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| domain | string | Sim | Domínio do seu sistema cadastrado no painel. |
| merchantId | string | Sim | ID do merchant no iFood. |
| orderId | string | Sim | ID do pedido no iFood. |
| code | string | Sim | Código de retirada apresentado pelo entregador. |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/orders/validate-pickup-code \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"domain": "app.meudelivery.com.br",
"merchantId": "abcd-1234-efgh-5678",
"orderId": "order-xyz-789",
"code": "9999"
}'
Resposta de sucesso
{
"success": true
}
Códigos de erro
| Status | Descrição |
|---|---|
| 400 | Tipo de validação incorreto para este pedido. |
| 404 | Pedido não encontrado ou endpoint indisponível (entrega iFood + recurso habilitado). Entrega própria valida localmente via pickupCode. |
| 412 | Status de handshake inválido — o pedido deve ter sido aceito pelo entregador antes da validação. |
Verificar Código de Entrega
Verifica o código de confirmação de entrega apresentado pelo destinatário no momento da entrega do pedido.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| domain | string | Sim | Domínio do seu sistema cadastrado no painel. |
| merchantId | string | Sim | ID do merchant no iFood. |
| orderId | string | Sim | ID do pedido no iFood. |
| code | string | Sim | Código de entrega apresentado pelo destinatário. |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/orders/verify-delivery-code \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"domain": "app.meudelivery.com.br",
"merchantId": "abcd-1234-efgh-5678",
"orderId": "order-xyz-789",
"code": "9999"
}'
Resposta de sucesso
{
"success": true
}
Códigos de erro
| Status | Descrição |
|---|---|
| 400 | Código de confirmação inválido (não confundir com código de retirada). |
| 404 | Pedido não encontrado. Entrega própria: compare com customer.phone.localizer. |
Módulo Merchant (Loja)
Endpoints para consultar e gerenciar lojas vinculadas ao iFood: listagem, detalhes, status operacional, pausas (interrupções), horários de funcionamento e QR code de check-in (Grocery).
Todas as rotas exigem Authorization: Bearer SEU_TOKEN_SECRETO. O {merchant_id} na URL deve ser o UUID da loja já vinculada ao seu cadastro no iHub (via Vincular Merchant).
404 (loja não vinculada), 401 (token iFood expirado), 403 (sem permissão), 429 (rate limit — respeite o header Retry-After).
Listar lojas
Lista todas as lojas associadas ao token OAuth do merchant informado (paginação opcional).
Query (opcional)
| Campo | Tipo | Descrição |
|---|---|---|
| page | integer | Página (mín. 1). |
| size | integer | Itens por página (máx. 100). |
Exemplo
curl "https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/list?page=1&size=50" \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Detalhes da loja
Retorna informações completas de uma loja específica (nome, endereço, categorias, etc.).
Exemplo
curl https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678 \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Status da loja
Consulta o status operacional geral da loja (aberta, fechada, pausada, etc.).
Exemplo
curl https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/status \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Status por operação
Status filtrado por tipo de operação da loja.
Parâmetros de URL
| Campo | Valores | Descrição |
|---|---|---|
| operation | DELIVERY, TAKEOUT, INDOOR | Tipo de operação (maiúsculas). |
Exemplo
curl https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/status/DELIVERY \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Erros
| Status | Descrição |
|---|---|
| 400 | operation inválida (use DELIVERY, TAKEOUT ou INDOOR). |
Listar pausas (interrupções)
Lista interrupções temporárias ativas da loja (pausas programadas ou em andamento).
Exemplo
curl https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/interruptions \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Criar pausa
Cria uma interrupção temporária de operação (ex.: pausa para manutenção ou falta de equipe).
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| description | string | Sim | Motivo da pausa (máx. 255 caracteres). |
| start | date | Sim | Início da pausa (ISO 8601). |
| end | date | Sim | Fim da pausa (deve ser posterior a start). |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/interruptions \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"description": "Pausa para manutenção",
"start": "2026-05-20T14:00:00Z",
"end": "2026-05-20T16:00:00Z"
}'
Resposta de sucesso
Status 201 Created com o objeto da interrupção criada (inclui id para remoção posterior).
Erros
| Status | Descrição |
|---|---|
| 409 | Sobreposição com outra interrupção já existente. |
Remover pausa
Remove uma interrupção ativa pelo ID retornado na criação ou listagem.
Exemplo
curl -X DELETE https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/interruptions/interruption-uuid-aqui \ -H "Authorization: Bearer SEU_TOKEN_SECRETO"
Resposta de sucesso
Status 204 No Content (corpo vazio).
Horários de funcionamento
Consulta os turnos de funcionamento cadastrados no iFood para a loja.
Exemplo
curl https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/opening-hours \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Atualizar horários
Substitui todos os turnos de funcionamento da loja. Dias da semana não enviados no array shifts ficam fechados.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| storeId | uuid | Sim | ID da loja no iFood (obtido em detalhes da loja). |
| shifts | array | Sim | Lista de turnos (mín. 1). |
| shifts[].dayOfWeek | string | Sim | MONDAY … SUNDAY |
| shifts[].start | string | Sim | Horário de abertura (H:i:s, ex.: 08:00:00). |
| shifts[].duration | integer | Sim | Duração do turno em minutos. |
Exemplo
curl -X PUT https://ihub.arcn.com.br/api/merchants/abcd-1234-efgh-5678/opening-hours \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"storeId": "c54bb20a-bce0-4e38-bd4a-fe5f0a7b6b5a",
"shifts": [
{
"dayOfWeek": "MONDAY",
"start": "08:00:00",
"duration": 720
},
{
"dayOfWeek": "TUESDAY",
"start": "08:00:00",
"duration": 720
}
]
}'
Resposta de sucesso
Status 201 Created com os turnos criados/atualizados.
Erros
| Status | Descrição |
|---|---|
| 400 | Validação (turnos sobrepostos, formato inválido, etc.). |
| 409 | Conflito na atualização. |
QR Code de check-in
Gera um PDF com QR codes de check-in para entregadores. Destinado a lojas do tipo Grocery. Aceita de 1 a 20 lojas por requisição.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| merchantIds | uuid[] | Sim | IDs das lojas (1 a 20). O token é resolvido pela primeira loja da lista. |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/merchants/checkin-qrcode \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"merchantIds": [
"abcd-1234-efgh-5678",
"9876-5432-1111-2222-333344445555"
]
}' \
--output checkin-qrcode.pdf
Resposta de sucesso
Status 200 com corpo binário application/pdf (arquivo para download/impressão).
Módulo Shipping (Entrega)
Use este módulo para pedir um entregador do iFood (Easy Delivery) para um pedido feito fora da plataforma iFood — WhatsApp, telefone, PDV, aplicativo próprio, etc. É indicado para lojas com frota própria que precisam de reforço em picos de demanda.
POST /api/ifood/action com action: "cancel" aqui, os motivos/códigos são diferentes.
Todas as rotas exigem Authorization: Bearer SEU_TOKEN_SECRETO. O {merchant_id} na URL deve ser o UUID da loja já vinculada ao seu cadastro no iHub (via Vincular Merchant).
developer.ifood.com.br/pt-BR/docs/food/guides/modules/shipping/intro) e testes reais em produção — não são mais estimativa.
Disponibilidade de entrega
Consulta se há cobertura de entrega para um endereço (área atendida, frota disponível) antes de registrar o pedido. Passo obrigatório — o id retornado aqui é o quoteId exigido no passo seguinte, e a cotação expira (expirationAt).
Query
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| latitude | number | Sim | Latitude do endereço de entrega. |
| longitude | number | Sim | Longitude do endereço de entrega. |
Exemplo
curl "https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/delivery-availability?latitude=-23.55052&longitude=-46.633308" \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"quote": { "grossValue": 12.90, "discount": 0, "netValue": 12.90 },
"deliveryTime": { "min": 20, "max": 40 },
"distance": 1850,
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"expirationAt": "2026-08-27T19:07:34.723Z",
"createdAt": "2026-08-27T19:07:34.723Z",
"hasPaymentMethods": true,
"paymentMethods": [
{ "id": "...", "brand": "string", "liability": "string", "paymentType": "string", "method": "string" }
]
}
Guarde o id (é o quoteId) e o quote.netValue — ambos são usados no passo de solicitar o entregador, abaixo.
Erros
| Status | Descrição |
|---|---|
| 400 | Endereço fora da área de cobertura ou sem entregador parceiro disponível no momento (ex.: code: "DeliveryDistanceTooHigh" — pode ocorrer mesmo com distância real pequena, se a loja não tiver cobertura de parceiros habilitada na região). |
| 404 | Merchant não vinculado ao seu cadastro no iHub. |
Solicitar entregador
Registra no iFood um pedido feito fora da plataforma e solicita a alocação automática de um entregador, a partir de uma cotação obtida em Disponibilidade de entrega. Em caso de sucesso, o iFood retorna o id do pedido gerado e uma trackingUrl para o cliente acompanhar a entrega.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| customer.name | string | Sim | Nome do cliente que vai receber o pedido. |
| customer.phone | object | Sim | countryCode, areaCode e number — todos exigidos separadamente pelo iFood. |
| delivery.quoteId | string | Recomendado | O id retornado pela consulta de disponibilidade. |
| delivery.merchantFee | number | Recomendado | Valor da entrega — use o quote.netValue retornado na disponibilidade. |
| delivery.deliveryAddress | object | Sim | postalCode, streetNumber, streetName, complement, neighborhood, city, state, country, reference. |
| delivery.deliveryAddress.coordinates | object | Sim | { "latitude": 0, "longitude": 0 } — objeto aninhado, não campos soltos. |
| items | array | Sim | Cada item exige id (UUID válido — gere um sintético se não tiver um real), name, quantity, unitPrice, price, optionsPrice, totalPrice (decimais em reais, não centavos). |
| payments | object | Não, se já pago | Omita o campo inteiro se o pedido já foi pago no seu sistema (o iFood não deve processar pagamento). Se pendente: { "methods": [{ "method": "CASH"|"CREDIT"|"DEBIT", "type": "OFFLINE", "value": 0, "cash": {"changeFor": 0} }] } — cash.changeFor é obrigatório para CASH, card.brand é obrigatório para CREDIT/DEBIT. |
| displayId | string | Não | Código do pedido no seu sistema, exibido pro entregador. Máximo 4 caracteres. |
Exemplo de requisição
curl -X POST https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"name": "João da Silva",
"phone": { "countryCode": "55", "areaCode": "11", "number": "999999999" }
},
"delivery": {
"quoteId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"merchantFee": 12.90,
"deliveryAddress": {
"postalCode": "01000-000",
"streetNumber": "100",
"streetName": "Rua Exemplo",
"complement": "Apto 42",
"neighborhood": "Centro",
"city": "São Paulo",
"state": "SP",
"country": "BR",
"reference": "Próximo ao mercado",
"coordinates": { "latitude": -23.55052, "longitude": -46.633308 }
}
},
"items": [
{ "id": "1", "name": "X-Burger", "quantity": 2, "unitPrice": 25.90, "price": 51.80, "optionsPrice": 0, "totalPrice": 51.80 }
],
"payments": {
"methods": [
{ "method": "CASH", "type": "OFFLINE", "value": 51.80 }
]
},
"displayId": "1234"
}'
Resposta de sucesso
{
"id": "order-uuid-gerado-pelo-ifood",
"trackingUrl": "https://tracking.ifood.com.br/order-uuid-gerado-pelo-ifood"
}
Guarde o id retornado — ele é o mesmo orderId que vai aparecer nos eventos enviados ao seu webhook (Eventos de Status) e que deve ser usado em ações de pedido (cancelamento, etc.).
Erros
| Status | Descrição |
|---|---|
| 400 | Entrega não viável (endereço fora de cobertura, sem entregador disponível, etc.). |
| 404 | Merchant não vinculado ao seu cadastro no iHub. |
| 401 | Token OAuth do merchant expirado/inválido. |
Cancelamento
Cancelamento de pedidos do módulo Shipping é em duas etapas: consultar os motivos válidos e enviar o cancelamento com o código escolhido. Não use a ação cancel de POST /api/ifood/action para pedidos registrados via Shipping — os motivos/códigos são diferentes dos do módulo Order.
Exemplo
curl https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-xyz-789/cancellation-reasons \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
[
{ "cancelCodeId": "817", "description": "O cliente cancelou o pedido" },
{ "cancelCodeId": "818", "description": "Impossível preparar o pedido" }
]
Status 204 (corpo vazio) significa que o pedido não pode mais ser cancelado (já entregue, já cancelado, etc.).
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| reason | string | Sim | Texto explicativo (para logs). |
| cancellationCode | string | Sim | O cancelCodeId obtido em cancellation-reasons (ex.: "817"). String — a doc oficial do iFood diz "integer", mas o erro real da API confirma que é string (expected=string, got=number). |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-xyz-789/cancel \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"reason": "Cliente solicitou cancelamento via chat",
"cancellationCode": "817"
}'
Resposta de sucesso
{ "success": true }
O cancelamento é assíncrono — acompanhe pelo webhook (CANCELLATION_REQUESTED → CANCELLED, ou CANCELLATION_REQUEST_FAILED se der errado, ex.: entregador já saiu pra entrega).
Safe Delivery Score
Nível de confiança calculado automaticamente pelo iFood para cada entrega, com base em validação de telefone e confirmação de endereço do cliente.
Exemplo
curl https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-xyz-789/safe-delivery \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"score": "VERY_HIGH",
"rules": {
"customer_phone_valid": true,
"customer_phone_is_fixed": false,
"customer_address_confirmed": true,
"customer_address_change_requested": false,
"merchant_address_change_approved": false,
"merchant_address_change_denied": false
}
}
score: LOW, MODERATE, HIGH ou VERY_HIGH. Consulte perto do horário de entrega, não só na criação — o score muda conforme o cliente confirma/altera o endereço.
Troca de endereço
Quando o cliente solicita mudar o endereço de entrega pela página de rastreamento do iFood (trackingUrl), você recebe o evento DELIVERY_ADDRESS_CHANGE_REQUESTED no seu webhook. Use estas rotas para aceitar ou recusar (máximo ~15 minutos para responder — depois disso o iFood recusa automaticamente).
curl -X POST https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-xyz-789/accept-address-change \ -H "Authorization: Bearer SEU_TOKEN_SECRETO"
Gera o evento DELIVERY_ADDRESS_CHANGE_ACCEPTED. Se o novo endereço cair em outra região de cobertura, o iFood nega automaticamente com DELIVERY_ADDRESS_CHANGE_DENIED (metadata.action = "region-mismatch").
curl -X POST https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-xyz-789/deny-address-change \ -H "Authorization: Bearer SEU_TOKEN_SECRETO"
Gera o evento DELIVERY_ADDRESS_CHANGE_DENIED.
DELIVERY_ADDRESS_CHANGE_REQUESTED no webhook. O iHub repassa o evento como recebido, sem transformação — trate o payload de forma defensiva no seu sistema até confirmar o formato exato em produção.
Loja propõe uma correção de endereço
Direção oposta da anterior: a loja propõe um novo endereço (ex.: o capturado estava errado/incompleto) — diferente de aceitar/recusar uma solicitação do cliente. O cliente recebe a proposta na página de rastreamento do iFood e tem até ~15 minutos para confirmar.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| streetName / streetNumber / complement / neighborhood / city / state / country / reference | string | Não | Campos do novo endereço proposto. |
| coordinates | object | Sim | { "latitude": 0, "longitude": 0 } — coordenadas do novo endereço. |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-xyz-789/request-address-change \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"streetName": "Rua Corrigida",
"streetNumber": "42",
"neighborhood": "Centro",
"city": "São Paulo",
"state": "SP",
"country": "BR",
"coordinates": { "latitude": -23.55052, "longitude": -46.633308 }
}'
Acompanhe a resolução pelos mesmos eventos de webhook: DELIVERY_ADDRESS_CHANGE_ACCEPTED, DELIVERY_ADDRESS_CHANGE_DENIED ou DELIVERY_ADDRESS_CHANGE_USER_CONFIRMED.
Pedido nativo do iFood (entrega própria + suporte da frota)
Cenário diferente do restante deste módulo: aqui o pedido já existe nativamente no iFood (chegou pelo seu webhook normal, como qualquer pedido do módulo Order) e a loja usa entrega própria como modelo padrão de logística — mas quer, pontualmente, pedir um entregador da frota do iFood como reforço. O pedido não é criado por essas rotas (ele já existe) — só a solicitação/cancelamento do entregador passa por aqui.
orderId (já nativo) e, na solicitação, o quoteId.
Mesma resposta da disponibilidade por merchant (quote, deliveryTime, distance, id = quoteId, expirationAt), mas sem query params — o iFood já sabe o endereço porque o pedido já existe no lado dele.
curl https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-nativo-789/delivery-availability \ -H "Authorization: Bearer SEU_TOKEN_SECRETO"
Solicitar entregador (pedido nativo)
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| quoteId | string | Sim | O id retornado pela disponibilidade acima. |
curl -X POST https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-nativo-789/request-driver \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{ "quoteId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }'
Resposta 202 Accepted, sem corpo (diferente do fluxo fora da plataforma, que retorna trackingUrl — pedidos nativos já têm rastreamento nativo no app do iFood pro cliente).
Cancelar solicitação de entregador (pedido nativo)
Cancela só a solicitação de entregador — o pedido em si continua existindo no iFood. Sem corpo na requisição. Não use POST .../cancel (a rota da seção Cancelamento) aqui: ela é exclusiva do fluxo fora da plataforma e retorna erro RequestCancelSalesChannelInvalid se usada num pedido nativo.
curl -X POST https://ihub.arcn.com.br/api/shipping/abcd-1234-efgh-5678/orders/order-nativo-789/cancel-request-driver \ -H "Authorization: Bearer SEU_TOKEN_SECRETO"
Resposta de sucesso
{ "success": true }
Nas requisições POST /api/ifood/action abaixo, envie sempre Authorization: Bearer SEU_TOKEN_SECRETO (igual às demais rotas).
Aceitar Disputa
Aceita uma disputa aberta pelo cliente no iFood.
{
"domain": "app.meudelivery.com.br",
"merchantId": "abcd-1234-efgh-5678",
"orderId": "order-xyz-789",
"action": "acceptDispute",
"disputeId": "dispute-id-aqui",
"reason": "Concordo com o cliente",
"detailReason": "Produto realmente estava errado"
}
Rejeitar Disputa
Rejeita uma disputa. disputeId e reason são obrigatórios.
{
"domain": "app.meudelivery.com.br",
"merchantId": "abcd-1234-efgh-5678",
"orderId": "order-xyz-789",
"action": "rejectDispute",
"disputeId": "dispute-id-aqui",
"reason": "Pedido foi entregue corretamente"
}
Propor Reembolso
Propõe um reembolso parcial em uma disputa. disputeId, alternativeId e refundAmount são obrigatórios.
{
"domain": "app.meudelivery.com.br",
"merchantId": "abcd-1234-efgh-5678",
"orderId": "order-xyz-789",
"action": "proposeRefund",
"disputeId": "dispute-id-aqui",
"alternativeId": "alternative-id",
"refundAmount": "15.50"
}
Módulo Analytics (KPIs)
Consulta agregada de indicadores de performance de pedidos por loja — GMV, ticket médio, distribuição por canal de venda, status, forma de pagamento e modelo logístico. Não retorna dados de pedidos individuais, só métricas agregadas sobre um período.
metrics, terms, groupBy, dateIntervals) — pelo menos um é obrigatório. Recomendamos groupBy (combinado com metrics) em vez de terms: no ambiente de homologação (x-request-homologation: true), o iFood sempre retorna um payload fixo de teste no formato groupBy, então usar esse formato garante que sua consulta funcione igual em teste e produção.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| filter.referenceDate | object | Sim | { "gte": "2026-01-01 00:00:00", "lte": "2026-01-31 23:59:59" } — período consultado, baseado na data de criação do pedido. |
| filter.orderStatus / salesChannels / deliveredBy / categories | array | Não | Filtros adicionais (ex.: ["CONCLUDED"]). |
| agg.metrics | object | Ao menos um de agg.* | Métricas numéricas: { "gmv": ["sum"], "gmvWithoutDelivery": ["sum"] } — funções aceitas: sum, avg, min, max. |
| agg.groupBy.fields | array | Ao menos um de agg.* | Campos pra quebrar o resultado em linhas: orderStatus, salesChannel, paymentMethod, deliveredBy, dayOfWeek, category, orderCreationHour, etc. |
| agg.terms | object | Ao menos um de agg.* | Contagem por valor de campo: { "orderStatus": ["count"] } — produz um único objeto agregado (sem quebra em linhas). Ver aviso acima sobre homologação. |
| page | integer | Sim | 1 a 1000. |
| size | integer | Sim | 1 a 10000. |
| sort.groupByKey | string | Não | asc ou desc — só tem efeito com agg.groupBy. |
Exemplo de requisição
curl -X POST https://ihub.arcn.com.br/api/analytics/abcd-1234-efgh-5678/orders/kpis \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"filter": {
"referenceDate": { "gte": "2026-01-01 00:00:00", "lte": "2026-01-31 23:59:59" }
},
"agg": {
"metrics": { "gmv": ["sum"], "gmvWithoutDelivery": ["sum"] },
"groupBy": { "fields": ["orderStatus", "salesChannel", "paymentMethod", "deliveredBy"] }
},
"page": 1,
"size": 100
}'
Resposta de sucesso
{
"currentPage": 1,
"size": 100,
"totalItems": 12,
"totalPages": 1,
"data": [
{
"groupByKey": {
"value": { "orderStatus": "CONCLUDED", "salesChannel": "IFOOD", "paymentMethod": "PIX", "deliveredBy": "MERCHANT_DELIVERY" },
"count": 159
},
"gmv": { "sum": 15230.93 },
"gmvWithoutDelivery": { "sum": 15210.95 }
}
],
"_meta": {
"queriedAt": "2026-09-10T14:32:07+00:00",
"clientId": "b685a0d6-...",
"homologation": false
}
}
Cada linha de data é uma combinação única dos campos de groupBy, com count (quantidade de pedidos naquela combinação) e as métricas agregadas daquela combinação. Some as linhas que te interessam pra chegar num total (ex.: GMV total = soma de gmv.sum de todas as linhas; pedidos concluídos = soma de count onde orderStatus == "CONCLUDED"). O campo _meta é acrescentado pelo iHub (não existe no schema do iFood) — útil pra exibir data/hora da consulta e o client_id do app na sua própria UI.
Homologação
Envie o header X-Request-Homologation: true pra consultar o ambiente de teste do iFood — a resposta vem num formato fixo (sempre groupBy por dayOfWeek/orderStatus/deliveredBy/paymentMethod/salesChannel), útil pra validar sua integração sem depender de dados reais. Nesse modo, o iHub não usa o cache de 30 minutos descrito abaixo — cada chamada é sempre fresca.
Erros
| Status | Descrição |
|---|---|
| 400 | Validação falhou — filter.referenceDate ausente, nenhuma agregação em agg, ou campo/função inválidos. |
| 404 | Merchant não vinculado ao seu cadastro no iHub, ou token OAuth expirado/inválido. |
| 429 | Limite de 500 requisições/minuto do iFood excedido. O iHub já tenta novamente automaticamente em erros transitórios (5xx/429 com espera curta). |
| 500 | Erro interno do iFood. |
Módulo Review (Avaliações)
Consulta e resposta das avaliações que os clientes deixam depois de um pedido — nota de 1 a 5, comentário, pesquisa de satisfação estruturada e o pedido vinculado. A loja só lê e responde; quem avalia é sempre o cliente.
Todas as rotas exigem Authorization: Bearer SEU_TOKEN_SECRETO. O {merchantId} na URL deve ser o UUID da loja já vinculada ao seu cadastro no iHub (via Vincular Merchant).
Listar avaliações
Lista as avaliações da loja, paginado, com filtro opcional por período e por pedido.
Query string
| Campo | Tipo | Descrição |
|---|---|---|
| page | integer | Página (padrão 1). |
| pageSize | integer | Itens por página — máximo real 50. Acima disso o iFood responde 400 (o iHub não impõe um limite mais baixo, pra deixar esse erro real passar). |
| dateFrom / dateTo | string | Filtro por período de criação da avaliação (ISO 8601, ex.: 2026-09-01T00:00:00Z). |
| orderId | string | Filtra pela avaliação de um pedido específico. |
| customerName | string | Filtra pelo nome do cliente. |
Exemplo
curl "https://ihub.arcn.com.br/api/review/abcd-1234-efgh-5678/reviews?page=1&pageSize=10&dateFrom=2026-09-01T00:00:00Z&dateTo=2026-09-30T23:59:59Z" \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"page": 1,
"size": 10,
"reviews": [
{
"id": "a3e01caa-4f89-4ec0-89c5-f18044e86fb8",
"score": 5,
"hasScoreChanged": false,
"status": "NOT_REPLIED",
"comment": "Muito bom, chegou rápido!",
"replies": [],
"createdAt": "2026-09-24T23:50:14.333752Z",
"order": { "id": "58db79bb-c11c-4b99-a174-8b92cb8fb781", "shortId": "1086", "createdAt": "2026-09-24T23:42:11.391Z" },
"merchant": { "id": "abcd-1234-efgh-5678", "name": "Nome da Loja" },
"surveyId": "7a77ef49-82d4-4671-92fa-bed7322d6069",
"version": "v2",
"visibility": "PRIVATE"
}
]
}
replies[] — um array, com from: "MERCHANT" ou "CUSTOMER" — não num campo answer único. Além disso, o campo status pode continuar NOT_REPLIED por um tempo mesmo depois de responder (o iFood atualiza esse campo de forma assíncrona, com atraso). Pra saber com certeza se uma avaliação já tem resposta, confira replies.length > 0 — não confie só em status.
Erros
| Status | Descrição |
|---|---|
| 400 | pageSize acima de 50. |
| 404 | Merchant não vinculado ao seu cadastro no iHub, ou token OAuth expirado/inválido. |
| 429 | Rate limit excedido. |
Detalhes da avaliação
Detalhes completos de uma avaliação: pedido vinculado, perguntas e respostas da pesquisa de satisfação, e o histórico de respostas da loja.
Exemplo
curl https://ihub.arcn.com.br/api/review/abcd-1234-efgh-5678/reviews/a3e01caa-4f89-4ec0-89c5-f18044e86fb8 \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"id": "a3e01caa-4f89-4ec0-89c5-f18044e86fb8",
"score": 5,
"status": "NOT_REPLIED",
"comment": "Muito bom, chegou rápido!",
"customerName": "Maria",
"replies": [
{ "createdAt": "2026-09-27T21:22:36.862495", "text": "Que bom que gostou!", "from": "MERCHANT" }
],
"createdAt": "2026-09-24T23:50:14.333752Z",
"order": { "id": "58db79bb-c11c-4b99-a174-8b92cb8fb781", "shortId": "1086", "createdAt": "2026-09-24T23:42:11.391Z" },
"merchant": { "id": "abcd-1234-efgh-5678", "name": "Nome da Loja" },
"surveyId": "7a77ef49-82d4-4671-92fa-bed7322d6069",
"version": "v2",
"visibility": "PRIVATE",
"questions": [
{
"id": "bf433963-657f-410e-ae8e-a3e8ab913604",
"type": "TEXT",
"title": "Deixar comentário",
"answers": [{ "id": "cc09284b-9c55-445b-a2b7-f00462600d6c", "title": "Muito bom, chegou rápido!" }]
},
{
"id": "57252d92-e048-475d-a68e-f9619c6c2c95",
"type": "CHOICE_MULTIPLE",
"title": "",
"answers": [{ "id": "a40b7179-4421-4708-879f-a0323d626156", "title": "Temperatura certa" }]
},
{
"id": "a6baadc5-e3d2-4ba3-8be6-2fded2c30409",
"type": "RATING",
"title": "O que você achou do pedido?",
"answers": [{ "id": "0faa9d56-1723-4753-ab4f-ab340d9ff35d", "title": "5" }]
}
]
}
Erros
| Status | Descrição |
|---|---|
| 400 | reviewId não é um UUID válido. |
| 404 | Avaliação inexistente, merchant não vinculado, ou token inválido. |
Responder avaliação
Responde uma avaliação. O iFood não tem endpoint separado de edição — reenviar pra esse mesmo endpoint substitui o texto de uma resposta já existente, em vez de criar uma segunda.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| text | string | Sim | Entre 10 e 300 caracteres. |
Exemplo
curl -X POST https://ihub.arcn.com.br/api/review/abcd-1234-efgh-5678/reviews/a3e01caa-4f89-4ec0-89c5-f18044e86fb8/answers \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{ "text": "Obrigado pelo feedback! Vamos melhorar o tempo de entrega." }'
Resposta de sucesso
{
"createdAt": "2026-09-27T21:28:40.376792935Z",
"reviewId": "a3e01caa-4f89-4ec0-89c5-f18044e86fb8",
"text": "Obrigado pelo feedback! Vamos melhorar o tempo de entrega."
}
Erros
| Status | Descrição |
|---|---|
| 400 | text com menos de 10 ou mais de 300 caracteres. |
| 404 | Avaliação inexistente. |
Resumo
Nota média e contagem de avaliações da loja.
Exemplo
curl https://ihub.arcn.com.br/api/review/abcd-1234-efgh-5678/summary \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"totalReviewsCount": 142,
"validReviewsCount": 53,
"score": 4.3
}
404 em vez de um objeto zerado; o iHub normaliza isso automaticamente pra {"totalReviewsCount":0,"validReviewsCount":0,"score":0}, então você nunca vê esse 404 — trate como "loja ainda sem avaliações".
Módulo Catalog (Cardápio)
Gerenciamento completo do cardápio da loja: catálogos, categorias, itens (simples, com complementos, combos e pizzas), preço e disponibilidade — inclusive em lote —, agendamento de horário, inventário e upload de imagem.
Todas as rotas exigem Authorization: Bearer SEU_TOKEN_SECRETO. O {merchantId} na URL deve ser o UUID da loja já vinculada ao seu cadastro no iHub (via Vincular Merchant).
contextModifiers por canal (DEFAULT = Entrega, WHITELABEL = Cardápio Digital, INDOOR = Consumo no Local) — ver aviso na seção de preço de item.
ean (código de barras) que bate com um produto do catálogo central do iFood (ex.: uma bebida de marca conhecida), o iFood assume nome, foto, descrição e peso desse produto automaticamente e o marca como industrialized: true na resposta. A partir daí, esse product não pode mais ser alterado por você — nem nome, nem foto, nem complementos — mesmo reenviando os mesmos dados sem nenhuma mudança. Tentar resulta em 400 "Not allowed to update product: industrialized product, different owner". Não informe ean se precisar manter controle total sobre nome/foto/complementos do item.
Listar catálogos
Lista os catálogos da loja — normalmente só um, mas lojas com múltiplos canais configurados de forma independente (multisetup) podem ter mais de um.
Exemplo
curl https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/catalogs \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
[
{
"catalogId": "37e1a777-f6ae-43c9-a0e3-107fdf1a0069",
"context": ["DEFAULT"],
"status": "AVAILABLE"
}
]
Os valores reais de context são DEFAULT (Entrega), WHITELABEL (Cardápio Digital) e INDOOR (Consumo no Local) — não confunda com "DELIVERY", que não é um valor válido apesar de parecer intuitivo.
Listar categorias
Lista as categorias de um catálogo.
Query string
| Campo | Tipo | Descrição |
|---|---|---|
| include_items | boolean | Se true, tenta incluir os itens de cada categoria na mesma resposta. |
Exemplo
curl https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/catalogs/37e1a777-f6ae-43c9-a0e3-107fdf1a0069/categories \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
[
{ "id": "7680bafc-dc71-4614-a658-a9eb47ffc94b", "name": "Pizzas", "status": "AVAILABLE", "sequence": 1, "index": 1, "template": "PIZZA" },
{ "id": "0f652e28-ed9e-4b97-9c9b-7ca828bd6913", "name": "Sobremesas", "status": "AVAILABLE", "sequence": 2, "index": 2, "template": "DEFAULT" }
]
Criar categoria
Cria uma categoria dentro de um catálogo.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| name | string | Sim | Nome da categoria. |
| status | string | Sim | AVAILABLE ou UNAVAILABLE. |
| template | string | Não | DEFAULT ou PIZZA. O iHub já manda DEFAULT se você omitir. |
"template must be one of the following values: DEFAULT, PIZZA" se ele não vier. O iHub já aplica DEFAULT como padrão pra você não precisar lembrar, mas se for cadastrar uma categoria de pizza, envie template: "PIZZA" explicitamente.
Exemplo
curl -X POST https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/catalogs/37e1a777-f6ae-43c9-a0e3-107fdf1a0069/categories \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{ "name": "Bebidas", "status": "AVAILABLE", "template": "DEFAULT" }'
Resposta de sucesso
Status 201 Created com o objeto da categoria criada (inclui id, usado nos próximos passos).
Itens de uma categoria
Lista os itens cadastrados dentro de uma categoria.
Exemplo
curl https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/categories/7680bafc-dc71-4614-a658-a9eb47ffc94b/items \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"categoryId": "7680bafc-dc71-4614-a658-a9eb47ffc94b",
"items": [
{
"id": "eb09eba5-bdc8-4cb3-aacc-77a31017a9eb",
"type": "DEFAULT",
"categoryId": "7680bafc-dc71-4614-a658-a9eb47ffc94b",
"status": "AVAILABLE",
"price": { "value": 42.9 },
"productId": "9cd01070-1747-460c-87be-89ba4db9a96e",
"externalCode": "PIZZA_MUSSARELA"
}
]
}
Criar ou atualizar item
Endpoint único pra criar e atualizar qualquer tipo de item: simples, com complementos, combo ou pizza — o que muda é a estrutura do payload, não a rota. É um upsert completo: reenviar o mesmo item.id com campos diferentes substitui o item inteiro (não faz merge parcial — ver aviso sobre shifts abaixo).
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| item.id | string | Sim | UUID gerado por você — usado como identificador estável em atualizações futuras. |
| item.productId | string | Sim | Precisa apontar pro id de um objeto em products. A doc oficial não deixa isso claro; omitir gera "item.productId must be a UUID". |
| item.categoryId | string | Depende | Obrigatório pra itens DEFAULT/COMBO_V2. Omita em itens PIZZA — ver aviso na seção de Pizza. |
| item.status | string | Sim | AVAILABLE ou UNAVAILABLE. |
| item.type | string | Não | DEFAULT (padrão), PIZZA ou COMBO_V2. |
| item.price.value | number | Não | Preço do item (não usado em COMBO_V2/PIZZA, cujo preço vem da combinação de opções escolhidas). |
| item.externalCode | string | Não | Código do seu PDV — fica salvo, mas não é aceito como chave nos endpoints de PATCH de preço/status (eles exigem o itemId do iFood). |
| item.shifts | array | Não | Agendamento de disponibilidade por dia/horário — ver seção própria. |
| products | array | Não | Um objeto por produto referenciado (o item principal e, se houver, cada complemento/opção). Campos: id, name, description, imagePath, ean, weight. |
| optionGroups | array | Não | Grupos de complementos — ver seção própria. |
| options | array | Não | As opções (complementos) em si. |
Exemplo — item simples
curl -X PUT https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/items \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '{
"item": {
"id": "SEU-UUID-1",
"type": "DEFAULT",
"categoryId": "7680bafc-dc71-4614-a658-a9eb47ffc94b",
"productId": "SEU-UUID-2",
"status": "AVAILABLE",
"price": { "value": 25.90 },
"externalCode": "SKU-001"
},
"products": [
{ "id": "SEU-UUID-2", "name": "X-Burger", "description": "Pão, carne, queijo e salada" }
],
"optionGroups": [],
"options": []
}'
Resposta de sucesso
Status 200 OK com o item completo já persistido (inclui contextModifiers gerados automaticamente pro contexto DEFAULT).
Validações reais aplicadas pelo iFood
| Campo | Regra confirmada |
|---|---|
products[].name | Até 150 caracteres (não 100, como uma leitura apressada da doc sugere). |
products[].weight.unit | Só aceita kg, g, l ou ml — qualquer outro valor (ex.: "unidades") retorna 400. Se o item for vendido por unidade, simplesmente omita weight. |
Complementos (grupos de opção)
Um grupo de complementos (optionGroups[]) e suas opções (options[]) são criados no mesmo payload de PUT /items, referenciados a partir do product do item principal.
{
"item": { "id": "ITEM-ID", "type": "DEFAULT", "categoryId": "CAT-ID", "productId": "PROD-ID", "status": "AVAILABLE", "price": { "value": 25.90 } },
"products": [
{ "id": "PROD-ID", "name": "X-Burger", "optionGroups": [ { "id": "GRUPO-ID", "min": 0, "max": 3 } ] },
{ "id": "PROD-QUEIJO", "name": "Queijo extra" },
{ "id": "PROD-BACON", "name": "Bacon" }
],
"optionGroups": [
{ "id": "GRUPO-ID", "name": "Adicionais", "status": "AVAILABLE", "optionIds": ["OPT-QUEIJO", "OPT-BACON"] }
],
"options": [
{ "id": "OPT-QUEIJO", "productId": "PROD-QUEIJO", "status": "AVAILABLE", "index": 0, "price": { "value": 4.00 } },
{ "id": "OPT-BACON", "productId": "PROD-BACON", "status": "AVAILABLE", "index": 1, "price": { "value": 6.00 } }
]
}
product.optionGroups[].min/max é quem define se o grupo é obrigatório (min ≥ 1) e quantas opções podem ser escolhidas. optionGroups[].optionGroupType pode ser omitido pra um grupo genérico — o iFood aplica DEFAULT automaticamente.
COMBO_V2 ou PIZZA exigem um optionGroupType explícito dentre os valores próprios de cada tipo (ver seções abaixo) — omitir, ou usar o padrão genérico, resulta em "The OptionGroup '...' must have a declared 'type'...". Um grupo de complementos comum só funciona em itens DEFAULT.
Depois de criado, preço/status/código de uma opção específica podem ser atualizados sem reenviar o item inteiro — ver Preço de complemento.
Combo
Um combo (item.type: "COMBO_V2") é um item cujo "produto principal" tem um grupo obrigatório (o combo em si) e pode ter grupos adicionais — cada grupo usa optionGroupType: "OFFER_UNIT", e o grupo principal é marcado com associationType: "MAIN" no vínculo do produto.
{
"item": { "id": "ITEM-ID", "type": "COMBO_V2", "categoryId": "CAT-ID", "productId": "COMBO-PROD-ID", "status": "AVAILABLE" },
"products": [
{
"id": "COMBO-PROD-ID", "name": "Combo Clássico",
"optionGroups": [
{ "id": "GRUPO-LANCHE", "min": 1, "max": 1, "associationType": "MAIN" },
{ "id": "GRUPO-BEBIDA", "min": 1, "max": 1 }
]
},
{ "id": "PROD-HAMBURGUER", "name": "Hambúrguer" },
{ "id": "PROD-BACON-BURGUER", "name": "Hambúrguer de bacon" },
{ "id": "PROD-REFRI-LARANJA", "name": "Refrigerante de laranja" },
{ "id": "PROD-REFRI-UVA", "name": "Refrigerante de uva" }
],
"optionGroups": [
{ "id": "GRUPO-LANCHE", "name": "Escolha seu hambúrguer", "status": "AVAILABLE", "optionGroupType": "OFFER_UNIT", "optionIds": ["OPT-HAMBURGUER", "OPT-BACON-BURGUER"] },
{ "id": "GRUPO-BEBIDA", "name": "Escolha seu refrigerante", "status": "AVAILABLE", "optionGroupType": "OFFER_UNIT", "optionIds": ["OPT-REFRI-LARANJA", "OPT-REFRI-UVA"] }
],
"options": [
{ "id": "OPT-HAMBURGUER", "productId": "PROD-HAMBURGUER", "status": "AVAILABLE", "index": 0, "price": { "value": 15.00 } },
{ "id": "OPT-BACON-BURGUER", "productId": "PROD-BACON-BURGUER", "status": "AVAILABLE", "index": 1, "price": { "value": 18.00 } },
{ "id": "OPT-REFRI-LARANJA", "productId": "PROD-REFRI-LARANJA", "status": "AVAILABLE", "index": 0, "price": { "value": 8.00 } },
{ "id": "OPT-REFRI-UVA", "productId": "PROD-REFRI-UVA", "status": "AVAILABLE", "index": 1, "price": { "value": 8.00 } }
]
}
O preço final do combo é a soma das opções escolhidas em cada grupo — o item em si não tem price próprio.
Pizza
Um item de pizza (item.type: "PIZZA") tem, no mínimo, os grupos SIZE, CRUST, EDGE e TOPPING — mesmo que EDGE seja opcional (min: 0), o grupo precisa existir, senão o iFood rejeita com "Pizza item must have sizes, crusts and edges".
template: "PIZZA"), a resposta é 409 "Cannot have two categories with same id". Capture o categoryId devolvido na resposta se precisar dele depois.
TOPPING) precisa de um contextModifiers[] com uma entrada por tamanho, usando o campo parentOptionId apontando pro id da opção de tamanho correspondente. parentCustomizationOptionId é um nome parecido que só existe nos endpoints de PATCH de preço/status de opção — usá-lo aqui (na criação) resulta em "Pizza topping must be linked with a size", sem indicar qual campo está errado.
{
"item": { "id": "ITEM-ID", "type": "PIZZA", "productId": "PIZZA-PROD-ID", "status": "AVAILABLE" },
"products": [
{
"id": "PIZZA-PROD-ID", "name": "Calabresa",
"optionGroups": [
{ "id": "GRUPO-TAMANHO", "min": 1, "max": 1 },
{ "id": "GRUPO-MASSA", "min": 1, "max": 1 },
{ "id": "GRUPO-BORDA", "min": 0, "max": 1 },
{ "id": "GRUPO-SABOR", "min": 1, "max": 1 }
]
},
{ "id": "PROD-TAM-P", "name": "Pequena" }, { "id": "PROD-TAM-G", "name": "Grande" },
{ "id": "PROD-MASSA-TRAD", "name": "Massa Tradicional" }, { "id": "PROD-MASSA-FINA", "name": "Massa Fina" },
{ "id": "PROD-BORDA-TRAD", "name": "Borda Tradicional" }, { "id": "PROD-BORDA-CATUPIRY", "name": "Borda Catupiry" },
{ "id": "PROD-CALABRESA", "name": "Calabresa" }, { "id": "PROD-MARGHERITA", "name": "Margherita" }
],
"optionGroups": [
{ "id": "GRUPO-TAMANHO", "name": "Tamanho", "status": "AVAILABLE", "optionGroupType": "SIZE", "optionIds": ["OPT-TAM-P", "OPT-TAM-G"] },
{ "id": "GRUPO-MASSA", "name": "Massa", "status": "AVAILABLE", "optionGroupType": "CRUST", "optionIds": ["OPT-MASSA-TRAD", "OPT-MASSA-FINA"] },
{ "id": "GRUPO-BORDA", "name": "Borda", "status": "AVAILABLE", "optionGroupType": "EDGE", "optionIds": ["OPT-BORDA-TRAD", "OPT-BORDA-CATUPIRY"] },
{ "id": "GRUPO-SABOR", "name": "Sabor", "status": "AVAILABLE", "optionGroupType": "TOPPING", "optionIds": ["OPT-CALABRESA", "OPT-MARGHERITA"] }
],
"options": [
{ "id": "OPT-TAM-P", "productId": "PROD-TAM-P", "status": "AVAILABLE", "index": 0, "price": { "value": 25.00 }, "fractions": [1, 2] },
{ "id": "OPT-TAM-G", "productId": "PROD-TAM-G", "status": "AVAILABLE", "index": 1, "price": { "value": 42.00 }, "fractions": [1, 2, 3, 4] },
{ "id": "OPT-MASSA-TRAD", "productId": "PROD-MASSA-TRAD", "status": "AVAILABLE", "index": 0, "price": { "value": 0 } },
{ "id": "OPT-MASSA-FINA", "productId": "PROD-MASSA-FINA", "status": "AVAILABLE", "index": 1, "price": { "value": 2.00 } },
{ "id": "OPT-BORDA-TRAD", "productId": "PROD-BORDA-TRAD", "status": "AVAILABLE", "index": 0, "price": { "value": 0 } },
{ "id": "OPT-BORDA-CATUPIRY", "productId": "PROD-BORDA-CATUPIRY", "status": "AVAILABLE", "index": 1, "price": { "value": 8.00 } },
{
"id": "OPT-CALABRESA", "productId": "PROD-CALABRESA", "status": "AVAILABLE", "index": 0, "price": { "value": 0 },
"contextModifiers": [
{ "catalogContext": "DEFAULT", "parentOptionId": "OPT-TAM-P", "price": { "value": 0 }, "status": "AVAILABLE" },
{ "catalogContext": "DEFAULT", "parentOptionId": "OPT-TAM-G", "price": { "value": 0 }, "status": "AVAILABLE" }
]
},
{
"id": "OPT-MARGHERITA", "productId": "PROD-MARGHERITA", "status": "AVAILABLE", "index": 1, "price": { "value": 0 },
"contextModifiers": [
{ "catalogContext": "DEFAULT", "parentOptionId": "OPT-TAM-P", "price": { "value": 0 }, "status": "AVAILABLE" },
{ "catalogContext": "DEFAULT", "parentOptionId": "OPT-TAM-G", "price": { "value": 0 }, "status": "AVAILABLE" }
]
}
]
}
| Detalhe | Regra confirmada |
|---|---|
Tamanhos precisam de fractions | Um array com os "pedaços" válidos pra aquele tamanho, ex.: [1,2,3,4] pra permitir até 4 sabores diferentes numa pizza grande. Omitir gera "Pizza size must have fractions". |
Sabor precisa de um contextModifiers por tamanho | Faltar o vínculo com qualquer tamanho cadastrado gera "Pizza topping option X must be linked with all sizes in all contexts". |
Agendamento de disponibilidade (shifts)
Restringe a venda de um item a dias/horários específicos (ex.: só no almoço). É um campo do próprio item, enviado junto no PUT /items — não existe endpoint dedicado.
{
"item": {
"id": "ITEM-ID", "type": "DEFAULT", "categoryId": "CAT-ID", "productId": "PROD-ID", "status": "AVAILABLE",
"shifts": [
{ "startTime": "11:00", "endTime": "15:00", "monday": true, "tuesday": true, "wednesday": true, "thursday": true, "friday": true, "saturday": false, "sunday": false }
]
},
"products": [ ... ]
}
shifts com o valor atual, o iFood reseta pro padrão dele (00:00–23:59, todos os dias — que na prática já significa "sempre disponível"). Pra restaurar "sempre disponível" de propósito, basta mandar shifts: [] — o iFood aplica esse mesmo padrão automaticamente. Se quiser manter uma restrição já configurada, busque o item atual primeiro (GET .../items/{itemId}/flat) e reenvie o shifts dele junto com o resto do payload.
Obter item completo
Devolve um item com produto, grupos de opção e opções já resolvidos — útil pra reconstruir o payload de um PUT antes de alterar só um campo (ver aviso acima sobre shifts).
Exemplo
curl https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/items/eb09eba5-bdc8-4cb3-aacc-77a31017a9eb/flat \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta: { "item": {...}, "products": [...], "optionGroups": [...], "options": [...] } — mesmo formato do body de PUT /items, pronto pra editar e reenviar.
Itens vendáveis
Lista os itens ativos e disponíveis pra venda num catálogo agora.
Itens bloqueados
Lista os itens indisponíveis num catálogo, agrupados por categoria, com o motivo do bloqueio em cada um — útil pra diagnosticar por que um item não aparece no app do iFood sem precisar adivinhar.
Resposta de sucesso
{
"categories": [
{
"name": "Sobremesas",
"items": [
{ "id": "...", "name": "Pudim", "restrictions": ["ITEM_PAUSED"] }
]
}
]
}
Motivos comuns em restrictions: CATEGORY_PAUSED, ITEM_PAUSED, ITEM_PRICE_MISSING, OPTION_GROUP_WITHOUT_AVAILABLE_OPTIONS, OPTION_PAUSED.
Preço de item
Atualiza o preço de um item já existente, sem precisar reenviar o item inteiro.
Body (JSON) — array de objetos
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| itemId | string | Sim | O id do item (não productId nem externalCode — o iFood rejeita esses como chave aqui). |
| price.value | number | Sim | Novo preço. |
| priceByCatalog | array | Não | Overrides de preço por contexto/canal, ex.: [{"value":29.9,"catalogContext":"WHITELABEL"}]. |
priceByCatalog pro contexto DEFAULT mesmo que você não peça, sincronizando os dois campos. Se você ler o preço de volta, priorize contextModifiers[DEFAULT].price sobre item.price — é o que reflete atualizações em lote (ver abaixo).
Exemplo
curl -X PATCH https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/items/price \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '[ { "itemId": "eb09eba5-bdc8-4cb3-aacc-77a31017a9eb", "price": { "value": 27.90 } } ]'
Resposta: {"results":[{"itemId":"...","success":true}]} com status 200 se tudo deu certo, ou 207 Multi-Status se algum item da lista falhou (cada resultado indica o próprio sucesso).
Status (disponibilidade) de item
Mesmo formato de preço de item, pra pausar/reativar.
Exemplo
curl -X PATCH https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/items/status \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '[ { "itemId": "eb09eba5-bdc8-4cb3-aacc-77a31017a9eb", "status": "UNAVAILABLE" } ]'
Aceita statusByCatalog igual a priceByCatalog, pra pausar só num canal específico.
Código externo do item
Atualiza o código do seu PDV vinculado a um item.
Body (JSON)
| Campo | Tipo | Obrigatório |
|---|---|---|
| itemId | string | Sim |
| externalCode | string (máx. 100) | Sim |
Preço de complemento
Mesma lógica de preço de item, mas pra uma opção (complemento) dentro de um grupo.
Body (JSON)
| Campo | Tipo | Obrigatório |
|---|---|---|
| optionId | string | Sim |
| price.value | number | Sim |
Assim como em itens, o iHub sincroniza automaticamente com contextModifiers[DEFAULT] nessa chamada.
Status de complemento
Body: { "optionId": "...", "status": "AVAILABLE" | "UNAVAILABLE" }.
Código externo do complemento
Body: { "optionId": "...", "externalCode": "..." } (máx. 100 caracteres).
Atualização de preço em massa
Diferente do PATCH /items/price: esse é o endpoint de lote de verdade — assíncrono, processa centenas de itens numa única chamada e devolve um batchId pra acompanhar.
Body (JSON) — array de objetos
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| price.value | number | Sim | Novo preço. |
| externalCode | string | Um dos dois | Identifica o produto pelo código do seu PDV. |
| productId | string | Um dos dois | Ou identifica pelo id do produto no iFood. |
PATCH /items/price (que sincroniza os dois), esse endpoint de lote grava só em contextModifiers[DEFAULT].price. Se sua aplicação lê item.price (raiz) em vez de contextModifiers, o valor vai parecer desatualizado depois de um lote — sempre priorize contextModifiers[DEFAULT] na leitura.
Exemplo
curl -X PATCH https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/products/price \
-H "Authorization: Bearer SEU_TOKEN_SECRETO" \
-H "Content-Type: application/json" \
-d '[
{ "externalCode": "SKU-001", "price": { "value": 27.90 } },
{ "externalCode": "SKU-002", "price": { "value": 15.50 } }
]'
Resposta de sucesso
Status 202 Accepted com {"batchId": "..."} — consulte o progresso em Consultar lote.
Atualização de status em massa
Mesmo formato do lote de preço: [{ "externalCode": "...", "status": "AVAILABLE" | "UNAVAILABLE" }], resposta 202 com batchId.
Consultar status do lote
Exemplo
curl https://ihub.arcn.com.br/api/catalog/abcd-1234-efgh-5678/batch/batch-uuid-aqui \ -H "Authorization: Bearer SEU_TOKEN_SECRETO" \ -H "Accept: application/json"
Resposta de sucesso
{
"batchStatus": "COMPLETED",
"results": [
{ "resourceId": "SKU-001", "result": "SUCCESS" },
{ "resourceId": "SKU-002", "result": "SUCCESS" }
]
}
batchStatus passa por PROCESSING antes de COMPLETED — normalmente leva poucos segundos pra lotes de até algumas centenas de itens. Faça polling com um intervalo curto (ex.: 2s) até sair de PROCESSING.
Inventário
Define um limite de estoque pra um produto parar de vender automaticamente quando esgotar.
Body: { "productId": "...", "amount": 10 }. Status 201.
Consulta o estoque atual do produto.
Remove o controle de estoque (volta a vender sem limite) de um ou mais produtos. Body: { "productIds": ["...", "..."] }.
Upload de imagem
Envia uma imagem (JPG/PNG, até 5MB) em base64 e devolve um caminho reutilizável em products[].imagePath.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| image | string | Sim | Imagem em base64 (com ou sem o prefixo data:image/...;base64,). |
Resposta de sucesso
Status 201 Created com {"imagePath": "..."}.
imagePath retornado por esse upload é um caminho relativo do storage do iFood, não a URL pública do CDN. Pra pegar a URL absoluta (a mesma que aparece quando você consulta o item depois), associe esse imagePath ao produto via PUT /items e depois releia o item com GET .../items/{itemId}/flat — o imagePath que volta ali já é a URL final resolvida.