Loja e cardápio
GET merchant e GET menus: dados da loja, categorias, itens, grupos de opções e o grupo Tamanho.
A API expõe duas operações de leitura sobre a loja ligada à credencial: os dados cadastrais (GET /v1/merchant/{merchantId}) e o cardápio publicado (GET /v1/merchant/{merchantId}/menus). Ambas são somente leitura. O lojista continua editando loja e cardápio pelo painel do MeuPedido; o seu sistema lê o resultado.
| Operação | Escopo | Retorna |
|---|---|---|
GET /v1/merchant/{merchantId} | merchant:read | Um objeto com os dados da loja |
GET /v1/merchant/{merchantId}/menus | catalog:read | Um array com um cardápio |
O merchantId é o da credencial
Uma credencial pertence a uma única loja. O merchantId da URL precisa ser o id dessa loja; qualquer outro id devolve 404, mesmo que a loja exista. O id está no claim merchant_id do token de acesso e no bloco merchant.id de todo pedido devolvido pela API.
Várias lojas
Para integrar N lojas, o lojista de cada uma gera a própria credencial. Cada token só enxerga a loja que o emitiu. Veja Conceitos.
Buscar a loja
curl https://api.meupedido.io/open-delivery/v1/merchant/8f1c2b6e-4a3d-4c7e-9b21-6d0f3a5e8c47 \
-H "Authorization: Bearer $ACCESS_TOKEN"Resposta 200:
{
"id": "8f1c2b6e-4a3d-4c7e-9b21-6d0f3a5e8c47",
"name": "Cantina da Vila",
"description": "Massas artesanais e pizzas de fermentação natural.",
"document": "12345678000190",
"status": "AVAILABLE",
"contactEmails": ["contato@cantinadavila.com.br"],
"contactPhones": ["+5511912345678"],
"address": {
"country": "BR",
"state": "SP",
"city": "São Paulo",
"district": "Vila Madalena",
"street": "Rua Harmonia",
"number": "512",
"postalCode": "05435-000",
"complement": null,
"latitude": -23.5537,
"longitude": -46.6883
},
"services": [
{ "serviceType": "DELIVERY", "status": "AVAILABLE", "menuId": "c9d4e2a1-7b3f-4f8e-a6d5-2e1b9c0f4a73" },
{ "serviceType": "TAKEOUT", "status": "AVAILABLE", "menuId": "c9d4e2a1-7b3f-4f8e-a6d5-2e1b9c0f4a73" }
],
"createdAt": "2025-03-12T14:02:11Z",
"lastUpdate": "2026-09-18T21:45:09Z"
}Campos da loja
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Id da loja. É o mesmo merchantId da URL e do claim merchant_id do token. |
name | string | Nome de exibição da loja. |
description | string ou null | Descrição livre, como aparece no cardápio digital. |
document | string ou null | CNPJ ou CPF da loja, só dígitos. |
status | AVAILABLE ou UNAVAILABLE | Se a loja está aberta para receber pedidos neste momento. |
contactEmails | string[] | E-mails de contato. |
contactPhones | string[] | Telefones de contato. |
address | objeto | Endereço com country, state, city, district, street, number, postalCode, complement, latitude e longitude. |
services | objeto[] | Modalidades de atendimento. Cada item traz serviceType (DELIVERY, TAKEOUT ou INDOOR), status e o menuId usado naquela modalidade. |
createdAt | data | Criação da loja, em UTC com sufixo Z. |
lastUpdate | data | Última alteração dos dados da loja, em UTC com sufixo Z. |
Campos sem valor vêm como null, nunca são omitidos.
Buscar o cardápio
O cardápio é devolvido em um array, como pede o padrão Open Delivery. No MeuPedido cada loja tem um único cardápio, então o array sempre traz um elemento e o id dele é o menuId referenciado em services.
curl https://api.meupedido.io/open-delivery/v1/merchant/8f1c2b6e-4a3d-4c7e-9b21-6d0f3a5e8c47/menus \
-H "Authorization: Bearer $ACCESS_TOKEN"Resposta 200, resumida a uma categoria, dois itens e dois grupos de opções:
[
{
"id": "c9d4e2a1-7b3f-4f8e-a6d5-2e1b9c0f4a73",
"name": "Cardápio principal",
"categories": [
{
"id": "5b7e1f3a-9c2d-4e6b-8a1f-0d3c7e9b2a54",
"name": "Pizzas",
"description": "Massa de fermentação natural, 35 cm ou 25 cm.",
"index": 0,
"status": "AVAILABLE",
"itemOfferIds": [
"a3f9c1d2-6e4b-4a8c-9f1d-7b2e5c0a8d36",
"e7d2b4c9-1a5f-4c3e-b8a2-9f6d0e1c3b75"
]
}
],
"items": [
{
"id": "a3f9c1d2-6e4b-4a8c-9f1d-7b2e5c0a8d36",
"name": "Pizza Margherita",
"description": "Molho de tomate, mussarela de búfala e manjericão.",
"externalCode": "PZ-001",
"status": "AVAILABLE",
"image": "https://cdn.meupedido.io/lojas/cantina-da-vila/pizza-margherita.jpg",
"price": { "value": 0, "originalValue": 0, "currency": "BRL" },
"optionGroupIds": [
"a3f9c1d2-6e4b-4a8c-9f1d-7b2e5c0a8d36-variacoes",
"2c8e4b1d-7f3a-4d9e-a5c6-1b0f8d3e7a92"
]
},
{
"id": "e7d2b4c9-1a5f-4c3e-b8a2-9f6d0e1c3b75",
"name": "Pizza Calabresa",
"description": "Calabresa artesanal, cebola roxa e azeitonas.",
"externalCode": "PZ-002",
"status": "UNAVAILABLE",
"image": null,
"price": { "value": 62.9, "originalValue": 69.9, "currency": "BRL" },
"optionGroupIds": ["2c8e4b1d-7f3a-4d9e-a5c6-1b0f8d3e7a92"]
}
],
"optionGroups": [
{
"id": "a3f9c1d2-6e4b-4a8c-9f1d-7b2e5c0a8d36-variacoes",
"name": "Tamanho",
"description": null,
"index": 0,
"status": "AVAILABLE",
"minPermitted": 1,
"maxPermitted": 1,
"options": [
{
"id": "4d1a7c3e-8b5f-4e2a-9c6d-3f0b1e8a5d27",
"name": "Grande (35 cm)",
"externalCode": "PZ-001-G",
"index": 0,
"status": "AVAILABLE",
"price": { "value": 69.9, "originalValue": 69.9, "currency": "BRL" }
},
{
"id": "9e3b5d7f-2c1a-4f6e-8d4b-6a0c2f9e1b58",
"name": "Média (25 cm)",
"externalCode": "PZ-001-M",
"index": 1,
"status": "AVAILABLE",
"price": { "value": 49.9, "originalValue": 49.9, "currency": "BRL" }
}
]
},
{
"id": "2c8e4b1d-7f3a-4d9e-a5c6-1b0f8d3e7a92",
"name": "Adicionais",
"description": "Escolha até 3.",
"index": 1,
"status": "AVAILABLE",
"minPermitted": 0,
"maxPermitted": 3,
"options": [
{
"id": "7a2f9d4b-3e6c-4b1a-8f5d-0c9e2a7b4d63",
"name": "Borda recheada",
"externalCode": "AD-010",
"index": 0,
"status": "AVAILABLE",
"price": { "value": 8, "originalValue": 8, "currency": "BRL" }
}
]
}
]
}
]Estrutura do cardápio
O cardápio é normalizado: categorias apontam para itens por id, itens apontam para grupos de opções por id. Nada é aninhado. Monte índices por id em memória antes de percorrer.
Cardápio
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Id do cardápio. Igual ao menuId em services da loja. |
name | string | Nome do cardápio. |
categories | objeto[] | Categorias, na ordem de exibição. |
items | objeto[] | Todos os itens vendáveis do cardápio. |
optionGroups | objeto[] | Todos os grupos de opções referenciados pelos itens. |
Categoria
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Id da categoria. |
name | string | Nome da categoria. |
description | string ou null | Descrição opcional. |
index | número | Posição na ordem de exibição, a partir de 0. |
status | AVAILABLE ou UNAVAILABLE | Disponibilidade da categoria inteira. |
itemOfferIds | string[] | Ids dos itens que pertencem à categoria, na ordem de exibição. |
Item
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Id do item. É o mesmo id que chega em items[].id de um pedido. |
name | string | Nome do item. |
description | string ou null | Descrição. |
externalCode | string ou null | Código do produto no sistema do lojista (PLU, SKU). Use para casar com o seu cadastro. |
status | AVAILABLE ou UNAVAILABLE | Disponibilidade do item. |
image | string ou null | URL da imagem. |
price | objeto | value (preço atual), originalValue (preço sem promoção) e currency (BRL). |
optionGroupIds | string[] | Ids dos grupos de opções que o item oferece, na ordem de exibição. |
Grupo de opções
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Id do grupo. |
name | string | Nome do grupo, como "Tamanho" ou "Adicionais". |
description | string ou null | Descrição opcional. |
index | número | Posição na ordem de exibição. |
status | AVAILABLE ou UNAVAILABLE | Disponibilidade do grupo. |
minPermitted | número | Quantidade mínima de opções que o cliente precisa escolher. 1 ou mais torna o grupo obrigatório. |
maxPermitted | número | Quantidade máxima de opções. |
options | objeto[] | Opções do grupo, cada uma com id, name, externalCode, index, status e price. |
Variações viram o grupo "Tamanho"
No MeuPedido um produto pode ter vários preços (por exemplo, pizza grande e média). O padrão Open Delivery não tem esse conceito no item, então a API converte cada produto com variações em:
- um item, que representa o produto, e
- um grupo de opções obrigatório (
minPermitted: 1,maxPermitted: 1) chamado Tamanho, com id{productId}-variacoes, em que cada opção é uma variação com o próprio preço.
O preço que conta é o da variação escolhida. Em um pedido, a variação não aparece em options[]: o item chega com externalCode igual ao id do produto, name com o nome do produto já incluindo a variação (por exemplo, "Pizza Margherita Grande") e unitPrice com o preço da variação escolhida. O options[] do item traz apenas os complementos, e totalPrice já considera unitPrice mais optionsPrice. Não há um id de variação no pedido; para saber qual foi escolhida, compare o unitPrice com os preços das opções do grupo Tamanho no cardápio, ou use o name.
Não trate Tamanho como adicional
Um grupo cujo id termina em -variacoes representa o próprio produto, não um acréscimo. Se o seu PDV tem o conceito de variação ou grade, mapeie para ele no cardápio, e no pedido resolva a variação pelo preço unitário ou pelo nome do item.
Itens indisponíveis não somem
Quando o lojista pausa um item, ele continua no cardápio com status: "UNAVAILABLE". O mesmo vale para categorias, grupos e opções. Isso mantém os ids estáveis: um pedido antigo sempre aponta para um item que existe no cardápio. Filtre por status na hora de exibir; não use a ausência do item como sinal de nada.
Quando sincronizar
Não há evento de cardápio na API. Para manter uma cópia local, busque o cardápio em um intervalo que faça sentido para a sua operação e compare lastUpdate da loja para saber se algo mudou nos dados cadastrais. Cada chamada conta no limite de 600 requisições por minuto da credencial.
Próximos passos
- Estrutura do pedido: como os itens e opções do cardápio aparecem em um pedido.
- Autenticação: escopos
merchant:readecatalog:read. - Referência de API: parâmetros e esquemas completos de
getMerchantegetMenus.