Contract reference
| Identity | Value |
|---|---|
| Contract name | FleetBridge Standard Delivery Provider API |
| API major | v1 |
| Semantic contract version | 1.1.0 |
| Revision | 2026-09-19 |
| Publication date | 2026-09-19 |
| Media type | application/json; charset=utf-8 |
This specification is the normative contract for providers that integrate with FleetBridge. The provider OpenAPI file, request and response examples, and certification suite are executable companion resources. The terms MUST, MUST NOT, SHOULD, and MAY have the meanings defined in RFC 2119.
1. Compatibility and versioning
Backward-compatible changes include new optional request or response properties, new optional event types, additional examples, and clarifications. These changes increment the semantic minor or patch version. Breaking changes require a new API major version. Breaking changes include removing or renaming a field, changing whether a field is required, changing an authentication or signature algorithm, changing the meaning of an existing status, or changing endpoint behavior. Providers MUST record the semantic contract version and revision they certified against. See CHANGELOG.md for the version history.
2. Environments, base URL, and authentication
The Provider supplies separate HTTPS base URLs for staging and production, such as https://provider.example/fleetbridge/v1. Each URL MUST use a certificate issued by a publicly trusted certificate authority. FleetBridge does not follow HTTP redirects. FleetBridge sends these headers with every request:
Authorization: Bearer <API_KEY>
Content-Type: application/json; charset=utf-8
Accept: application/json
API keys MUST be scoped to the FleetBridge integration audience or account. Staging and production MUST use separate keys. Keys must be revocable, rotated securely, and excluded from logs. Return 401 Unauthorized when credentials are missing or invalid. Return 403 Forbidden when the credentials are valid but do not grant access to the requested resource.
FleetBridge uses a 15-second HTTP timeout and accepts response bodies up to 5 MiB. For requests identified as idempotent in this specification, FleetBridge makes no more than three total attempts after a network failure, timeout, 429, or 5xx response. When the Provider sends Retry-After, FleetBridge honors the delay up to a maximum of 30 seconds. FleetBridge does not automatically retry update, cancellation, or return requests.
3. Correlation and durable idempotency
platformReference is FleetBridge's durable delivery correlation ID. The Provider MUST store it and return it unchanged in every event for that delivery. providerDeliveryId is the Provider's durable delivery ID. providerTrackingId is optional and does not replace either of the other identifiers.
For Create Delivery, idempotencyKey is required and currently has the same value as platformReference. Its uniqueness scope is the Provider account or integration audience. The Provider MUST enforce idempotency in durable, shared storage that works across process restarts and service instances:
- The first valid request creates at most one delivery.
- An identical or compatible replay returns the original result and identifiers.
- Concurrent duplicate requests converge on the same result.
- A replay after a process restart returns the original result.
- A replay with a changed delivery payload or callback URL returns
409 Conflict. - If the first request included a callback, a replay that omits
webhookretains the original callback. - The Provider MUST NOT create a second physical delivery after a timeout or other ambiguous response.
4. Per-delivery callbacks and multi-brand isolation
A Create Delivery request MAY include a delivery-specific callback:
{"webhook":{"url":"https://api.fleetbridge.example/api/v1/webhooks/providers/<connection-token>"}}
FleetBridge selects the callback in this order:
- Use
CreateDelivery.webhook.urlwhen it is present. - Otherwise, use the global FleetBridge webhook URL configured for the Provider connection.
- If neither URL is available, do not push webhook events. FleetBridge uses polling when the Provider supports it.
When a per-delivery callback is supplied, the Provider MUST validate it, store it with the delivery, and use it for every event for that delivery. The Provider MUST NOT infer a tenant or brand from platformReference, rewrite the URL, or send one delivery's events to another delivery's callback. The callback MUST be an absolute HTTPS URL no longer than 2,048 characters and MUST NOT contain embedded credentials or a URL fragment. The Provider SHOULD reject nonstandard ports. It MUST apply outbound URL and DNS/IP safety controls and MUST NOT follow redirects.
The token in the callback path is a confidential routing key for a specific FleetBridge tenant and Provider connection. It is not the HMAC secret and MUST NOT be logged. The webhook HMAC secret is provisioned separately and MUST NOT appear in a Create Delivery request.
5. Provider endpoints
| Method | Path | Automatic retry | Capability |
|---|---|---|---|
POST |
/deliveries |
Yes, same idempotency key | required |
GET |
/deliveries/{providerDeliveryId}/status |
Yes | supportsPolling |
GET |
/deliveries/{providerDeliveryId}/tracking |
Yes | tracking fields as declared |
PATCH |
/deliveries/{providerDeliveryId} |
No | update capabilities |
POST |
/deliveries/{providerDeliveryId}/cancel |
No | cancellation capability |
POST |
/deliveries/{providerDeliveryId}/return |
No | supportsReturnToOrigin |
POST |
/webhooks/test |
Yes | webhook providers |
5.1 Create delivery
POST /deliveries accepts the fields listed below. Timestamps use RFC 3339 and include an explicit UTC offset; FleetBridge sends timestamps in UTC. Monetary values are JSON numbers.
| Field | Type | Required | Limit/meaning |
|---|---|---|---|
platformReference |
string | yes | stable correlation, max 200 |
idempotencyKey |
string | yes | durable idempotency identity, max 200 |
pickupAddress |
string | yes | max 500 |
pickupLat, pickupLng |
number | yes | latitude -90..90, longitude -180..180 |
customerName |
string | yes | max 200 |
customerPhone |
string | yes | max 50 |
dropoffAddress |
string | yes | max 500 |
dropoffLat, dropoffLng |
number | yes | coordinate ranges above |
paymentMethod |
string | yes | cash, card, online, wallet, or agreed raw value max 100 |
amount |
number | yes | 0..9,999,999,999.99, two decimal places |
deliveryFeeAmount |
number/null | no | same monetary range |
currency |
string | yes | 3-character uppercase code |
notes |
string/null | no | max 2,000 |
preparationTimeMinutes |
integer | yes | >= 0 |
scheduledDeliveryAtUtc |
date-time/null | no | requires scheduled-delivery capability |
webhook.url |
URI/null | no | immutable callback described in section 4 |
A successfully processed request returns 200 OK with accepted, providerDeliveryId, and optional providerTrackingId and rejectionReason values. When accepted is true, providerDeliveryId MUST contain a nonblank value. The Provider MAY return 200 OK with accepted:false for a business rejection. Use 400 or 422 for malformed or invalid requests and 409 for conflicts.
5.2 Update delivery
PATCH /deliveries/{providerDeliveryId} MAY include any of these fields: dropoffAddress, paired dropoffLat and dropoffLng, customerPhone, scheduledDeliveryAtUtc, notes, customerName, customerEmail, amount, currency, paymentMethod, deliveryFeeAmount, and preparationTimeMinutes.
Only non-null fields request a change. In contract v1.1, an omitted field and an explicit null both mean "leave this field unchanged." Clearing a nullable field is not supported. The Provider MUST return fieldAccepted, an object with a Boolean result for each submitted field, and MAY return errorMessage. Return 404 for an unknown delivery. Report an unsupported or invalid change with 422 or a false field result. FleetBridge does not automatically retry updates.
5.3 Cancellation and return
The cancellation body is {"stage":"before_pickup"} or {"stage":"after_pickup"}. The response contains confirmed and MAY include errorMessage. Repeating the same cancellation MUST be idempotent at the business level. The Provider MUST define cancellation outcomes for pending, accepted, picked-up, final, and unknown deliveries. Return 404 for an unknown delivery.
The return body is {"reasonCode":"..."}. The response contains accepted and MAY include errorMessage. FleetBridge uses this endpoint only when supportsReturnToOrigin=true. Proof of Delivery is outside the scope of this contract revision.
5.4 Status
GET /deliveries/{providerDeliveryId}/status returns status and eventTimeUtc. Allowed values:
| Status | Terminal | Meaning |
|---|---|---|
sent_to_provider |
no | request recorded |
provider_accepted |
no | delivery accepted |
driver_assigned |
no | driver assigned |
arrived_at_pickup |
no | driver at pickup |
picked_up |
no | goods collected |
on_the_way |
no | traveling to the destination |
delivered |
yes | delivery completed |
cancelled |
yes | delivery canceled |
failed |
yes | delivery failed after a real provider decision |
return_requested |
no | return requested |
returning_to_origin |
no | return in progress |
returned_to_origin |
yes | return completed |
return_failed |
yes | return failed and requires review |
The Provider MUST NOT emit a status that is absent from this vocabulary or map an unknown internal state to failed. FleetBridge rejects unknown values and retains the last recognized state.
5.5 Tracking
GET /deliveries/{providerDeliveryId}/tracking returns nullable driverName, driverPhone, paired driverLat and driverLng, trackingUrl, and estimatedDeliveryAtUtc, plus required eventTimeUtc. Do not invent values when data is unavailable. Driver personal data MUST be limited to the fields in this contract and protected from exposure in logs. Status and tracking endpoints remain the authoritative convergence sources even when webhooks are enabled.
6. Webhook channel
The Provider sends each event to the callback selected for that delivery. Events use this backward-compatible flat JSON payload:
{
"eventType": "driver.location_updated",
"platformReference": "FB-123",
"providerDeliveryId": "PROV-456",
"providerTrackingId": "TRACK-456",
"status": "on_the_way",
"eventTimeUtc": "2026-09-19T12:30:00Z",
"driverName": "Controlled Driver",
"driverPhone": null,
"driverLat": 32.2211,
"driverLng": 35.2544,
"trackingUrl": null,
"estimatedDeliveryAtUtc": "2026-09-19T12:50:00Z"
}
platformReference, status, and eventTimeUtc are required. At least one Provider identifier SHOULD be present. eventType is optional for v1.0 compatibility and REQUIRED for new v1.1 implementations.
| Event type | Expected status | Required extra data |
|---|---|---|
delivery.accepted |
provider_accepted |
provider delivery ID |
driver.assigned |
driver_assigned |
available driver identity |
driver.location_updated |
current nonterminal status | driverLat, driverLng |
eta.updated |
current nonterminal status | estimatedDeliveryAtUtc |
tracking.updated |
current status | trackingUrl and/or tracking fields |
delivery.picked_up |
picked_up |
none |
delivery.delivered |
delivered |
none |
delivery.cancelled |
cancelled |
none |
delivery.failed |
failed |
real terminal provider failure |
Location coordinates use the ranges defined for Create Delivery. eventTimeUtc is the time the Provider observed the event and MUST remain unchanged when the event is retried. Providers SHOULD send meaningful location changes at a reasonable rate and MAY combine excessive intermediate points. Events can be duplicated or arrive out of order. FleetBridge uses correlation, event time, and allowed status transitions to process duplicates idempotently and ignore stale regressions. After sending a terminal event, the Provider MUST stop sending nonterminal events for that delivery.
7. Webhook authentication, replay protection, and retries
Compute a lowercase hexadecimal HMAC-SHA256 signature over the exact UTF-8 bytes of the HTTP request body. Use the separately provisioned webhook secret for the Provider connection. Send the signature in X-Platform-Signature without a sha256= prefix. Any change to the body after signing invalidates the signature. See webhook-signing/ for code samples and a fixed test vector.
FleetBridge validates the callback URL token, then the signature, and then the event's correlation and lifecycle rules. The Provider MUST preserve the logical event's original eventTimeUtc on every retry. Any 2xx response completes the attempt. Retry after 408, 429, and 5xx responses. Do not retry another 4xx response until its configuration or payload issue is corrected. Use bounded exponential backoff with jitter for at least six attempts over at least 15 minutes, and honor Retry-After. Delivery order is not guaranteed, so senders and receivers MUST safely handle duplicate events.
The callback token identifies the FleetBridge routing connection. The HMAC signature proves body authenticity and integrity. Both controls are required when webhooks are used.
8. Polling convergence and timeout ambiguity
FleetBridge may poll the Status and Tracking endpoints even when webhooks are active. These endpoints MUST return the same state or a newer state. Return 404 only when the delivery is unknown. Do not disguise a transient 429 or 5xx condition as 404 or as a generic success. A Create Delivery timeout has an ambiguous outcome: FleetBridge retries with the same idempotency identity, and the Provider MUST return the original delivery instead of creating another one.
9. Errors and rate limiting
Errors use this JSON envelope:
{"code":"validation_failed","message":"Request validation failed.","retryable":false,"fieldErrors":{"currency":["Must be three uppercase characters."]}}
code, message, and retryable are required. fieldErrors is optional. Error messages MUST NOT expose stack traces, SQL, secrets, internal exception types, or credentials.
| HTTP | Meaning |
|---|---|
| 400 | malformed request |
| 401 | missing/invalid authentication |
| 403 | authenticated but not authorized |
| 404 | unknown delivery/resource |
| 409 | idempotency/callback/state conflict |
| 422 | syntactically valid but semantically invalid/unsupported |
| 429 | rate limited; send Retry-After seconds or HTTP date |
| 500 | unexpected provider failure |
| 502/503 | transient dependency/unavailability |
10. Capabilities and security
Capabilities are declared during onboarding and configured by FleetBridge. Contract v1 does not define a runtime capability endpoint. A capability can be enabled only after it is implemented and certified. See CAPABILITIES.md. supportsProofOfDelivery MUST remain false for this contract revision.
Providers MUST isolate FleetBridge credentials and data from other partners and accounts. Authorization MUST be enforced independently of callback routing. Providers MUST validate all contract limits, minimize personal data, redact sensitive log fields, and keep staging separate from production. Callback tokens, API keys, and webhook secrets are all secrets.
11. Certification and onboarding
Certification is a black-box process. It requires only staging endpoints, credentials, webhook configuration, and controlled fixtures. The certification lifecycle is:
IMPLEMENTATION_DECLARED → STAGING_CONFIGURED → STAGING_CERTIFIED → PRODUCTION_CONFIGURED → PRODUCTION_CERTIFIED
SUSPENDED and RECERTIFICATION_REQUIRED are administrative states. Recertification is required after a breaking contract revision; a change to authentication, signatures, statuses, or callbacks; a major Provider API change; a material certification failure; or a security incident.
FleetBridge certifies the complete path from Create Delivery through Provider acceptance, tracking or status updates, final delivery, and FleetBridge convergence. The suite also covers invalid credentials, identical and conflicting duplicate creates, concurrent creates, unknown deliveries, updates, cancellation, webhook signatures, duplicate and out-of-order events, polling fallback, unknown-status safety, 429 handling, timeout ambiguity, callback persistence, and multi-brand isolation when the available fixtures support those cases. Production activation and routing changes require separate approval.