MeuPedido/developer

Autenticação

OAuth client credentials, escopos, expiração de 3600 s, credencial pausada ou revogada e limites do endpoint de token.

A API usa OAuth 2.0 com o fluxo client credentials: o seu sistema troca client_id e client_secret por um token de acesso e envia esse token em todas as chamadas. Não há login de usuário, redirecionamento nem refresh token.

Fluxo de autenticação OAuth client credentialsO seu sistema envia client_id e client_secret para POST /oauth/token e recebe um JWT válido por 3600 segundos. As chamadas seguintes vão com Authorization: Bearer. Quando o token expira, a API responde 401 invalid_token e o seu sistema pede um token novo no mesmo endpoint, sem refresh token.Seu sistemaclient_id mp_…API MeuPedidoapi.meupedido.io/open-delivery1Obter o tokenPOST /oauth/tokengrant_type=client_credentials · client_id · secret200 {"access_token": "eyJ…", "expires_in": 3600}JWT HS256 (merchant_id, client_id, scope). Sem refresh token.2Chamar a APIGET /v1/events:pollingAuthorization: Bearer eyJ…200 [ … ]O mesmo token serve para todas as rotas /v1 por 3600 s.3Token expirouGET /v1/orders/{orderId}Authorization: Bearer eyJ… (expirado)401 {"error": "invalid_token"}Também chega na hora se o lojista pausar ou revogar a credencial.4RenovarPOST /oauth/tokenIgual ao passo 1. Depois, refaça a chamada que recebeu 401.
  • Requisição do seu sistema, sempre por HTTPS
  • Resposta 2xx
  • 401 invalid_token: token expirado ou credencial pausada/revogada
  • Uma credencial atende uma loja; N lojas são N credenciais e N tokens
  1. Seu sistema chama POST /oauth/token com a credencial.
  2. A API responde com um JWT válido por 3600 segundos e os escopos concedidos.
  3. Seu sistema envia o token em Authorization: Bearer em cada chamada.
  4. Antes de o token expirar, seu sistema pede outro.

Obtendo o token

POST https://api.meupedido.io/open-delivery/oauth/token

O caminho POST /v1/oauth/token é um alias e responde igual.

A credencial pode ser enviada de três formas. O formulário é a forma canônica do OAuth 2.0 e a que a maioria das bibliotecas usa por padrão.

Content-Type: application/x-www-form-urlencoded, com os três campos no corpo.

Terminal
curl -X POST https://api.meupedido.io/open-delivery/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=mp_7f3a9c1e5b2d4a6f8e0c1b3d" \
  -d "client_secret=$CLIENT_SECRET"

Qualquer outro Content-Type responde 415.

Resposta

200 OK
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjaGFudF9pZCI6IjZkMmY0YzhhLTFiM2UtNGY1YS05YzdkLTJlOGIwYTFmM2M1ZCIsImNsaWVudF9pZCI6Im1wXzdmM2E5YzFlNWIyZDRhNmY4ZTBjMWIzZCIsInNjb3BlIjoib3JkZXJzOnJlYWQgb3JkZXJzOndyaXRlIG1lcmNoYW50OnJlYWQgY2F0YWxvZzpyZWFkIn0.Q1w7Xy0Yt3cJ5w8NnZK2p9Vb4Ls6Hd1Ff0Rr8Mm3Aa0",
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjaGFudF9pZCI6IjZkMmY0YzhhLTFiM2UtNGY1YS05YzdkLTJlOGIwYTFmM2M1ZCIsImNsaWVudF9pZCI6Im1wXzdmM2E5YzFlNWIyZDRhNmY4ZTBjMWIzZCIsInNjb3BlIjoib3JkZXJzOnJlYWQgb3JkZXJzOndyaXRlIG1lcmNoYW50OnJlYWQgY2F0YWxvZzpyZWFkIn0.Q1w7Xy0Yt3cJ5w8NnZK2p9Vb4Ls6Hd1Ff0Rr8Mm3Aa0",
  "token_type": "bearer",
  "tokenType": "bearer",
  "expires_in": 3600,
  "expiresIn": 3600,
  "scope": "orders:read orders:write merchant:read catalog:read"
}

Cada campo vem em snake_case (como o RFC 6749 define) e em camelCase (como a especificação Open Delivery escreve). Os valores são idênticos; leia o que a sua biblioteca esperar.

CampoSignificado
access_tokenO JWT a enviar em Authorization: Bearer
token_typeSempre bearer
expires_inValidade em segundos, sempre 3600
scopeOs escopos da credencial, separados por espaço

O token é um JWT assinado com HS256 pelo MeuPedido. Ele carrega as claims merchant_id (a loja), client_id e scope. Trate-o como opaco: não dependa do formato interno, e nunca tente validá-lo localmente, porque a chave de assinatura não é pública.

