Pincode de coleta — fluxo motorista para loja

Passo a passo do modelo em que a Abbiamo é dona do PIN e o motorista repassa o código ao operador da loja no balcão.

👍

Por que a Abbiamo gera o PIN nesse modelo?

Quando a Abbiamo gera e valida o código, ele fica mais perto da filial — que é quem é dona do pedido e quem precisa garantir que a mercadoria certa saiu pra coleta certa. A transportadora deixa de carregar regras que não são dela: formato do código, quantas tentativas o motorista pode fazer, o que fazer se algo der errado. Tudo isso passa pra Abbiamo, que é o ponto neutro entre filial e transportadora.

Na prática isso significa:

  • A filial enxerga e controla. O operador da loja digita o código no dashboard da Abbiamo — ou em um sistema próprio da filial, via endpoint dedicado, pra quem quer embarcar a validação na interface que o atendente já usa. Em qualquer caminho, o histórico de cada tentativa fica centralizado pra auditoria.
  • Liberações administrativas ficam possíveis. Em casos excepcionais — motorista perdeu o código, app travou, fila grande no balcão — alguém da operação da filial pode forçar a liberação direto pelo dashboard, sem precisar acionar a transportadora. A operação não trava por causa de um caso isolado.
  • A transportadora carrega menos lógica de negócio. Toda a regra do código (geração, formato, política de tentativas, antifraude) fica do lado da Abbiamo. A transportadora só exibe o código que recebeu no app do motorista e aguarda o sinal de destravamento — não decide se o código está certo, nem o que fazer quando o motorista erra.
  • A transportadora recebe menos requisições. A Abbiamo só dispara o webhook de destravamento quando o código confere e o pedido ainda não foi coletado. Códigos errados, limite de tentativas excedido ou pedidos já coletados não chegam na transportadora — o operador recebe o erro direto no dashboard, sem ruído pro parceiro.
  • Mudança de status fica automática. Quando a transportadora responde 200 no destravamento, a Abbiamo transita o pedido pra COLLECTED na hora — não precisa enviar um evento collected separado pra fechar o ciclo.
📘

Quando esse fluxo se aplica?

Este é o fluxo motorista para loja de pincode de coleta, controlado por pickup_verification.pincode_owner = "abbiamo" no webhook Delivery request. A Abbiamo gera o PIN no momento do despacho da entrega pra transportadora e valida localmente quando o operador digita no dashboard. É exigido por filiais que precisam ser a fonte de verdade do PIN — tipicamente por motivos de auditoria, antifraude ou compliance.

Este modelo é opt-in por integração filial × transportadora — os dois lados precisam suportar. Para o fluxo padrão, em que a transportadora gera o PIN, veja Pincode de coleta — fluxo loja para motorista.

Quem valida o quê

AtorResponsabilidade
AbbiamoGera o PIN no momento do despacho da entrega pra transportadora. Envia o PIN pré-gerado no mesmo webhook de despacho. Valida o PIN digitado pelo operador localmente. Pede pra transportadora (síncronamente) destravar o motorista quando o PIN bate.
TransportadoraRecebe o PIN pré-gerado no Delivery request e mostra pro motorista no app dela. Expõe o webhook Pickup pin validation request pra destravar o motorista quando a Abbiamo chamar.
MotoristaRecebe o PIN no app da transportadora e repassa verbalmente ao operador da loja no balcão.
Operador da lojaRecebe o PIN verbalmente do motorista e digita no dashboard da Abbiamo.

Passo a passo

  1. Criação do pedido. A filial cria o pedido pela Orders API. A integração filial × transportadora está configurada pela Abbiamo com pickup_verification.pincode = true e pickup_verification.pincode_owner = "abbiamo". Nesse momento ainda não existe PIN — um pedido pode ter vários envios, e o código é por envio.
  2. Despacho. Quando a Abbiamo decide despachar uma entrega pra transportadora, ela gera um PIN de 4 dígitos único por entrega e persiste. Em seguida, envia o webhook Delivery request pra transportadora com logistic_data.pickup_verification carregando pincode: true, pincode_owner: "abbiamo" e pincode_value com o código de 4 dígitos.
  3. Transportadora exibe o PIN pro motorista. O app do motorista mostra o código recebido em pincode_value junto com o resto da informação de coleta.
  4. Motorista chega na loja. Verbaliza o PIN pro operador no balcão.
  5. Operador digita o PIN no dashboard. A Abbiamo valida o código localmente contra a própria cópia armazenada no momento do despacho.
  6. Abbiamo pede pra transportadora destravar o motorista. Se o PIN bate, a Abbiamo dispara o webhook Pickup pin validation request pra transportadora. Essa chamada é síncrona — a Abbiamo espera a resposta no mesmo HTTP request, com timeout de 5 segundos.
  7. Transportadora destrava o motorista e responde. No mesmo HTTP response, a transportadora responde 200 / driver_unlocked (ou 200 / already_unlocked em retry idempotente). O app do motorista para de bloquear a coleta.
  8. Coleta confirmada. A Abbiamo transita a entrega pra COLLECTED, retorna sucesso pro dashboard, e o operador libera fisicamente o pacote pro motorista.

