Reverse Movement — Drop Off Parts to Crash Claim HQ (leg 2 of 2)
Completes a return trip started in 02-pickup-parts-from-repair-shop.md. No separate search step — the driver reaches this screen when Parts_search_details with movement_type: "reverse" returns stage: "dropoff".
Endpoint
Same shared endpoint as every doc in this spec:
- Dev:
https://www.zohoapis.com.au/creator/custom/clientportal/Mobile_Kratos_Incoming_handler_DEV?publickey=xxxxxxxxxxxxxxxxxxxx - Method: POST
Step 1 — Upload Image (per part) — two calls
Same two-call staging flow as every other doc — see 01-drop-off-parts-to-repair-shop.md §Step 2 for the full field list, response shapes, and why it's just a temporary holding spot. Only difference here: Movement_Stage: "reverse_dropoff". The photo is copied out of this staging record into Deliver_Parts.Delivery_Image in Step 2 below — it is never the final home for the image.
Call 1a — parts_movement_upload_token
{
"payload": {
"event_type": "parts_movement_upload_token",
"Parts_Order": "10875000024191015",
"Movement_Stage": "reverse_dropoff",
"rego": "TN42AU6373",
"user_email": "user@email.com"
}
}
Returns record_id (= the image_id for Step 2), token, and the app/report/field link names.
Call 1b — attach the file
POST https://www.zohoapis.com.au/creator/v2.1/data/{app_owner}/{app_name}/report/{report_name}/{record_id}/{field_name}/upload
Authorization: Zoho-oauthtoken <token from 1a>
Content-Type: multipart/form-data
file: <binary>
Step 2 — parts_drop_off_reverse
Payload
{
"payload": {
"event_type": "parts_drop_off_reverse",
"user_email": "user@email.com",
"details": {
"rego": "TN42AU6373",
"parts_movement_id": "10875000030318111",
"delivery_location": "",
"movement_type": "reverse",
"parts": [
{ "parts_order_id": "10875000024189993", "confirm": true, "image_id": "10875000030314834" }
]
}
}
}
| Field | Required | Notes |
|---|---|---|
rego | ✓ | Claim is resolved server-side — no claim_id is sent |
parts_movement_id | ✓ | From the search response (stage: "dropoff"), or from leg 1's submission response |
movement_type | ✓ | "reverse" |
delivery_location | — | Sent as an empty string; HQ is derived server-side |
parts[] | ✓ | The parts belonging to that movement's Deliver_Parts. image_id is record_id from Step 1's Call 1a |
Business logic
- Load
Parts_Movementbyparts_movement_id— must haveMovement_Status == "Parts Picked Up". - For each confirmed part: find the existing
Deliver_Partsrecord created in leg 1 (byParts_Order+Parts_Movement), setDelivery = true. Look up the staged row inParts_Uploaded_Imagesbyimage_id, then copy itsParts_Imageinto that sameDeliver_Partsrecord'sDelivery_Imagefield — this is an update to the record leg 1 already created, not a newDeliver_Partsrow. UpdateParts_Order.Status:Picked Up from Repair Shop → Delivered Back to HQ. - Update
Parts_Movement:Movement_Status = "Parts Dropped off",Dropped_Of_By,Dropped_Off_Date_Time,Dropped_Off_Location_Type = HQ. - Post the Cliq "Parts Delivered" announcement server-side; remove the earlier pickup thread from the channel.
- Once copied, the staging row in
Parts_Uploaded_Imagesis no longer needed — safe to delete or leave for audit, at the Creator side's discretion.
Response
{
"result": {
"data": {
"delivery_parts": [
{
"parts_order_id": 10875000024189993,
"delivery_id": 10875000030318113
},
{
"parts_order_id": 10875000024191015,
"delivery_id": 10875000030318117
}
],
"parts_movement_id": 10875000030318111
},
"status": "success"
},
"code": 3000
}
The delivery_ids are the same Deliver_Parts records leg 1 returned — this leg updates them, it does not create new ones.
Error cases
| Condition | result.text |
|---|---|
parts_movement_id not found, or not "Parts Picked Up" | "This return trip has already been completed or does not exist." |
No parts have confirm: true | "Select at least one part to drop off." |
A confirmed part has no matching image_id | "<Part No.> is missing its drop-off photo." |
Trip complete — no further mobile call needed for this movement.