Em código

curl -X POST https://api.meupedido.io/open-delivery/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=$CLIENT_ID" \
  -d "client_secret=$CLIENT_SECRET"

Usando o token

Envie o token no header Authorization de todas as chamadas à API.

Terminal
curl "https://api.meupedido.io/open-delivery/v1/events:polling" \
  -H "Authorization: Bearer $TOKEN"

Sem o header, a resposta é 401 com corpo vazio e o header WWW-Authenticate.

Expiração e renovação

O token vale por 3600 segundos a partir da emissão. Não existe refresh token: renovar é chamar POST /oauth/token de novo.

A estratégia recomendada:

  • Guarde o token junto com o instante de expiração calculado a partir de expires_in.
  • Renove antes de expirar, com uma margem de alguns minutos, em vez de esperar o 401.
  • Se ainda assim uma chamada responder 401, peça um token novo uma vez e repita a chamada. Se o endpoint de token também responder 401 invalid_client, a credencial foi pausada ou revogada: pare e avise o operador.
  • Um token por credencial, compartilhado entre as threads ou workers do seu processo. Pedir um token a cada requisição esgota o limite do endpoint.

Escopos

Os escopos são definidos pelo lojista ao criar a credencial e não podem ser alterados depois. O token carrega exatamente os escopos da credencial.

EscopoLibera
orders:readGET /v1/events:polling, POST /v1/events/acknowledgment, GET /v1/orders/{orderId}
orders:writePOST /v1/orders/{orderId}/confirm e as demais ações
merchant:readGET /v1/merchant/{merchantId}
catalog:readGET /v1/merchant/{merchantId}/menus

Uma chamada a um endpoint cujo escopo a credencial não tem responde:

403 Forbidden
{
  "error": "insufficient_scope",
  "message": "A credencial não possui o escopo orders:write."
}

Credencial pausada ou revogada

O lojista pode pausar, retomar ou revogar a credencial a qualquer momento no painel. O efeito é imediato e vale para tokens já emitidos, mesmo dentro do prazo de validade:

401 Unauthorized
{
  "error": "invalid_token",
  "message": "A credencial foi pausada ou revogada pelo lojista."
}

Com a credencial pausada, os eventos continuam sendo acumulados no feed e ficam disponíveis assim que ela for retomada. Revogação é permanente: para voltar, o lojista cria outra credencial.

Erros do endpoint de token

O endpoint de token responde no formato do RFC 6749: error com um código estável e error_description com o texto em pt-BR. É o formato que toda biblioteca OAuth 2.0 já sabe ler, e por isso é diferente do error e message das demais rotas.

StatuserrorQuando
400unsupported_grant_typegrant_type diferente de client_credentials
400invalid_requestFalta client_id, client_secret ou grant_type, ou o corpo está malformado
401invalid_clientCredencial inexistente, segredo errado, pausada ou revogada
413invalid_requestCorpo acima de 4 KB. Um pedido de token tem só três campos
415invalid_requestContent-Type diferente de formulário ou JSON
429rate_limit_exceededLimite do endpoint atingido; espere o Retry-After
400 Bad Request
{
  "error": "invalid_request",
  "error_description": "Informe client_id e client_secret."
}

O 401 vem só com o código, de propósito. Credencial inexistente e segredo errado recebem exatamente a mesma resposta, para o endpoint não revelar quais client_id existem:

401 Unauthorized
{
  "error": "invalid_client"
}

Limites do endpoint de token

O endpoint de token tem dois limites independentes, ambos respondendo 429 com Retry-After: 60:

  • 60 requisições por minuto por endereço IP. Um único processo bem comportado nunca chega perto disso. O 429 vem com error e message.
  • 10 falhas por minuto por credencial. Se o seu sistema entrar em loop com um segredo errado, ele vai bater neste limite antes de qualquer outro, e o 429 vem com error e error_description. O limite vale só para o segredo errado: o segredo correto continua emitindo token normalmente, então ninguém que conheça apenas o seu client_id consegue derrubar a sua integração.

Os demais endpoints têm o limite geral de 600 requisições por minuto por credencial, descrito em Boas práticas.

Segurança do segredo

  • O client_secret é mostrado uma única vez, ao criar a credencial. Guarde-o em um cofre de segredos ou em variável de ambiente.
  • Nunca o coloque em código, repositório, log, mensagem de erro, URL ou ticket de suporte. O suporte nunca pede o segredo.
  • Use uma credencial por loja e por sistema. Se um segredo vazar, o lojista revoga só aquela credencial.
  • Toda comunicação é HTTPS. Não há endpoint HTTP.
  • CORS está liberado apenas para o playground deste portal. A integração é servidor a servidor: chamar a API a partir de um navegador expõe o segredo e é bloqueado.

Próximos passos

Nesta página