Este tutorial cobre o fluxo de liquidação do início ao fim: receber o evento de passagem, criar um pedido, cobrar o cliente e confirmar o pagamento.
Pré-requisito: ambiente configurado conforme o Quickstart.
Quando uma passagem é capturada, a Movvia entrega um webhook no seu endpoint:
{
"evento": "pe.transacao.recebida",
"id": "evt_8f3a1b2c",
"dados": {
"transacaoId": "t_9f2c7e1a",
"placa": "ABC1D23",
"valor": 12.50,
"praca": "KM 245 — Imigrantes",
"criadoEm": "2026-04-24T09:58:00Z"
}
}Armazene o transacaoId para usar na criação do pedido.
Agrupe uma ou mais transações em um pedido. Use uma idempotencyKey única:
curl -X POST "$BASE_URL/pedidos" \
-H "Authorization: Basic $MV_KEY" \
-H "x-parceiro-id: $MV_PARCEIRO_ID" \
-H "Content-Type: application/json" \
-d '{
"transacoes": ["t_9f2c7e1a"],
"idempotencyKey": "ord_20260424_ABC1D23_001"
}'Resposta:
{
"pedidoId": "ped_a1b2c3d4",
"status": "pendente",
"valor": 12.50,
"transacoes": ["t_9f2c7e1a"],
"criadoEm": "2026-04-24T10:00:00Z"
}Armazene o pedidoId antes de prosseguir.
Execute o débito no seu sistema (saldo, pontos, PIX, cartão). Este passo é interno ao seu produto — a Movvia não participa.
Crie o pedido apenas após receber o evento confirmado. Confirme o pedido somente quando a cobrança for bem-sucedida no seu lado.
Após débito bem-sucedido, confirme o pedido:
curl -X POST "$BASE_URL/pedidos/ped_a1b2c3d4/confirmar" \
-H "Authorization: Basic $MV_KEY" \
-H "x-parceiro-id: $MV_PARCEIRO_ID" \
-H "Content-Type: application/json" \
-d '{"idempotencyKey": "conf_ped_a1b2c3d4"}'Resposta:
{
"pedidoId": "ped_a1b2c3d4",
"status": "confirmado",
"confirmadoEm": "2026-04-24T10:05:00Z"
}Se não conseguir cobrar o cliente, cancele o pedido:
curl -X POST "$BASE_URL/pedidos/ped_a1b2c3d4/cancelar" \
-H "Authorization: Basic $MV_KEY" \
-H "x-parceiro-id: $MV_PARCEIRO_ID" \
-H "Content-Type: application/json" \
-d '{"motivo": "falha_cobranca", "idempotencyKey": "canc_ped_a1b2c3d4"}'async function liquidarTransacao(transacaoId: string, placa: string) {
const idempotencyKey = `ord_${Date.now()}_${placa}`;
// Criar pedido
const pedidoRes = await fetch(`${BASE_URL}/pedidos`, {
method: 'POST',
headers: {
'Authorization': `Basic ${process.env.MV_KEY}`,
'x-parceiro-id': process.env.MV_PARCEIRO_ID!,
'Content-Type': 'application/json',
},
body: JSON.stringify({ transacoes: [transacaoId], idempotencyKey }),
});
const pedido = await pedidoRes.json();
// Cobrar cliente (lógica interna do seu produto)
const cobrado = await cobrarCliente(placa, pedido.valor);
if (cobrado) {
// Confirmar
await fetch(`${BASE_URL}/pedidos/${pedido.pedidoId}/confirmar`, {
method: 'POST',
headers: {
'Authorization': `Basic ${process.env.MV_KEY}`,
'x-parceiro-id': process.env.MV_PARCEIRO_ID!,
'Content-Type': 'application/json',
},
body: JSON.stringify({ idempotencyKey: `conf_${pedido.pedidoId}` }),
});
} else {
// Cancelar
await fetch(`${BASE_URL}/pedidos/${pedido.pedidoId}/cancelar`, {
method: 'POST',
headers: {
'Authorization': `Basic ${process.env.MV_KEY}`,
'x-parceiro-id': process.env.MV_PARCEIRO_ID!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
motivo: 'falha_cobranca',
idempotencyKey: `canc_${pedido.pedidoId}`,
}),
});
}
}