Fix or reassign a shipment

Updated May 31, 20263 min read

When a shipment lands in error, re-book it with POST /shipments/{shipment_id}/reprocess. The same endpoint covers both common fixes: correct the data the error points to, or move the shipment to a different carrier account. Reprocess applies your change as a partial update and re-submits the booking.

Resolving errors is usually easiest in the Carriyo Dashboard, where an operator sees the error, corrects it, and reprocesses in a few clicks, see Resolve shipment errors. Use this API path when you want to automate it.

Scenario

Two situations leave a shipment in error, both fixable with reprocess:

  • A data problem. A Carriyo or carrier validation flags a field, for example an invalid phone number on the dropoff. Correct the field and reprocess.
  • A carrier problem. Carriyo's rules couldn't assign a carrier (no_carrier_assigned), or the assigned carrier rejected the booking. Move it to a different carrier account and reprocess.

Prerequisites

  • API credentials: see Getting started.
  • A shipment in a reprocess-eligible status (most commonly error).
  • For a carrier change, the carrier_id of the carrier account you want (a UUID).

Step 1, read the error

Read post_shipping_info.error_details to see what failed, from the error webhook (see Book a shipment) or by fetching the shipment:

curl 'https://api.carriyo.com/shipments/MPRD8K2NXVABE2' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'tenant-id: YOUR_TENANT_ID' \
  -H 'x-api-key: YOUR_API_KEY'
{
  "shipment_id": "MPRD8K2NXVABE2",
  "post_shipping_info": {
    "status": "error",
    "error_details": [
      {
        "level": "ERROR",
        "trigger": "BOOKING",
        "source": "CARRIYO",
        "type": "VALIDATION",
        "message": "The Phone number provided '212-555-0100' is invalid. Please use a valid phone number and reprocess booking again.",
        "code": "phone_number_invalid",
        "field": "dropoff.contact_phone"
      }
    ]
  },
  "...": "(other fields elided)"
}

The field tells you what to send back corrected. (code meanings are in Error codes.)

Step 2, reprocess with your fix

reprocess is a POST with the action in the path. Its body is a partial update: include a top-level field to replace it, omit it to leave it unchanged, or set it to null to clear it (custom attributes are the exception: they merge key-by-key). An included object is replaced as a whole, so send the complete object. The call moves the shipment to pending and re-submits the booking. Send only what the error needs, pick the case that matches.

Fix the data

The error above points at dropoff.contact_phone. Because an included object is replaced wholesale, send the entire dropoff with the corrected phone, not just the phone:

curl -X POST 'https://api.carriyo.com/shipments/MPRD8K2NXVABE2/reprocess' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'tenant-id: YOUR_TENANT_ID' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "dropoff": {
      "address1": "350 5th Avenue",
      "city": "New York",
      "state": "NY",
      "country": "US",
      "postcode": "10118",
      "contact_name": "Alex Chen",
      "contact_phone": "+12125550100"
    }
  }'

Reassign the carrier

If the problem is the carrier, a rejection or no_carrier_assigned, pass carrier_account.carrier_id set to the account you want:

curl -X POST 'https://api.carriyo.com/shipments/MPRD8K2NXVABE2/reprocess' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'tenant-id: YOUR_TENANT_ID' \
  -H 'x-api-key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "carrier_account": {
      "carrier_id": "a72f1b90-5e3d-4c2a-9f10-2b7c6e4d8a31"
    }
  }'

Naming an account skips the shipping rules: Carriyo books with that account and won't fall through to another if it can't serve the shipment. To let the rules pick again instead, reprocess without carrier_account.

Step 3, read the outcome

Reprocess returns the shipment in pending, the booking is re-submitted but not yet accepted:

{
  "shipment_id": "MPRD8K2NXVABE2",
  "post_shipping_info": {
    "status": "pending",
    "key_milestones": {}
  },
  "...": "(other fields elided)"
}

It then resolves asynchronously, pendingbooked (tracking number and label attached) or pendingerror (still failing, read error_details and try again). Catch the outcome on the same booked / error webhook you use for new bookings, see Book a shipment.

Eligible statuses

Reprocess covers more than error: booked, ready_to_ship, error, cancelled, cancelled_by_carrier, out_for_collection, failed_collection_attempt, ready_for_return, return_in_transit, and returned. A terminal status like delivered returns a 400. To re-book a draft, use Draft then confirm instead, confirm handles draft and error.

Pitfalls

  • Send the whole object you're changing. Top-level fields you include are replaced wholesale, so a dropoff carrying only the phone would blank the rest of the address. Send the complete object; use null only to clear a field deliberately.
  • It's carrier_account.carrier_id, not carrier_account_id. On the shipment you name the account under carrier_account.carrier_id (a UUID), even though the carrier account's own field is carrier_account_id. A legacy quirk that's easy to get wrong.
  • A named carrier account has no fallback. Reprocess with a specific carrier_account skips the rules; if that account can't serve the shipment it fails to error rather than rerouting.