Ações e idempotência
confirm, startPreparation, readyForPickup, dispatch, pickedUp, delivered e requestCancellation, com Idempotency-Key e as respostas 202, 404, 409 e 422.
Ações são as chamadas que movem o pedido pelo ciclo de vida. Todas são POST /v1/orders/{orderId}/{ação}, exigem o escopo orders:write e, com exceção de requestCancellation, não têm corpo.
Uma ação pela API percorre exatamente as mesmas regras que um clique no painel: mesma validação, mesmo histórico, mesmos efeitos (impressão, notificação ao cliente, entregador). O ator fica registrado como a sua credencial.
As ações
| Ação | Situação resultante | Evento emitido | Uso |
|---|---|---|---|
POST /v1/orders/{orderId}/confirm | ACCEPTED | CONFIRMED | A loja aceitou o pedido. |
POST /v1/orders/{orderId}/startPreparation Extensão MeuPedido | PREPARING | PREPARING | A cozinha começou. Opcional. |
POST /v1/orders/{orderId}/readyForPickup | READY | READY_FOR_PICKUP | Pronto para sair ou para o cliente retirar. |
POST /v1/orders/{orderId}/dispatch | DELIVERY | DISPATCHED | Saiu para entrega. Só pedido DELIVERY. |
POST /v1/orders/{orderId}/pickedUp Extensão MeuPedido | DONE | CONCLUDED | O cliente retirou. Encerra o pedido. |
POST /v1/orders/{orderId}/delivered | DONE | CONCLUDED | Entregue. Encerra o pedido. |
POST /v1/orders/{orderId}/requestCancellation | CANCELLED | CANCELLED | Cancela imediatamente. Aceita corpo opcional. |
pickedUp e delivered levam à mesma situação: para a loja, os dois significam pedido encerrado. Use o que descreve o que aconteceu.
Exemplo: confirmar um pedido
curl -X POST "https://api.meupedido.io/open-delivery/v1/orders/3f8a1c2d-5b6e-4f7a-9c8d-1e2f3a4b5c6d/confirm" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Idempotency-Key: confirm-3f8a1c2d-5b6e-4f7a-9c8d-1e2f3a4b5c6d"{ "status": "accepted", "situation": "ACCEPTED" }Respostas
Toda ação responde com um dos quatro resultados abaixo.
| Status | Corpo | Significado |
|---|---|---|
202 | {"status":"accepted","situation":"ACCEPTED"} | A transição foi aplicada. situation é a situação nova. |
202 | {"status":"already_applied","situation":"ACCEPTED"} | O pedido já estava nessa situação. Nada mudou e nenhum evento foi emitido. |
404 | {"error":"order_not_found","message":"..."} | O pedido não existe ou não pertence à loja da credencial. |
422 | {"error":"invalid_transition","message":"..."} | A transição não é permitida a partir da situação atual. message explica em português. |
already_applied é 202, e não erro, de propósito: o caso real é um comando reenviado depois de um timeout. Tratar isso como falha faria o seu sistema mostrar erro em uma operação que já está feita.
Um orderId que não é um GUID também responde 404, no formato ProblemDetails (type, title, status, traceId).
{
"error": "invalid_transition",
"message": "Pedido encerrado não pode ser cancelado."
}Exemplos de 422: dispatch em pedido INDOOR, requestCancellation em pedido DONE, qualquer ação em pedido CANCELLED.
Cancelar
requestCancellation é a única ação com corpo, e o corpo é opcional:
curl -X POST "https://api.meupedido.io/open-delivery/v1/orders/3f8a1c2d-5b6e-4f7a-9c8d-1e2f3a4b5c6d/requestCancellation" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "reason": "Produto em falta.", "code": "OTHER_CANCELLATION_REASON" }'{ "status": "accepted", "situation": "CANCELLED" }| Campo | Tipo | Descrição |
|---|---|---|
reason | string, opcional | Motivo registrado no histórico do pedido e enviado ao lojista. Padrão: "Cancelamento solicitado pela API pública.". |
code | string, opcional | Aceito por compatibilidade com o padrão e ignorado. O code do evento CANCELLED é derivado de quem cancelou, não deste campo. |
O cancelamento é imediato: não existe uma etapa de aprovação, e o evento CANCELLED sai com metadata.reason igual ao motivo informado. Cancelar um pedido DONE responde 422.
Sem corpo também funciona
Enviar requestCancellation sem corpo e sem Content-Type cancela com o motivo padrão.
Idempotência
Comandos de mudança de estado não são seguros de repetir por natureza, e a rede repete: um timeout do seu lado não diz se a ação foi aplicada. O cabeçalho opcional Idempotency-Key resolve isso.
POST /v1/orders/3f8a1c2d-5b6e-4f7a-9c8d-1e2f3a4b5c6d/dispatch
Authorization: Bearer {access_token}
Idempotency-Key: 2c0f6b3a-8e1d-4a9b-b7c5-0d4e8f1a2b3cComo funciona:
- A chave é qualquer string escolhida por você, única por credencial. Um UUID por tentativa lógica, ou um valor derivado como
dispatch-{orderId}, funcionam. - Mesma chave, mesma requisição (mesma rota, mesma ação, mesmo corpo): a API devolve a resposta gravada na primeira vez, com o mesmo status e o mesmo corpo, sem executar de novo. Vale por 24 horas.
- Mesma chave, requisição diferente:
409 {"error":"idempotency_key_reuse","message":"..."}. Nada é executado. - Respostas
202,404e422são gravadas. Erros5xxnão são, para que a repetição execute de verdade.
{
"error": "idempotency_key_reuse",
"message": "Esta chave de idempotência já foi usada com outro conteúdo."
}Mesmo sem Idempotency-Key, repetir uma ação já aplicada devolve already_applied e não muda nada. A chave acrescenta uma garantia a mais: a resposta exata da primeira execução, útil quando a situação do pedido já avançou por outro caminho entre a primeira tentativa e a repetição.
Boas práticas
- Envie
Idempotency-Keyem toda ação. Custa um cabeçalho e elimina uma classe inteira de bugs de rede. - Em timeout, repita com a mesma chave. Nunca gere chave nova para a mesma intenção.
- Antes de avançar, confira a situação atual em
GET /v1/orders/{orderId}se o seu sistema pode ter ficado para trás (por exemplo, o operador avançou o pedido no painel). - Trate
422como bug de fluxo ou disputa com o painel, e não como erro transitório: repetir não resolve.
Próximos passos
- Ciclo de vida do pedido: a máquina de estados que define quais ações são válidas.
- Catálogo de eventos: o que cada ação emite no feed.
- Boas práticas: limites, erros gerais e backoff.