This API provides integration with Uber Direct for creating delivery quotes and managing deliveries.
http://localhost:5000/api
This API implements several security measures to protect against abuse and ensure secure operation:
To prevent abuse and ensure fair usage, all endpoints are rate-limited based on IP address:
- Health Check: No limit (unlimited)
- Get Delivery Quote: 10 requests per minute
- Create Delivery: 5 requests per minute
- Get Delivery: 20 requests per minute
- Update Delivery: 10 requests per minute
- Cancel Delivery: 5 requests per minute
- List Deliveries: 5 requests per minute
- Admin List Deliveries: 2 requests per minute
- Proof of Delivery: 10 requests per minute
- Find Stores: 10 requests per minute
Rate limits are enforced using Flask-Limiter. Exceeding these limits will result in a 429 (Too Many Requests) response.
- Phone Numbers: Must start with
+followed by digits only (e.g.,+1234567890) - Coordinates: Latitude must be between -90 and 90, longitude between -180 and 180
- Required Fields: All mandatory fields are validated; invalid data is rejected with appropriate error messages
- Environment Variables: All sensitive configuration (API keys, secrets) must be set via environment variables
- Validation on Startup: The application validates required environment variables on startup and fails to start if any are missing
- OAuth Token Management: Access tokens are automatically refreshed when expired, preventing unauthorized API calls
- No Plaintext Secrets: Secrets are never logged or exposed in responses
- Secure Token Storage: OAuth tokens are managed securely in memory with automatic expiration handling
POST /deliveries/quote
Get a delivery quote from Uber for a pickup and dropoff location.
{
"pickup_address": {
"street_address": "string",
"city": "string",
"state": "string",
"zip_code": "string",
"country": "US"
},
"dropoff_address": {
"street_address": "string" | ["string", "string"],
"city": "string",
"state": "string",
"zip_code": "string",
"country": "US"
},
"external_store_id": "string",
"pickup_latitude": 37.7749,
"pickup_longitude": -122.4194,
"dropoff_latitude": 37.7849,
"dropoff_longitude": -122.4094,
"pickup_ready_dt": "2025-10-14T10:00:00Z",
"pickup_deadline_dt": "2025-10-14T11:00:00Z",
"dropoff_ready_dt": "2025-10-14T11:00:00Z",
"dropoff_deadline_dt": "2025-10-14T12:00:00Z",
"pickup_phone_number": "+15555555555",
"dropoff_phone_number": "+15555555555",
"manifest_total_value": 2500,
"items": [
{
"name": "Package description",
"description": "Additional details",
"quantity": 1,
"value": 25.00
}
]
}pickup_address- Pickup location detailsdropoff_address- Dropoff location details
external_store_id- Store identifier (must match for delivery creation)pickup_latitude/longitude- Precise pickup coordinatesdropoff_latitude/longitude- Precise dropoff coordinatespickup_ready_dt/deadline_dt- Pickup time window (RFC 3339 format)dropoff_ready_dt/deadline_dt- Dropoff time window (RFC 3339 format)pickup_phone_number/dropoff_phone_number- Contact numbers (must include country code)manifest_total_value- Total value in cents (e.g., $25.00 = 2500)items- Array of items being delivered
curl -X POST "http://localhost:5000/api/deliveries/quote" \
-H "Content-Type: application/json" \
-d '{
"pickup_address": {
"street_address": "123 Market St",
"city": "San Francisco",
"state": "CA",
"zip_code": "94103",
"country": "US"
},
"dropoff_address": {
"street_address": "500 Mission St",
"city": "San Francisco",
"state": "CA",
"zip_code": "94105",
"country": "US"
},
"external_store_id": "store_12345"
}'{
"success": true,
"quote": {
"id": "dqt_7oB_OKLmRVy6LUWyjqfKxg",
"kind": "delivery_quote",
"currency_code": "usd",
"estimated_at": "2025-10-14T10:00:00Z",
"expires_at": "2025-10-14T11:00:00Z",
"fee": 640,
"duration": 1800
}
}POST /deliveries
Create a new delivery using a previously obtained quote.
{
"quote_id": "dqt_7oB_OKLmRVy6LUWyjqfKxg",
"pickup_name": "Store Name",
"pickup_address": {
"street_address": "string" | ["string", "string"],
"city": "string",
"state": "string",
"zip_code": "string",
"country": "US"
},
"pickup_phone_number": "string",
"dropoff_name": "Recipient Name",
"dropoff_address": {
"street_address": "string" | ["string", "string"],
"city": "string",
"state": "string",
"zip_code": "string",
"country": "US"
},
"dropoff_phone_number": "string",
"manifest_items": [
{
"name": "Item name",
"quantity": 1,
"weight": 30,
"dimensions": {
"length": 40,
"height": 40,
"depth": 40
},
"size": "small",
"price": 100
}
],
"external_store_id": "store_12345",
"pickup_business_name": "Business Name",
"pickup_latitude": 37.7749,
"pickup_longitude": -122.4194,
"pickup_notes": "Special pickup instructions",
"pickup_verification": {
"signature_requirement": {
"enabled": true,
"collect_signer_name": true,
"collect_signer_relationship": true
},
"picture": true
},
"dropoff_business_name": "Business Name",
"dropoff_latitude": 37.7849,
"dropoff_longitude": -122.4094,
"dropoff_notes": "Special delivery instructions",
"dropoff_seller_notes": "Fragile - handle with care",
"dropoff_verification": {
"signature_requirement": {
"enabled": true,
"collect_signer_name": true,
"collect_signer_relationship": true
},
"barcodes": [
{
"value": "123456789",
"type": "CODE39"
}
]
},
"deliverable_action": "deliverable_action_meet_at_door",
"manifest_reference": "REF0000001",
"manifest_total_value": 1000,
"idempotency_key": "unique-key-123",
"return_verification": {
"picture": true
},
"external_id": "external-order-123",
"user_fees_summary": [
{
"fee_type": "promo",
"amount": -300,
"user_fee_tax_info": [
{
"tax_rate": 200
}
]
}
]
}quote_id- Quote ID from previous quote requestpickup_name- Pickup contact namepickup_address- Pickup location detailspickup_phone_number- Pickup contact phonedropoff_name- Dropoff contact namedropoff_address- Dropoff location detailsdropoff_phone_number- Dropoff contact phonemanifest_items- Array of items to deliver
external_store_id- Must match the quote's external_store_idpickup_business_name/dropoff_business_name- Business namespickup_latitude/longitude- Precise coordinatespickup_notes/dropoff_notes- Special instructionspickup_verification/dropoff_verification- Verification requirementsdeliverable_action- Delivery method (e.g., "deliverable_action_meet_at_door")manifest_reference- Reference numbermanifest_total_value- Total value in centsidempotency_key- Prevents duplicate deliveriesreturn_verification- Return verification settingsexternal_id- External order identifieruser_fees_summary- Fee and tax information
curl -X POST "http://localhost:5000/api/deliveries" \
-H "Content-Type: application/json" \
-d '{
"quote_id": "dqt_7oB_OKLmRVy6LUWyjqfKxg",
"pickup_name": "My Store",
"pickup_address": {
"street_address": "123 Market St",
"city": "San Francisco",
"state": "CA",
"zip_code": "94103",
"country": "US"
},
"pickup_phone_number": "4444444444",
"dropoff_name": "Reese Ippient",
"dropoff_address": {
"street_address": ["285 Fulton St", ""],
"state": "NY",
"city": "New York",
"zip_code": "10006",
"country": "US"
},
"dropoff_phone_number": "5555555555",
"manifest_items": [
{
"name": "Cell phone box",
"quantity": 1,
"weight": 30,
"dimensions": {
"length": 40,
"height": 40,
"depth": 40
}
}
],
"external_store_id": "store_12345"
}'{
"success": true,
"delivery": {
"id": "del_7oB_OKLmRVy6LUWyjqfKxg",
"status": "pending",
"quote_id": "dqt_7oB_OKLmRVy6LUWyjqfKxg",
"fee": 640,
"currency": "usd",
"created": "2025-10-14T10:08:00.48Z",
"tracking_url": "https://delivery.uber.com/orders/...",
"pickup": {
"name": "My Store",
"address": "123 Market St, San Francisco, CA 94103, US",
"phone_number": "4444444444"
},
"dropoff": {
"name": "Reese Ippient",
"address": "285 Fulton St, New York, NY 10006, US",
"phone_number": "5555555555"
},
"manifest_items": [
{
"name": "Cell phone box",
"quantity": 1,
"weight": 30,
"dimensions": {
"length": 40,
"height": 40,
"depth": 40
}
}
]
}
}GET /deliveries/<delivery_id>
Retrieve the details of a specific delivery by its delivery ID. The customer ID is automatically included from the environment configuration.
delivery_id(string, required) - Unique identifier for the delivery (starts withdel_)
curl -X GET "http://localhost:5000/api/deliveries/del_aEOkr3JwTcKEaupQaj3W-g" \
-H "Content-Type: application/json"{
"id": "del_aEOkr3JwTcKEaupQaj3W-g",
"quote_id": "dqt_7oB_OKLmRVy6LUWyjqfKxg",
"complete": false,
"courier": {
"name": "John Doe",
"phone_number": "+15555555555",
"location": {
"lat": 37.7749,
"lng": -122.4194
},
"vehicle": {
"make": "Toyota",
"model": "Camry",
"color": "Blue",
"license_plate": "ABC123"
}
},
"courier_imminent": false,
"created": "2025-10-14T10:00:00Z",
"currency": "usd",
"deliverable_action": "deliverable_action_deliver",
"dropoff": {
"name": "Recipient Name",
"phone_number": "+15555555555",
"address": {
"street_address": ["500 Mission St"],
"city": "San Francisco",
"state": "CA",
"zip_code": "94105",
"country": "US"
},
"location": {
"lat": 37.7849,
"lng": -122.4094
},
"notes": "Second floor, black door to the right"
},
"dropoff_deadline": "2025-10-14T12:00:00Z",
"dropoff_eta": "2025-10-14T11:30:00Z",
"dropoff_identifier": "",
"dropoff_ready": "2025-10-14T11:00:00Z",
"external_id": "EI000001",
"fee": 640,
"kind": "delivery",
"live_mode": true,
"manifest": {
"reference": "REF0000001",
"total_value": 2500
},
"manifest_items": [
{
"name": "Package",
"quantity": 1,
"size": "small",
"dimensions": {
"length": 40,
"height": 40,
"depth": 40
},
"weight": 30,
"price": 100
}
],
"pickup": {
"name": "Store Name",
"phone_number": "+15555555555",
"address": {
"street_address": ["123 Market St"],
"city": "San Francisco",
"state": "CA",
"zip_code": "94103",
"country": "US"
},
"location": {
"lat": 37.7749,
"lng": -122.4194
},
"notes": "Follow big green 'Pickup' signs in the parking lot"
},
"pickup_deadline": "2025-10-14T11:00:00Z",
"pickup_eta": "2025-10-14T10:15:00Z",
"pickup_ready": "2025-10-14T10:00:00Z",
"status": "pickup",
"tip": 200,
"tracking_url": "https://delivery.uber.com/orders/12345678-1234-1234-1234-123456789012",
"undeliverable_action": "",
"undeliverable_reason": "",
"updated": "2025-10-14T10:15:00Z",
"uuid": "12345678123412341234123456789012"
}400 Bad Request- Invalid delivery ID format or API error404 Not Found- Delivery not found
GET /admin/deliveries
Retrieve a list of deliveries for the configured customer with optional filtering. This endpoint uses the customer ID from the environment configuration.
filter(string, optional) - Filter deliveries by delivery state. Valid values: "pending", "pickup", "pickup_complete", "dropoff", "delivered", "canceled", "returned", "ongoing"external_store_id(string, optional) - Filter deliveries by external_store_idstart_dt(string, optional) - Beginning of the filter time range (RFC 3339 format). Defaults to 3 months prior to current time if not providedend_dt(string, optional) - End of the filter time range (RFC 3339 format). Defaults to current time if not providedlimit(integer, optional) - Maximum number of responses to returnoffset(integer, optional) - Offset of response objects for pagination
curl -X GET "http://localhost:5000/api/admin/deliveries?filter=delivered&limit=10" \
-H "Content-Type: application/json"{
"success": true,
"deliveries": [
{
"id": "del_7oB_OKLmRVy6LUWyjqfKxg",
"status": "delivered",
"quote_id": "dqt_7oB_OKLmRVy6LUWyjqfKxg",
"fee": 640,
"currency": "usd",
"created": "2025-10-14T10:08:00.48Z",
"tracking_url": "https://delivery.uber.com/orders/...",
"pickup": {
"name": "My Store",
"address": "123 Market St, San Francisco, CA 94103, US",
"phone_number": "4444444444"
},
"dropoff": {
"name": "Reese Ippient",
"address": "285 Fulton St, New York, NY 10006, US",
"phone_number": "5555555555"
},
"manifest_items": [
{
"name": "Cell phone box",
"quantity": 1,
"weight": 30,
"dimensions": {
"length": 40,
"height": 40,
"depth": 40
}
}
]
}
]
}-
External Store ID: If provided in the quote request, it must match exactly in the delivery creation request.
-
Address Format: Street addresses can be either a string or an array of strings for multi-line addresses.
-
Phone Numbers: Must include country code (e.g., +1 for US numbers).
-
Coordinates: If provided, they must be geographically close to the address. Uber validates coordinate/address matching.
-
Quote Expiration: Quotes expire after a certain time (typically 1 hour). Use fresh quotes for delivery creation.
-
Idempotency: Use
idempotency_keyto prevent duplicate deliveries when retrying failed requests. -
Verification: Signature and picture verification can be enabled for additional security.
GET /health
Check if the API service is running and healthy.
curl -X GET "http://localhost:5000/api/health" \
-H "Content-Type: application/json"{
"status": "ok"
}POST /deliveries/<delivery_id>
Update details of an existing delivery. Note: Updates are only allowed within certain time windows before pickup.
delivery_id(string, required) - Unique identifier for the delivery (starts withdel_)
{
"dropoff_notes": "Updated delivery instructions",
"dropoff_seller_notes": "Handle with extra care",
"manifest_reference": "REF0000002",
"pickup_notes": "Updated pickup instructions",
"dropoff_verification": {
"barcodes": [
{
"value": "W1129082649-1",
"type": "CODE39"
}
]
},
"tip_by_customer": 500
}dropoff_notes- Updated delivery instructionsdropoff_seller_notes- Seller notes for couriermanifest_reference- Updated reference numberpickup_notes- Updated pickup instructionsdropoff_verification- Updated verification requirementstip_by_customer- Additional tip amount in cents
curl -X POST "http://localhost:5000/api/deliveries/del_aEOkr3JwTcKEaupQaj3W-g" \
-H "Content-Type: application/json" \
-d '{
"dropoff_notes": "Ring doorbell twice",
"tip_by_customer": 300
}'{
"success": true,
"delivery": {
"id": "del_aEOkr3JwTcKEaupQaj3W-g",
"status": "pending",
"updated": "2025-10-14T10:30:00Z"
}
}POST /deliveries/<delivery_id>/cancel
Cancel an ongoing or scheduled delivery.
delivery_id(string, required) - Unique identifier for the delivery (starts withdel_)
curl -X POST "http://localhost:5000/api/deliveries/del_aEOkr3JwTcKEaupQaj3W-g/cancel" \
-H "Content-Type: application/json"{
"id": "del_aEOkr3JwTcKEaupQaj3W-g",
"status": "canceled",
"canceled_at": "2025-10-14T10:30:00Z"
}GET /deliveries
Retrieve a list of deliveries stored in the local database with optional filtering.
status(string, optional) - Filter deliveries by statuslimit(integer, optional) - Maximum number of deliveries to return (default: 50, max: 100)offset(integer, optional) - Number of deliveries to skip for pagination (default: 0)
curl -X GET "http://localhost:5000/api/deliveries?status=delivered&limit=10&offset=0" \
-H "Content-Type: application/json"{
"success": true,
"deliveries": [
{
"_id": "670d1234567890abcdef12345",
"delivery_id": "del_aEOkr3JwTcKEaupQaj3W-g",
"status": "delivered",
"created_at": "2025-10-14T10:00:00Z",
"updated_at": "2025-10-14T11:30:00Z"
}
],
"count": 1
}Note: The count field represents the number of deliveries returned in this response, not the total number of deliveries matching the filters.
POST /deliveries/<delivery_id>/proof-of-delivery
Retrieve proof of delivery information including signature images or verification details.
delivery_id(string, required) - Unique identifier for the delivery (starts withdel_)
{
"waypoint": "dropoff",
"type": "signature"
}waypoint- Either "pickup" or "dropoff"type- Type of proof: "signature", "picture", or "pincode"
curl -X POST "http://localhost:5000/api/deliveries/del_aEOkr3JwTcKEaupQaj3W-g/proof-of-delivery" \
-H "Content-Type: application/json" \
-d '{
"waypoint": "dropoff",
"type": "signature"
}'{
"id": "pod_1234567890",
"waypoint": "dropoff",
"type": "signature",
"data": "iVBORw0KGgoAAAANSUhEUgAA...",
"captured_at": "2025-10-14T11:30:00Z"
}GET /direct/stores
Find stores that can deliver to a specific location based on latitude and longitude coordinates.
latitude(number, required) - Latitude of the dropoff locationlongitude(number, required) - Longitude of the dropoff location
curl -X GET "http://localhost:5000/direct/stores?latitude=40.7128&longitude=-74.0060" \
-H "Content-Type: application/json"{
"stores": [
{
"external_id": "store_123",
"name": "Example Store",
"address": {
"street1": "123 Main St",
"street2": "Suite 100",
"city": "New York",
"state": "NY",
"zipcode": "10001",
"country_iso2": "US"
}
}
]
}Both endpoints return errors in the following format:
{
"success": false,
"error": {
"code": "error_code",
"message": "Error description",
"metadata": {
"param_details": "Additional error details"
}
}
}Common error codes:
invalid_params- Invalid request parametersaddress_undeliverable- Address cannot be delivered toexpired_quote- Quote has expiredmissing_payment- Payment method required