Pickup pincode — driver-to-seller flow

Step-by-step for the pickup pincode model where Abbiamo owns the PIN and the driver passes it to the store operator at the counter.

This is the driver-to-seller pickup pincode flow, controlled by pickup_verification.pincode_owner = "abbiamo" in the Delivery request webhook. Abbiamo generates the PIN at order creation and validates it locally when the operator types it in the dashboard. It is required by shippers that need to be the source of truth for the PIN — typically for audit, fraud prevention or regulatory reasons.

This model is opt-in per shipper × carrier integration — both sides must support it. For the default flow where the carrier generates the PIN, see Pickup pincode — seller-to-driver flow.

Who validates what

ActorResponsibility
AbbiamoGenerates the PIN at order creation. Sends the PIN pre-generated to the carrier. Validates the PIN typed by the operator locally. Asks the carrier (synchronously) to unlock the driver once the PIN matches.
CarrierReceives the PIN pre-generated in the Delivery request and shows it to the driver in its own app. Exposes the Pickup pin validation request webhook to unlock the driver when Abbiamo calls.
DriverReceives the PIN from the carrier's app and tells it to the store operator at the counter.
Store operatorReceives the PIN verbally from the driver and types it into the Abbiamo dashboard.

Step-by-step

  1. Order creation. The shipper creates a delivery through the Orders API. The shipper × carrier integration is configured by Abbiamo with pickup_verification.pincode = true and pickup_verification.pincode_owner = "abbiamo". Abbiamo generates a 4-digit PIN and persists it on the delivery.
  2. Dispatch. Abbiamo sends the Delivery request webhook to the carrier. The logistic_data.pickup_verification block carries pincode: true, pincode_owner: "abbiamo" and pincode_value containing the 4-digit code.
  3. Carrier displays the PIN to the driver. The driver's app shows the code received in pincode_value along with the rest of the pickup information.
  4. Driver arrives at the store. Verbalizes the PIN to the operator at the counter.
  5. Operator types the PIN in the dashboard. Abbiamo validates the code locally against its own copy stored at order creation.
  6. Abbiamo asks the carrier to unlock the driver. If the PIN matches, Abbiamo fires the Pickup pin validation request webhook to the carrier. This call is synchronous — Abbiamo waits for the carrier's response on the same HTTP request, with a 5-second timeout.
  7. Carrier unlocks the driver and responds. On the same HTTP response, the carrier replies 200 / driver_unlocked (or 200 / already_unlocked for an idempotent retry). The driver's app stops blocking the collection.
  8. Collection confirmed. Abbiamo transitions the delivery to COLLECTED, returns success to the dashboard, and the operator physically releases the package to the driver.

If the PIN does not match, the operator sees an error in the dashboard. The carrier is not called, the driver stays blocked, and the delivery status does not change. If the carrier responds with a 4xx/5xx or times out, the dashboard surfaces a "carrier unavailable" error and the operator can retry or fall back to a manual channel.

Example payloads

Delivery request from Abbiamo to the carrier (relevant block only):

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

Synchronous webhook from Abbiamo to the carrier when the operator submits the PIN:

{
  "event_type": "PICKUP_PIN_VALIDATION_REQUEST",
  "event_at": "2026-05-12T14:34:17.890Z",
  "delivery_id": "851dc274-e090-4881-8f3c-5b660cecf059"
}

Expected response from the carrier on the same HTTP request:

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

By the time Abbiamo calls the carrier on step 6, the PIN has already been validated locally. The carrier only receives the delivery_id and is expected to unlock the driver based on that. Sending the PIN again on this call would duplicate the source of truth.

Enabling this flow

The choice of model is part of the commercial agreement between shipper and carrier, and is configured on the Abbiamo side — the shipper does not pick the model per-order. To enable the driver-to-seller flow for a given shipper × carrier pair:

  1. The carrier must support reading pickup_verification.pincode_value from the Delivery request webhook and showing it to the driver.
  2. The carrier must expose the Pickup pin validation request webhook handler, honoring the idempotency and 5-second timeout requirements documented there.
  3. Both sides reach out to carrier@abbiamolog.com to flip the integration to pincode_owner = "abbiamo".

Until both sides are ready, the integration stays on the default pincode_owner = "carrier" flow — no breaking change.

Common pitfalls

  • Carrier ignores pincode_value and generates its own PIN. In this model the carrier must display the pincode_value it received — the operator will type that code, not whatever the carrier generated. Mismatched PINs surface as INVALID_PIN errors in the dashboard.
  • Carrier handler is too slow on the synchronous webhook. The default Abbiamo timeout is 5 seconds. If the carrier's unlock logic is heavier than that, it should respond 200 / driver_unlocked as soon as the unlock is committed in its database and complete the rest of the work asynchronously.
  • Carrier handler is not idempotent. Abbiamo retries once on 5xx / timeout. The carrier handler must return 200 / already_unlocked (without re-running side effects) when it receives a second call for the same delivery_id.

Nesta página