External & Carrier Integrations
3 API calls in this section.
Global JSON response contract for every /external/* endpoint:
successis always a boolean.errorisnullfor success and a stablesnake_casecode for failure.messageis always a readable message localized from the request language.Existing endpoint-specific data fields remain unchanged at the top level.
Existing HTTP status codes remain unchanged.
POST /external/deliveries/shipment-labelskeeps its successfulapplication/pdfbinary response so existing downloads continue to work; every JSON error from that endpoint follows this contract.
Frontend integration
branch on HTTP status and error; display message; continue reading existing endpoint-specific payload fields exactly as before.
Global JSON response contract for every /external/* endpoint
{
"success": true,
"error": null,
"message": "Localized readable message"
}Get Shipment Labels
/external/deliveries/shipment-labelsReturns an application/pdf response containing canonical shipment labels for one or multiple deliveries. Use one delivery_codes value for a single shipment and multiple values for a combined PDF.
Authentication and authorization
Requires X-API-Key authentication. Tenant scope comes from the authenticated context. Customer callers may request only their own deliveries; privileged tenant callers may request any delivery in that tenant.
Request
delivery_codes is required and accepts 1-50 non-empty delivery-code strings. Duplicates are removed in first-seen order.
Current-label behavior
Missing, stale, or unreadable labels use guarded generation; unstarted queued jobs can be claimed immediately, while running generation is awaited through the shared single-label lifecycle. Receiver data comes from the delivery's current delivery_location. Each successful generation has a new numeric file version and audit history; older PDF files remain available. A failed reprint preserves the previous URL.
Response
Success is PDF binary with Content-Disposition; errors are localized JSON. Combined PDFs use the private content-addressed cache and do not reuse the previous cache key after a canonical label changes.
Errors
400 invalid body/code or over 50 unique codes; 403 ownership/permission; 404 delivery/tenant not found; 413 byte limit; 422 invalid PDF; 500 lookup/cache/signing/upload errors; 502 label generation/download failure. No partial PDF is returned.
Concurrent printing
Successful labels with a URL are reused. Missing or needs_reprint labels use an atomic shared claim. A queued creation job can be claimed immediately by either foreground printing or its background worker. The atomic delivery-row lock permits only one generator; an unexpired active generator is joined instead of superseded, and delayed background jobs reuse completed labels. Generation and batch polling share a 90-second budget per request, leaving time for PDF merge/upload. Polls fetch pending IDs together. If the budget expires, HTTP 503 with code label_generation_in_progress asks the caller to retry; no partial PDF is returned. A later request may recover an abandoned active claim after 120 seconds; unstarted queued jobs have no grace-period delay. Version checks fence off superseded results. Unreadable-PDF repair explicitly replaces the observed version, and concurrent repairs reuse its replacement. Creation and reprint triggers are unchanged. The external error envelope retains its stable error field; successful responses remain PDF binary.
Headers
| Parameter | Type | Description |
|---|---|---|
X-API-Key | string | Authenticated external API key. Example: |
Content-Type | string | Example: |
Body parameters
| Parameter | Type | Description |
|---|---|---|
delivery_codes | array<string> | — |
1curl --globoff --request POST "https://staging-api.ondi.io/functions/v1/external/deliveries/shipment-labels" \2 --header "X-API-Key: ${ONDI_TENANT_API_KEY}" \3 --header "Content-Type: application/json" \4 --data-raw '{5 "delivery_codes": [6 "2501",7 "2502"8 ]9}'Response examples
1<binary PDF response>Calculate Delivery Price
/external/delivery/priceCalculate delivery price based on pickup and dropoff coordinates. This endpoint is designed for external integrations and accepts latitude/longitude coordinates directly instead of address IDs.
Requires X-API-Key authentication.
Public endpoint accessible to external systems
Pricing Logic
Determines the pickup and dropoff delivery zones from the coordinates
Looks up the applicable zone-pricing rule for the resolved origin/destination pair, including same-zone pairs
Uses the service default price only when no zone rule matches and the effective pricing policy allows fallback
If
warehouse_idprovided, uses warehouse address as pickup locationSupplied units affect the per-unit portion of zone pricing and are no longer replaced by the service maximum
Units must remain within the delivery service
unit_minandunit_maxrangeCurrency is resolved from tenant currency settings, then system currency settings, and falls back to
IQD.Returns error if locations are outside configured delivery zones
Frontend integration contract
Send the intended positive
unitsvalue when quoting a known shipment size; the backend now honors it exactly.Omit
unitsonly when pricing should use the configured missing-unit fallback. Readunit_sizeandunit_size_sourcefrom the success response.Read
currency_codefor the OnDi currency code.Handle HTTP 400
invalid_units_parameterfor zero, negative, non-numeric, or unresolved template values.Handle HTTP 400
can_not_use_this_delivery_for_this_unit_sizeby displaying the localizedmessage; usecalculated_unit_size,allowed_unit_min,allowed_unit_max, andviolationfor context.
Query parameters
| Parameter | Type | Description |
|---|---|---|
delivery_service_idRequired | string | ID of the delivery service to calculate price for (Required) UUID of the delivery service Example: |
pickup_lat | string | Latitude of pickup location (Optional if Example: |
pickup_lng | string | Longitude of pickup location (Optional if Example: |
dropoff_latRequired | string | Latitude of dropoff location (Required, decimal format) Latitude of dropoff location (decimal format, Example: |
dropoff_lngRequired | string | Longitude of dropoff location (Required, decimal format) Longitude of dropoff location (decimal format, Example: |
warehouse_idOptional | string | ID of the warehouse for pickup location (Optional, alternative to Example: |
unitsOptional | string | Number of units for pricing calculation. When provided, this exact positive value is used. When omitted, the configured missing-unit fallback is used (Optional) Positive number of units for pricing. When provided, the API uses that exact value. When omitted, Example: |
tenant_idRequired | string | UUID of the tenant |
Headers
| Parameter | Type | Description |
|---|---|---|
X-API-Key | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/external/delivery/price?delivery_service_id=${DELIVERY_SERVICE_ID}&pickup_lat=${PICKUP_LAT}&pickup_lng=${PICKUP_LNG}&dropoff_lat=${DROPOFF_LAT}&dropoff_lng=${DROPOFF_LNG}&warehouse_id=${WAREHOUSE_ID}&units=${UNITS}" \2 --header "X-API-Key: ${ONDI_TENANT_API_KEY}"Response examples
1{2 "success": true,3 "error": null,4 "message": "Price calculated successfully",5 "price": 15.5,6 "currency_code": "IQD"7}Get Zone by Coordinates
/external/zoneGet the delivery zone that contains the given coordinates. This endpoint uses the get_zone_by_point database function to find which zone contains the specified latitude and longitude.
Requires X-API-Key authentication.
Public endpoint accessible to external systems
Query parameters
| Parameter | Type | Description |
|---|---|---|
latRequired | string | Latitude of the location (Required, decimal format) Latitude of the location (decimal format, Example: |
lngRequired | string | Longitude of the location (Required, decimal format) Longitude of the location (decimal format, Example: |
tenant_idRequired | string | UUID of the tenant |
Headers
| Parameter | Type | Description |
|---|---|---|
X-API-Key | string | Example: |
1curl --globoff --request GET "https://staging-api.ondi.io/functions/v1/external/zone?lat=${LATITUDE}&lng=${LONGITUDE}" \2 --header "X-API-Key: ${ONDI_TENANT_API_KEY}"Response examples
1{2 "success": true,3 "error": null,4 "message": "Zone found successfully",5 "zone": {6 "id": "123e4567-e89b-12d3-a456-426614174000",7 "name": "Downtown Zone",8 "boundaries": {9 "type": "Polygon",10 "coordinates": [11 [12 [13 40.7128,14 -74.00615 ],16 [17 40.72,18 -74.0119 ]20 ]21 ]22 },23 "is_active": true24 }25}