MeuPedido/developer
Pedidos

Polling

Consulta de eventos com entrega at-least-once, dedupe por eventId, limite de 200 por consulta e confirmação obrigatória.

Polling é o modo padrão de receber eventos: o seu sistema consulta GET /v1/events:polling em intervalo fixo, processa cada evento e confirma o recebimento em POST /v1/events/acknowledgment. Nada é perdido entre uma consulta e outra, porque o que não foi confirmado volta na próxima.

Loop de polling de eventosQuatro passos em ciclo: consultar GET /v1/events:polling, buscar cada pedido em orderURL, processar deduplicando por eventId e confirmar com POST /v1/events/acknowledgment. A confirmação fecha o ciclo e a consulta seguinte traz de novo tudo que não foi confirmado.eventospara cada eventopróxima consultasem ack, o evento volta inteiroConsultarGET /v1/events:polling?limit=100limit padrão 100, máximo 200sem eventos devolve [] (nunca 204)Buscar o pedidoGET {orderURL}o envelope traz só id, tipo e linko pedido completo vem daquiProcessardedupe por eventIdo mesmo evento pode chegar de novograve no seu banco antes do ackConfirmarPOST /v1/events/acknowledgment[{ "id": eventId }] → 202confirmado é apagado após 30 dias
  • Ciclo normal: confirmar e consultar de novo
  • Evento sem ack volta na próxima consulta (entrega at-least-once)
  • Sem cursor e sem filtro: cada credencial tem o próprio feed, em ordem de createdAt

O ciclo

Consultar

GET /v1/events:polling devolve os eventos pendentes da sua credencial, em ordem de createdAt. Cada item é um envelope com eventId, eventType, orderId, orderURL e createdAt. O envelope nunca traz o pedido.

Buscar o pedido

Para os eventos que precisam do conteúdo (CREATED, MODIFIED), faça GET em orderURL. Você lê o pedido de agora, e não uma fotografia do instante da transição.

Processar e gravar

Aplique o evento no seu sistema e grave o eventId como processado. Só depois disso passe ao próximo passo.

Confirmar

POST /v1/events/acknowledgment com a lista de eventId processados. Eventos confirmados saem do feed. Eventos não confirmados voltam na próxima consulta.

Consultar eventos

GET /v1/events:polling?limit=100
Authorization: Bearer {access_token}

Escopo: orders:read.

ParâmetroTipoPadrãoDescrição
limitinteiro100Quantidade máxima de eventos por resposta. Máximo 200; valores maiores são reduzidos para 200.

Não existe cursor, since ou filtro por tipo. O feed é o conjunto de eventos ainda não confirmados pela sua credencial, sempre a partir do mais antigo.

curl "https://api.meupedido.io/open-delivery/v1/events:polling?limit=100" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Resposta

200 com um array. Quando não há eventos pendentes o array vem vazio; a API nunca responde 204.

200 OK
[
  {
    "eventId": "e1b9c0d2-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "eventType": "CREATED",
    "orderId": "3f8a1c2d-5b6e-4f7a-9c8d-1e2f3a4b5c6d",
    "orderURL": "https://api.meupedido.io/open-delivery/v1/orders/3f8a1c2d-5b6e-4f7a-9c8d-1e2f3a4b5c6d",
    "createdAt": "2026-09-19T14:02:11Z"
  },
  {
    "eventId": "0c7d2e91-6f3a-4b58-9e1d-4a2b3c4d5e6f",
    "eventType": "CANCELLED",
    "orderId": "9b2e4f6a-1c3d-4e5f-8a7b-6c5d4e3f2a1b",
    "orderURL": "https://api.meupedido.io/open-delivery/v1/orders/9b2e4f6a-1c3d-4e5f-8a7b-6c5d4e3f2a1b",
    "createdAt": "2026-09-19T14:03:40Z",
    "metadata": {
      "reason": "Cliente desistiu do pedido.",
      "code": "CONSUMER_CANCELLATION_REQUESTED"
    }
  }
]

Os campos opcionais (sourceAppId, metadata, delivery) só aparecem quando têm valor. A descrição de cada um está no catálogo de eventos.

Confirmar eventos

POST /v1/events/acknowledgment
Authorization: Bearer {access_token}
Content-Type: application/json

Escopo: orders:read. O corpo é um array de objetos com o id de cada evento:

curl -X POST "https://api.meupedido.io/open-delivery/v1/events/acknowledgment" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    { "id": "e1b9c0d2-4a5b-4c6d-8e7f-9a0b1c2d3e4f" },
    { "id": "0c7d2e91-6f3a-4b58-9e1d-4a2b3c4d5e6f" }
  ]'
