Country-wide delivery across Trinidad & Tobago
Charlieville, Trinidad
RESTful Design

Clean, predictable endpoints following REST conventions

Bearer Token Auth

Secure API key authentication with HTTPS encryption

Sandbox Mode

Test integration safely before going live

JSON Responses

Consistent JSON format for all responses

Getting Started

Quick Setup Guide

Get up and running with our API in minutes

1
Create a Merchant Account

Sign up for a free merchant account to access the developer dashboard and generate your API credentials.

2
Generate API Tokens

Navigate to Settings > API in your dashboard. Generate a sandbox token for testing and a production token for live operations.

3
Make Your First Request

Include your token in the Authorization header as a Bearer token. Use sandbox paths for testing before going live.

Authentication Header
// Include your API token in every request

curl -X GET "https://odeliver.com/api/v1/shipments" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json"


// Or using JavaScript

fetch('https://odeliver.com/api/v1/shipments', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer YOUR_API_TOKEN',
    'Content-Type': 'application/json'
  }
})

Base URLs

Use different base paths depending on your token type. Sandbox tokens must use sandbox paths, and production tokens must use production paths.

Environments
Sandbox
https://odeliver.com/sandbox/v1/shipments https://odeliver.com/sandbox/v1/instant-shipments
Production
https://odeliver.com/api/v1/shipments https://odeliver.com/api/v1/instant-shipments
Important: Using a sandbox token with production paths (or vice versa) will result in a 403 Forbidden error.

Authentication

All API requests require authentication using a Bearer token. Include your token in the Authorization header.

Keep your API tokens secure! Never expose them in client-side code or public repositories.
Token Types
  • Sandbox Tokens - For testing (use /sandbox/v1/ paths)
  • Production Tokens - For live transactions (use /api/v1/ paths)
Rate Limit Headers
  • X-RateLimit-Limit - Requests allowed per period
  • X-RateLimit-Remaining - Requests remaining
  • X-RateLimit-Reset - Time until limit resets
API Reference

Available Endpoints

Core endpoints to manage your deliveries

Standard Shipments

Hub & Spoke delivery (1-2 business days)

GET /v1/shipments List shipments
GET /v1/shipments/{id} Get shipment
POST /v1/shipments Create shipment
POST /v1/shipments/{id}/cancel Cancel shipment
GET /v1/shipments/{id}/label Get label (PDF or base64)
POST /v1/shipments/estimate Get price estimate
GET /v1/shipments/{shipment_id}/track Track by shipment ID

Instant Shipments

Same-day delivery (within hours)

GET /v1/instant-shipments List shipments
GET /v1/instant-shipments/{id} Get shipment
POST /v1/instant-shipments Create shipment
POST /v1/instant-shipments/{id}/cancel Cancel shipment
POST /v1/instant-shipments/estimate Get price estimate
GET /v1/instant-shipments/slots Get scheduled delivery slots
GET /v1/instant-shipments/{id}/track Track by ID
GET /v1/instant-shipments/{shipment_id}/track Track by shipment ID

Tracking

GET /v1/shipments/{shipment_id}/track Track standard shipment
GET /v1/instant-shipments/{id}/track Track instant by ID
GET /v1/instant-shipments/{shipment_id}/track Track instant by shipment ID

All tracking endpoints return delivery_status (integer) and delivery_status_label (human-readable).

Health Check

GET /v1/ping API health check

Returns { "success": true, "data": { "time": "...", "status": "alive" } }. No authentication required.

Example

Create a Standard Shipment

Hub & Spoke delivery — city IDs are integers from your account settings

Request
POST /api/v1/shipments
{
  "pickup": {
    "company": "My Store Ltd",
    "address1": "123 Main Street",
    "address2": "Suite 100",
    "city": 1,
    "zip": "00000",
    "phone": "18685551234",
    "lat": 10.6549,
    "lng": -61.5019
  },
  "dropoff": {
    "name": "Jane Doe",
    "email": "jane@example.com",
    "phone": "18685555678",
    "address1": "456 Oak Avenue",
    "city": 2,
    "zip": "00000",
    "lat": 10.2833,
    "lng": -61.4667,
    "instructions": "Leave at front door"
  },
  "size": [2],
  "item_cost": 250.00,
  "payment_on_delivery": 1,
  "shipping_cost": 0,
  "delivery_type": 1
}
Response
201 Created
{
  "success": true,
  "data": {
    "id": 12345,
    "shipment_id": "OD-7X9K2M4P",
    "message": "Created"
  }
}
Create Instant Shipment
POST /api/v1/instant-shipments
// Same pickup/dropoff structure, plus:
{
  ...
  "size": [2, 2],
  "item_cost": 150.00,
  "payment_on_delivery": 1,
  "shipping_cost": 0
}

// Response
{
  "success": true,
  "data": {
    "id": 6789,
    "shipment_id": "OD-A3B5C7D9",
    "collect": 185.00,
    "message": "Created Successfully"
  }
}
Reference

Request Parameters

Required and optional fields for creating shipments

