The MVMNT API strongly encourages using PATCH requests for updating resources. Partial updates allow you to modify only specific fields without sending the entire resource payload.
- Reduced Payload Size - Only send the fields you want to change
- Better Performance - Less data transfer and faster processing
- Avoid Overwrites - Don't accidentally clear fields you didn't mean to change
- Concurrent Safety - Multiple clients can update different fields without conflicts
- Simpler Code - No need to fetch full resource before updating
While the API technically supports PUT for full resource replacement, we strongly discourage this approach because:
- Risk of data loss if you omit fields
- Larger payloads
- Higher chance of concurrent update conflicts
- Requires fetching the full resource first
Always use PATCH for updates unless you have a specific reason not to.
With PATCH, you only include the fields you want to update. All other fields remain unchanged.
Understanding how PATCH handles different field scenarios:
| Scenario | Behavior | Example |
|---|---|---|
| Field omitted | Not modified (current value preserved) | Request doesn't include externalNotes → field stays unchanged |
| Field provided with value | Updated to the new value | "status": "booked" → field updates to "booked" |
| Field set to null | Cleared (set to null) where nullable | "externalNotes": null → field cleared |
Key Principle: Only send what you want to change. Everything else stays as-is.
PATCH /v1/orders/ORD-12345
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"status": "booked"
}Only the status field is updated. All other fields (stops, freight, charges, notes, etc.) remain exactly as they were.
PATCH /v1/orders/ORD-12345
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
{
"status": "in_transit",
"externalNotes": "Driver called - ETA 2pm",
"key": "ERP-ORD-789"
}Only status, externalNotes, and key are updated.
Providing a value replaces the existing value:
{
"externalNotes": "New notes"
}Result: externalNotes is now "New notes" (previous value is replaced)
To clear a nullable field, explicitly set it to null:
{
"externalNotes": null
}Result: externalNotes is now null
Omitting a field does NOT clear it - it remains unchanged:
{
"status": "booked"
// externalNotes is NOT included, so it stays as-is
}For nested objects, you can update individual fields within the object:
PATCH /v1/orders/ORD-12345
{
"freight": {
"weight": 16000,
"commodityDescription": "Updated description"
}
}Behavior: Only the specified fields within freight are updated. Other freight fields (handlingUnits, handlingUnitType, etc.) remain unchanged.
For array fields, the entire array is replaced:
PATCH /v1/orders/ORD-12345
{
"charges": [
{
"chargeCodeId": "550e8400-e29b-41d4-a716-446655440000",
"amount": 1500.00,
"description": "Updated linehaul"
}
]
}Behavior: The charges array is completely replaced with the new array. Previous charges are removed.
To preserve existing items, you must include them in the update:
- Fetch the current resource (GET)
- Modify the array in your application
- Send the complete modified array in PATCH
Use Case: Change order status after booking
curl -X PATCH https://api.mvmnt.io/v1/orders/ORD-12345 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "booked"}'Use Case: Update shipment with tracking and ETA
curl -X PATCH https://api.mvmnt.io/v1/shipments/SHP-67890 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"trackingNumber": "TRK-ABC123",
"estimatedDelivery": "2025-01-22T14:00:00Z"
}'Use Case: Remove external notes
curl -X PATCH https://api.mvmnt.io/v1/orders/ORD-12345 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"externalNotes": null}'Use Case: Update freight weight without changing other freight details
curl -X PATCH https://api.mvmnt.io/v1/orders/ORD-12345 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"freight": {
"weight": 18000
}
}'Use Case: Associate MVMNT order with your system's ID
curl -X PATCH https://api.mvmnt.io/v1/orders/ORD-12345 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"key": "MY-SYSTEM-ID-789"}'async function updateOrder(orderId, updates) {
const response = await fetch(`https://api.mvmnt.io/v1/orders/${orderId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(updates),
});
if (!response.ok) {
throw new Error(`Update failed: ${response.statusText}`);
}
return response.json();
}
// Usage - update only status
await updateOrder('ORD-12345', {
status: 'booked'
});
// Usage - update multiple fields
await updateOrder('ORD-12345', {
status: 'in_transit',
externalNotes: 'Driver confirmed pickup',
key: 'ERP-12345'
});import requests
def update_order(order_id: str, updates: dict) -> dict:
response = requests.patch(
f'https://api.mvmnt.io/v1/orders/{order_id}',
headers={
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json',
},
json=updates
)
response.raise_for_status()
return response.json()
# Usage - update only status
update_order('ORD-12345', {
'status': 'booked'
})
# Usage - update multiple fields
update_order('ORD-12345', {
'status': 'in_transit',
'externalNotes': 'Driver confirmed pickup',
'key': 'ERP-12345'
})PATCH requests are validated the same as POST/PUT requests:
- Required fields (for creation) are NOT required in PATCH
- Field types must match schema (string, number, boolean, etc.)
- Enum values must be valid (e.g.,
statusmust be one of the allowed values) - References must exist (e.g.,
locationIdmust reference a valid location)
PATCH /v1/orders/ORD-12345
{
"status": "invalid_status"
}Response: 400 Bad Request
{
"error": "validation_error",
"message": "Invalid field values",
"details": [
{
"field": "status",
"message": "Must be one of: draft, quoted, booked, dispatched, in_transit, delivered, canceled"
}
]
}Successful PATCH requests return the full updated resource:
Request:
PATCH /v1/orders/ORD-12345
{
"status": "booked"
}Response: 200 OK
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"friendlyId": "ORD-12345",
"status": "booked",
"organizationId": "org_abc123",
"key": "ERP-12345",
"stops": [...],
"freight": {...},
"charges": [...],
"totalRevenue": 1500.00,
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T14:30:00Z"
}Note that updatedAt is automatically set to the current timestamp.
Partial updates help reduce concurrency conflicts, but conflicts can still occur:
We plan to support optimistic locking using an etag or version field:
PATCH /v1/orders/ORD-12345
If-Match: "version-123"
{
"status": "booked"
}If another client updated the resource since you fetched it, you'll receive:
Response: 412 Precondition Failed
{
"error": "precondition_failed",
"message": "Resource was modified by another request",
"currentVersion": "version-124"
}Solution: Re-fetch the resource, reapply your changes, and retry.
Note: This feature is planned for a future release. Currently, last-write-wins.
- Use PATCH for all updates (not PUT)
- Only include fields you want to change
- Include
keywhen updating if you track entities in your system - Validate before sending to avoid unnecessary API calls
- Handle validation errors gracefully
- Don't use PUT unless you truly need full replacement
- Don't fetch-then-update unless necessary (e.g., for arrays)
- Don't send unchanged fields (wastes bandwidth)
- Don't assume PATCH semantics for arrays (arrays are replaced entirely)
Problem: Field values aren't changing
Solutions:
- Verify the field name matches the schema exactly (case-sensitive)
- Check that you're sending valid JSON
- Ensure
Content-Type: application/jsonheader is set - Verify the field is writable (some fields are read-only)
Problem: Existing array items are removed
Explanation: This is expected behavior - arrays are replaced entirely in PATCH requests.
Solution: To preserve existing items, include them in your update payload.
Problem: Cannot update certain fields
Example:
{
"error": "validation_error",
"details": [
{
"field": "id",
"message": "This field is read-only"
}
]
}Solution: Remove read-only fields from your update payload. Common read-only fields:
idfriendlyIdcreatedAtorganizationId
- API Reference - See which fields are updatable for each resource
- Error Handling - Learn how to handle validation errors
- Using Client Keys - Track your system's IDs in MVMNT