202 Accepted
{ "acknowledged": 2 }

acknowledged é a quantidade de eventos que saiu do feed. Ids que não pertencem à sua credencial, ids repetidos e ids já confirmados são ignorados em silêncio: a resposta continua 202, apenas com a contagem menor.

Garantias

At-least-once. Todo evento é entregue pelo menos uma vez. Consultar não confirma: um evento devolvido pela consulta continua pendente até você chamar acknowledgment. Se o seu processo cair entre a consulta e a confirmação, o evento volta na próxima consulta.

Sem perda entre consultas. Não existe cursor a manter. O estado "o que ainda falta" vive na API, por credencial, e a única coisa que o move é a confirmação.

Ordem. Os eventos vêm ordenados por createdAt. A ordem entre pedidos diferentes não importa para o seu fluxo; a ordem dentro do mesmo pedido segue o ciclo de vida.

Um feed por credencial. Duas credenciais na mesma loja têm feeds independentes. Confirmar em uma não tira o evento da outra. Uma credencial criada hoje não recebe os eventos de ontem. Uma credencial pausada continua acumulando eventos, que ficam disponíveis quando ela for retomada.

Retenção. Eventos confirmados são apagados após 30 dias. Eventos não confirmados nunca são apagados: eles continuam voltando até serem confirmados.

Deduplicação

Porque a entrega é at-least-once, o mesmo eventId pode chegar mais de uma vez, seja por uma confirmação que não chegou, seja porque você recebe por polling e por webhook ao mesmo tempo (modo BOTH). Trate o eventId como chave única:

async function handle(event) {
  // Já processado: só confirmar de novo, sem reaplicar.
  if (await store.hasEvent(event.eventId)) return;

  const order = await fetchOrder(event.orderURL);
  await store.applyInTransaction(order, event); // grava o pedido e o eventId juntos
}

Grave o eventId na mesma transação em que aplica o efeito. Gravar antes cria a chance de marcar como processado algo que falhou; gravar depois cria a chance de aplicar duas vezes.

Intervalo e limite

  • Consulte a cada 5 a 10 segundos em operação normal. Intervalo menor que isso não faz o pedido chegar antes e consome o seu limite de 600 requisições por minuto.
  • Use limit=200 se a sua integração processa em lote. Se a resposta vier cheia (200 itens), consulte de novo imediatamente após confirmar, sem esperar o intervalo.
  • Confirme em lote, mas não segure a confirmação por muito tempo: enquanto não confirmar, os mesmos eventos ocupam espaço na próxima resposta.
  • Em 429, respeite Retry-After (60 segundos) antes de tentar de novo.

Webhook não substitui a confirmação

Se a sua credencial está em modo WEBHOOK ou BOTH, receber o evento na sua URL não o confirma. Chame acknowledgment também para eventos recebidos por webhook; caso contrário, eles continuam no polling e nunca são limpos. Veja Webhooks.

Um loop completo

const BASE = 'https://api.meupedido.io/open-delivery';

async function poll(accessToken) {
  const res = await fetch(`${BASE}/v1/events:polling?limit=200`, {
    headers: { Authorization: `Bearer ${accessToken}` },
  });
  if (res.status === 429) {
    const wait = Number(res.headers.get('retry-after') ?? 60) * 1000;
    await new Promise((r) => setTimeout(r, wait));
    return;
  }
  const events = await res.json();
  const done = [];

  for (const event of events) {
    try {
      await handle(event);
      done.push({ id: event.eventId });
    } catch (err) {
      // Não confirma: o evento volta na próxima consulta.
      console.error('Falha ao processar', event.eventId, err);
    }
  }

  if (done.length > 0) {
    await fetch(`${BASE}/v1/events/acknowledgment`, {
      method: 'POST',
      headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
      body: JSON.stringify(done),
    });
  }

  // Resposta cheia: há mais, consulta de novo sem esperar.
  if (events.length === 200) return poll(accessToken);
}

setInterval(() => poll(getToken()).catch(console.error), 5000);

Erros

StatusCorpoQuando
401vazio, com WWW-AuthenticateSem token ou token expirado.
401{"error":"invalid_token"}Credencial pausada ou revogada pelo lojista.
403{"error":"insufficient_scope"}A credencial não tem orders:read.
429{"error":"rate_limit_exceeded"}Mais de 600 requisições por minuto. Respeite Retry-After.

Próximos passos

Nesta página