Se o PIN não bate, o operador vê um erro no dashboard. A transportadora não é chamada, o motorista continua bloqueado e o status da entrega não muda. Se a transportadora responder com 4xx/5xx ou der timeout, o dashboard mostra erro de "transportadora indisponível" e o operador pode tentar de novo ou cair pra um canal manual.

Exemplos de payload

Delivery request da Abbiamo pra transportadora (bloco relevante):

{
  "event_type": "DELIVERY_REQUEST",
  "logistic_data": {
    "pickup_verification": {
      "pincode": true,
      "pincode_owner": "abbiamo",
      "pincode_value": "8745"
    }
  }
}

Webhook síncrono da Abbiamo pra transportadora quando o operador submete o PIN:

O payload espelha os mesmos blocos identificadores que já chegaram no Delivery request original (seller, carrier, identificadores da entrega, logistic_data), pra transportadora conseguir localizar a entrega no sistema dela e reaproveitar contexto recebido no despacho (ex.: um token específico da filial dentro de logistic_data.headers):

{
  "event_type": "PICKUP_PIN_VALIDATION_REQUEST",
  "event_at": "2026-05-12T14:34:17.890Z",
  "seller": {
    "seller_name": "Go Go Fruits",
    "seller_id": "eb064ede-08f3-470e-a37c-5b796a17cca8",
    "seller_document_number": "88399480000156",
    "seller_group_id": "b7d56bca-606e-405e-bf4d-9b0a3291b61d"
  },
  "carrier": {
    "name": "CARRIER_BRAND_NAME",
    "method": {
      "id": "e84b2788-5b78-40dd-95cf-75807f70aaaa",
      "name": "CARRIER_BRAND_NAME_D0",
      "type": "D0"
    }
  },
  "invoice_number": "example_invoice_number_1",
  "delivery_id": "851dc274-e090-4881-8f3c-5b660cecf059",
  "order_number": "example_carrier_payload_1",
  "logistic_data": {
    "headers": {
      "Authorization": "Bearer xxx"
    },
    "pickup_verification": {
      "pincode": true,
      "pincode_owner": "abbiamo",
      "pincode_value": "8745"
    }
  }
}

Resposta esperada da transportadora no mesmo HTTP request:

{
  "code": "driver_unlocked",
  "delivery_id": "851dc274-e090-4881-8f3c-5b660cecf059",
  "unlocked_at": "2026-05-12T14:34:18.014Z",
  "driver": {
    "name": "Carlos Silva",
    "document_number": "12345678900"
  }
}
🚧

Essa chamada é de liberação, não de revalidação

No momento em que a Abbiamo chama a transportadora no passo 6, o PIN já foi validado localmente pela Abbiamo. A transportadora não deve revalidar o pincode_value que aparece dentro de logistic_data.pickup_verification — o único propósito desse endpoint é destravar o motorista no app da transportadora.

O pincode_value aparece aqui só porque o bloco logistic_data inteiro é reenviado por conveniência (pra transportadora reaproveitar qualquer contexto que dependia dele no despacho — tipicamente um token específico da filial dentro de logistic_data.headers). Se a transportadora não precisa desse contexto, pode ignorar tudo além do delivery_id.

Como habilitar esse fluxo

A escolha do modelo é parte do acordo comercial entre filial e transportadora, e é configurada do lado da Abbiamo — a filial não escolhe o modelo por pedido. Para habilitar o fluxo motorista para loja num par filial × transportadora:

  1. A transportadora precisa ler pickup_verification.pincode_value do webhook Delivery request e exibir pro motorista.
  2. A transportadora precisa expor o handler do webhook Pickup pin validation request, respeitando os requisitos de idempotência e timeout de 5 segundos documentados lá.
  3. Ambos os lados acionam o [email protected] pra virar a integração pra pincode_owner = "abbiamo".

Enquanto os dois lados não estiverem prontos, a integração continua no fluxo padrão pincode_owner = "carrier" — sem breaking change.

Erros comuns

  • Transportadora ignora pincode_value e gera o próprio PIN. Nesse modelo, a transportadora deve exibir o pincode_value que recebeu — o operador vai digitar esse código, não o que a transportadora gerou. PINs divergentes aparecem como erro INVALID_PIN no dashboard.
  • Handler da transportadora muito lento no webhook síncrono. O timeout padrão da Abbiamo é 5 segundos. Se a lógica de unlock da transportadora for mais pesada que isso, ela deve responder 200 / driver_unlocked assim que o unlock estiver garantido em commit no banco e completar o resto async.
  • Handler da transportadora não é idempotente. A Abbiamo faz 1 retry em 5xx / timeout. O handler precisa retornar 200 / already_unlocked (sem rodar efeitos colaterais de novo) quando recebe uma segunda chamada pra mesmo delivery_id. A Abbiamo também já bloqueia o disparo do webhook quando a entrega está em COLLECTED (ou qualquer estado terminal posterior) — o operador recebe direto o erro INVALID_DELIVERY_STATUS sem a transportadora ser acionada de novo —, então a janela real de retry concorrente é curta.

Referências relacionadas