Delivery API Migration
There have been notable changes to the Delivery API to support multiple couriers per delivery and a new requirement for specifying the delivery provider source. This guide outlines how to handle these changes.
Deadline
January 5th, 2026
To meet the January 5th, 2026 deadline, your integration must be updated to use the new providerSource and providerName arguments when assigning a courier through courierAssign, courierEventCreate, courierImagesCreate, and courierTrackingEventCreate.
Migrating to use courierId for mutations courierEventCreate, courierImagesCreate, courierTrackingEventCreate, and courierUnassign is not required for this deadline but is highly recommended as the next step in your integration upgrade.
Action Required by Deadline
The deliveryServiceProvider argument on courierAssign is now deprecated. It has been replaced by two new fields that must be provided within the courier object itself:
providerSource: A required enum (
IN_HOUSEorTHIRD_PARTY) that specifies who is fulfilling the delivery.providerName: The name of the service provider. This is only necessary/required if
providerSourceisTHIRD_PARTY(e.g., "DoorDash", "Uber Direct").
You must send these new arguments when using courierEventCreate, courierImagesCreate, courierTrackingEventCreate, and courierUnassign.
A Note on Changes
To assist with the January 5th, 2026 deadline, the new providerSource and providerName arguments have also been added to the CourierInput object.
This was done to support integrations that have not yet migrated away from the deprecated inline courier assignment (i.e., you are still passing the courier object to courierEventCreate, courierImagesCreate, courierTrackingEventCreate, and courierUnassign.
This change allows you to pass the new required providerSource and providerName arguments through the deprecated courier argument, enabling you to meet the deadline without immediately refactoring for the Recommended Next Steps.
Examples
Migrating a courierAssign Call
This example shows the specific change required to meet the deadline.
Before
{
"input": {
"courier": {
"id": "your-courier-id",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+16175551234"
},
"deliveryId": "ezcater-delivery-id",
"deliveryServiceProvider": "DoorDash"
}
}
After
{
"input": {
"courier": {
"id": "your-courier-id",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+16175551234",
"providerName": "DoorDash",
"providerSource": "THIRD_PARTY",
},
"deliveryId": "ezcater-delivery-id"
}
}
Note: deliverySericeProvider is removed and providerName and providerSource is added inside the courier object
Meeting the Deadline with courierEventCreate (Deprecated Flow)
{
"input": {
"courier": {
"id": "your-courier-id",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+16175551234",
"providerSource": "IN_HOUSE"
},
"deliveryId": "ezcater-delivery-id",
"eventType": "PICKED_UP",
"occurredAt": "2025-11-01T22:03:03Z"
}
}
While this path provides a bridge to compliance, we strongly recommend prioritizing the migration to the two-step process (only assigning couriers through courierAssign or couriersAssign) as outlined in the Recommended Next Steps.
Recommended Next Steps
Migrating to courierId
This migration is not required for the January 5th, 2026 deadline but is the next step to fully modernize your integration.
Passing the courier object to mutations courierEventCreate, courierImagesCreate, courierTrackingEventCreate, and courierUnassign will not be allowed in the near future. This means a courier must be created and assigned to a delivery before you can reference them in other operations.
New Two-Step Process
Your integration must eventually be updated to follow this two-step process:
Assign Courier(s): Use
courierAssignorcouriersAssignto create/update and assign the courier(s) to the delivery.Perform Action: Use the
courierIdfrom the prior step to call other mutations.
All courier creation, updates, and assignments are being centralized to courierAssign and couriersAssign.
couriersAssign (The New Standard)
The new couriersAssign mutation is the standard for managing assignments.
Behavior: It accepts a list of CourierAssignmentInput objects.
Use Case: Use this to set or overwrite the complete list of couriers. To remove all couriers, pass an empty list.
Assigning Two couriers With couriersAssign
{
"input": {
"couriers": [
{
"id": "courier-id-1",
"firstName": "Jane",
"lastName": "Doe",
"phone": "+16175551234",
"providerSource": "IN_HOUSE"
},
{
"id": "courier-id-2",
"firstName": "John",
"lastName": "Smith",
"phone": "+16175555678",
"providerSource": "THIRD_PARTY",
"providerName": "DoorDash"
}
],
"deliveryId": "ezcater-delivery-id"
}
}
courierAssign (Transition Mutation)
The existing courierAssign mutation is being phased out but has been updated to help you transition.
We've added a new optional boolean argument, allowMultipleCouriers. This is an opt-in flag for new behavior.
Legacy Behavior (omitted or
false): The mutation replaces all existing couriers with the single courier provided.New Behavior (
true): The mutation adds the provided courier to the delivery's existing list of assignments without removing others.
Once your application is ready to support multiple couriers, you should always pass true for allowMultipleCouriers.
Handling New Error Responses
Migrating to the courierId argument introduces stricter validation and new potential errors. These errors will only happen when using the new courierId argument.
Error Cases
Courier Does Not Exist
If the courier for the provided courierId does not exist, the mutation will fail.
{
"errors": [
{
"message": "Courier not found",
"path": [
"courierEventCreate"
],
"extensions": {
"type": "request",
"statusCode": 404,
"serviceName": "delivery-public",
"code": "DOWNSTREAM_SERVICE_ERROR",
"exception": {
"message": "Courier not found",
"locations": [
{
"line": 1,
"column": 72
}
],
"path": [
"courierEventCreate"
]
}
}
}
],
"data": {
"courierEventCreate": null
}
}
Courier Is Not Assigned
If the courier exists but has not been assigned to the specified deliveryId, the mutation will fail.
{
"errors": [
{
"message": "Courier assignment not found",
"path": [
"courierEventCreate"
],
"extensions": {
"type": "request",
"statusCode": 404,
"serviceName": "delivery-public",
"code": "DOWNSTREAM_SERVICE_ERROR",
"exception": {
"message": "Courier assignment not found",
"locations": [
{
"line": 1,
"column": 72
}
],
"path": [
"courierEventCreate"
]
}
}
}
],
"data": {
"courierEventCreate": null
}
}