pickup Object
Parameter Type Description
company string Business name (optional)
address1 * string Street address
address2 string Suite, unit, etc.
city * integer City ID (must exist in system)
zip * string Postal code (digits only)
phone * string Phone number (exactly 11 digits)
lat * float Latitude coordinate
lng * float Longitude coordinate
dropoff Object
Parameter Type Description
name * string Recipient name (max 50 chars)
email string Email for notifications
phone * string Phone number (exactly 11 digits)
address1 * string Street address
address2 string Apt, suite, etc.
city * integer City ID (must exist in system)
zip * string Postal code (digits only)
lat * float Latitude coordinate
lng * float Longitude coordinate
instructions string Delivery instructions (max 150 chars)
Shipment Options
Parameter Type Description
size * array Package sizes array. Standard: 1-5 items, values 1-4. Instant: 1-4 items, value 2.
item_cost float Cost of item being shipped (min 0)
payment_on_delivery * 0 or 1 1 = driver collects payment from customer
shipping_cost * 0 or 1 0 = customer pays shipping, 1 = seller pays
delivery_type integer 1 = Delivery, 2 = Exchange, 3 = Collection
round_trip 0 or 1 1 = round trip delivery
customer_approval 0 or 1 1 = require customer approval before dispatch
Insurance & Scheduling
Parameter Type Description
oprotect 0 or 1 1 = enable OProtect insurance
ins_amt float Insurance coverage amount
ins_paid_by 0 or 1 0 = customer pays, 1 = seller pays
Instant Scheduling (instant shipments only)
schedule_date string YYYY-MM-DD (omit for ASAP delivery)
schedule_slot string Slot code from /v1/instant-shipments/slots
Standard Only
delivery_window string Delivery window preference (standard shipments)
print_label 0 or 1 1 = auto-generate shipping label
blind_shipping 0 or 1 1 = hide sender info from recipient

List Shipments

Retrieve a paginated list of your shipments with optional filters. Works the same for both /v1/shipments and /v1/instant-shipments.

Query Parameters
page Page number (default: 1)
per_page Results per page (default: 25, max: 100)
delivery_status Filter by delivery status (integer)
from Start date filter (YYYY-MM-DD)
to End date filter (YYYY-MM-DD)
sort_by Sort field: id, created_at, delivery_status (default: created_at)
sort_dir asc or desc (default: desc)
GET /v1/shipments?page=1&per_page=25&sort_by=created_at
{
  "success": true,
  "data": {
    "items": [
      {
        "id": 12345,
        "shipment_id": "OD-7X9K2M4P",
        "delivery_status": 0,
        "created_at": "2026-01-15 14:30:00"
      }
    ],
    "pagination": {
      "page": 1,
      "per_page": 25,
      "total": 150,
      "pages": 6,
      "sort_by": "created_at",
      "sort_dir": "desc",
      "filters": {
        "from": null,
        "to": null,
        "delivery_status": null
      }
    }
  }
}

Get Price Estimate

Calculate delivery cost before creating a shipment. The two shipment types use different inputs.

Standard estimates use city IDs and package sizes. Instant estimates use GPS coordinates (lat/lng).
Standard Estimate Fields
pickup.city * City ID (integer)
dropoff.city * City ID (integer)
size * Array of sizes (1-5 items, values 1-4)
delivery_window Delivery window preference
Instant Estimate Fields
pickup.lat, pickup.lng * Pickup coordinates
dropoff.lat, dropoff.lng * Dropoff coordinates
POST /v1/shipments/estimate
// Standard Estimate Request
{
  "pickup":  { "city": 1 },
  "dropoff": { "city": 2 },
  "size": [2]
}

// Response
{
  "success": true,
  "data": {
    "estimated_delivery_total": 85.00,
    "currency": "TTD"
  }
}
POST /v1/instant-shipments/estimate
// Instant Estimate Request
{
  "pickup":  { "lat": 10.6549, "lng": -61.5019 },
  "dropoff": { "lat": 10.2833, "lng": -61.4667 }
}

// Response
{
  "success": true,
  "data": {
    "estimated_delivery_total": 45.00,
    "currency": "TTD",
    "is_peak": false,
    "peak_window": "11:00-13:00"
  }
}

Error Responses

All errors follow a consistent format with an error code and optional field-level details.

HTTP Status Codes
200 Success
201 Created (returned on successful create)
401 Unauthorized — invalid or missing Bearer token
403 Forbidden — sandbox token on production path (or vice versa)
404 Not Found — resource doesn't exist or not owned by you
409 Conflict — shipment cannot be cancelled in current state
422 Validation Error — invalid or missing fields
429 Rate Limited — too many requests (check retry_after)
500 Server Error
Validation Error (422)
422 Unprocessable Entity
{
  "success": false,
  "error": "Validation failed",
  "code": "VALIDATION_ERROR",
  "errors": [
    {
      "field": "pickup.address1",
      "message": "Required",
      "code": "REQUIRED"
    },
    {
      "field": "dropoff.phone",
      "message": "Must be exactly 11 digits",
      "code": "PHONE_11"
    }
  ]
}
Rate Limit (429)
429 Too Many Requests
{
  "success": false,
  "error": "Rate limit exceeded",
  "code": "RATE_LIMITED",
  "errors": {
    "retry_after": 60
  }
}
Environment Mismatch (403)
403 Forbidden
{
  "success": false,
  "error": "Sandbox tokens must use /sandbox/ path"
}

Ready to Integrate?

Create your merchant account to get API tokens and start building. Our sandbox environment lets you test without any real transactions.