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
| Actor | Responsibility |
|---|---|
| Abbiamo | Generates 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. |
| Carrier | Receives 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. |
| Driver | Receives the PIN from the carrier's app and tells it to the store operator at the counter. |
| Store operator | Receives the PIN verbally from the driver and types it into the Abbiamo dashboard. |
Step-by-step
- Order creation. The shipper creates a delivery through the Orders API. The shipper × carrier integration is configured by Abbiamo with
pickup_verification.pincode = trueandpickup_verification.pincode_owner = "abbiamo". Abbiamo generates a 4-digit PIN and persists it on the delivery. - Dispatch. Abbiamo sends the Delivery request webhook to the carrier. The
logistic_data.pickup_verificationblock carriespincode: true,pincode_owner: "abbiamo"andpincode_valuecontaining the 4-digit code. - Carrier displays the PIN to the driver. The driver's app shows the code received in
pincode_valuealong with the rest of the pickup information. - Driver arrives at the store. Verbalizes the PIN to the operator at the counter.
- Operator types the PIN in the dashboard. Abbiamo validates the code locally against its own copy stored at order creation.
- 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.
- Carrier unlocks the driver and responds. On the same HTTP response, the carrier replies
200 / driver_unlocked(or200 / already_unlockedfor an idempotent retry). The driver's app stops blocking the collection. - 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:
- The carrier must support reading
pickup_verification.pincode_valuefrom the Delivery request webhook and showing it to the driver. - The carrier must expose the Pickup pin validation request webhook handler, honoring the idempotency and 5-second timeout requirements documented there.
- 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_valueand generates its own PIN. In this model the carrier must display thepincode_valueit received — the operator will type that code, not whatever the carrier generated. Mismatched PINs surface asINVALID_PINerrors 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_unlockedas 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 return200 / already_unlocked(without re-running side effects) when it receives a second call for the samedelivery_id.