Creating Orders - Developer Guide

Learn how to create delivery orders using the Dropcolis API. This guide covers authentication, request formatting, and includes complete code examples in multiple languages.

View in Swagger UI API Reference

Overview

The POST /v1/orders endpoint allows you to create delivery orders. Each order requires authentication via HMAC-SHA256 signature and includes pickup/dropoff locations, parcel details, and service preferences.

POST /v1/orders

Creates a new delivery order. Requires HMAC authentication and returns order details including tracking information.

Prerequisites

  1. API Credentials: You need a public key and secret key from Dropcolis
  2. HMAC Support: Your programming language must support HMAC-SHA256
  3. HTTPS: All API requests must use HTTPS in production
💡 Testing: Use sandbox credentials for development:
  • Public Key: pk_test_pivohub
  • Secret Key: sk_test_secret_pivohub

Authentication

All requests require HMAC-SHA256 authentication. You must include these headers:

Header Description Example
X-Api-Key Your public API key pk_test_pivohub
X-Timestamp Unix timestamp (seconds) 1702051200
X-Signature HMAC signature (v1=hex) v1=abc123...
Idempotency-Key Unique UUID for duplicate prevention 550e8400-e29b-41d4-a716-446655440000

Signature Generation

The signature is calculated as follows:

string_to_sign = timestamp + "\n" + method + "\n" + path + "\n" + body
signature = HMAC_SHA256(secret_key, string_to_sign)
X-Signature = "v1=" + hex(signature)
⚠️ Important: The body must be the exact JSON string (no extra spaces, same key order). Use JSON.stringify() or equivalent to ensure consistency.

Request Body Structure

The order creation request requires the following fields:

Field Type Required Description
partner_order_id string Yes Your unique order identifier
service_level string Yes One of: standard, express, same_day
pickup object Yes Pickup location details (name, phone, email, address, time_window)
dropoff object Yes Delivery location details (name, phone, email, address, time_window)
parcels array Yes Array of 1-50 parcels with dimensions, weight, and value
reference string No Optional reference number (e.g., sales order)
cod object No Cash on delivery amount (amount_cents, currency)
insurance object No Insurance coverage (amount_cents, currency)
instructions string No Special delivery instructions (max 1000 chars)
metadata object No Custom key-value pairs

Code Examples

Python

Python Example
import hmac
import hashlib
import time
import json
import uuid
import requests

def create_order():
    # Configuration
    public_key = "pk_test_pivohub"
    secret_key = "sk_test_secret_pivohub"
    base_url = "http://localhost:5000"
    
    # Order data
    order_data = {
        "partner_order_id": "PH-2025-000123",
        "reference": "SO-55555",
        "service_level": "standard",
        "cod": {"amount_cents": 0, "currency": "CAD"},
        "insurance": {"amount_cents": 5000, "currency": "CAD"},
        "pickup": {
            "name": "Warehouse Montreal",
            "phone": "+1-514-555-0001",
            "email": "warehouse@company.com",
            "address": {
                "line1": "123 Main Street",
                "city": "Montréal",
                "province": "QC",
                "postal_code": "H1A1A1",
                "country": "CA"
            },
            "time_window": {
                "start": "2025-11-08T09:00:00-05:00",
                "end": "2025-11-08T12:00:00-05:00"
            }
        },
        "dropoff": {
            "name": "John Doe",
            "phone": "+1-438-555-0002",
            "email": "john.doe@customer.com",
            "address": {
                "line1": "789 Oak Avenue",
                "city": "Montréal",
                "province": "QC",
                "postal_code": "H2L1P1",
                "country": "CA"
            },
            "time_window": {
                "start": "2025-11-08T13:00:00-05:00",
                "end": "2025-11-08T17:00:00-05:00"
            }
        },
        "parcels": [
            {
                "parcel_id": "PKG-001",
                "description": "Electronics - Laptop",
                "length_cm": 40,
                "width_cm": 30,
                "height_cm": 25,
                "weight_kg": 5.5,
                "value_cents": 150000,
                "fragile": True,
                "barcode": "TRACK-12345"
            }
        ],
        "instructions": "Call 10 minutes before arrival",
        "metadata": {
            "order_source": "web",
            "customer_id": "CUST-12345"
        }
    }
    
    # Prepare request
    method = "POST"
    path = "/v1/orders"
    body = json.dumps(order_data, separators=(',', ':'))
    timestamp = str(int(time.time()))
    idempotency_key = str(uuid.uuid4())
    
    # Generate signature
    string_to_sign = f"{timestamp}\n{method}\n{path}\n{body}"
    signature = hmac.new(
        secret_key.encode('utf-8'),
        string_to_sign.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    # Make request
    headers = {
        'Content-Type': 'application/json',
        'X-Api-Key': public_key,
        'X-Timestamp': timestamp,
        'X-Signature': f'v1={signature}',
        'Idempotency-Key': idempotency_key
    }
    
    response = requests.post(
        f"{base_url}{path}",
        headers=headers,
        data=body
    )
    
    print(f"Status: {response.status_code}")
    print(f"Response: {json.dumps(response.json(), indent=2)}")
    return response.json()

if __name__ == "__main__":
    create_order()

JavaScript (Node.js)

JavaScript Example
const crypto = require('crypto');
const axios = require('axios');

async function createOrder() {
    // Configuration
    const publicKey = 'pk_test_pivohub';
    const secretKey = 'sk_test_secret_pivohub';
    const baseUrl = 'http://localhost:5000';
    
    // Order data
    const orderData = {
        partner_order_id: 'PH-2025-000123',
        reference: 'SO-55555',
        service_level: 'standard',
        cod: { amount_cents: 0, currency: 'CAD' },
        insurance: { amount_cents: 5000, currency: 'CAD' },
        pickup: {
            name: 'Warehouse Montreal',
            phone: '+1-514-555-0001',
            email: 'warehouse@company.com',
            address: {
                line1: '123 Main Street',
                city: 'Montréal',
                province: 'QC',
                postal_code: 'H1A1A1',
                country: 'CA'
            },
            time_window: {
                start: '2025-11-08T09:00:00-05:00',
                end: '2025-11-08T12:00:00-05:00'
            }
        },
        dropoff: {
            name: 'John Doe',
            phone: '+1-438-555-0002',
            email: 'john.doe@customer.com',
            address: {
                line1: '789 Oak Avenue',
                city: 'Montréal',
                province: 'QC',
                postal_code: 'H2L1P1',
                country: 'CA'
            },
            time_window: {
                start: '2025-11-08T13:00:00-05:00',
                end: '2025-11-08T17:00:00-05:00'
            }
        },
        parcels: [{
            parcel_id: 'PKG-001',
            description: 'Electronics - Laptop',
            length_cm: 40,
            width_cm: 30,
            height_cm: 25,
            weight_kg: 5.5,
            value_cents: 150000,
            fragile: true,
            barcode: 'TRACK-12345'
        }],
        instructions: 'Call 10 minutes before arrival',
        metadata: {
            order_source: 'web',
            customer_id: 'CUST-12345'
        }
    };
    
    // Prepare request
    const method = 'POST';
    const path = '/v1/orders';
    const body = JSON.stringify(orderData);
    const timestamp = Math.floor(Date.now() / 1000).toString();
    const idempotencyKey = require('crypto').randomUUID();
    
    // Generate signature
    const stringToSign = `${timestamp}\n${method}\n${path}\n${body}`;
    const signature = crypto
        .createHmac('sha256', secretKey)
        .update(stringToSign)
        .digest('hex');
    
    // Make request
    const headers = {
        'Content-Type': 'application/json',
        'X-Api-Key': publicKey,
        'X-Timestamp': timestamp,
        'X-Signature': `v1=${signature}`,
        'Idempotency-Key': idempotencyKey
    };
    
    try {
        const response = await axios.post(
            `${baseUrl}${path}`,
            orderData,
            { headers }
        );
        
        console.log('Status:', response.status);
        console.log('Response:', JSON.stringify(response.data, null, 2));
        return response.data;
    } catch (error) {
        console.error('Error:', error.response?.data || error.message);
        throw error;
    }
}

createOrder();

cURL

cURL Example
#!/bin/bash

# Configuration
PUBLIC_KEY="pk_test_pivohub"
SECRET_KEY="sk_test_secret_pivohub"
BASE_URL="http://localhost:5000"
TIMESTAMP=$(date +%s)
IDEMPOTENCY_KEY=$(uuidgen)

# Order data
ORDER_DATA='{
  "partner_order_id": "PH-2025-000123",
  "reference": "SO-55555",
  "service_level": "standard",
  "cod": {"amount_cents": 0, "currency": "CAD"},
  "insurance": {"amount_cents": 5000, "currency": "CAD"},
  "pickup": {
    "name": "Warehouse Montreal",
    "phone": "+1-514-555-0001",
    "email": "warehouse@company.com",
    "address": {
      "line1": "123 Main Street",
      "city": "Montréal",
      "province": "QC",
      "postal_code": "H1A1A1",
      "country": "CA"
    },
    "time_window": {
      "start": "2025-11-08T09:00:00-05:00",
      "end": "2025-11-08T12:00:00-05:00"
    }
  },
  "dropoff": {
    "name": "John Doe",
    "phone": "+1-438-555-0002",
    "email": "john.doe@customer.com",
    "address": {
      "line1": "789 Oak Avenue",
      "city": "Montréal",
      "province": "QC",
      "postal_code": "H2L1P1",
      "country": "CA"
    },
    "time_window": {
      "start": "2025-11-08T13:00:00-05:00",
      "end": "2025-11-08T17:00:00-05:00"
    }
  },
  "parcels": [{
    "parcel_id": "PKG-001",
    "description": "Electronics - Laptop",
    "length_cm": 40,
    "width_cm": 30,
    "height_cm": 25,
    "weight_kg": 5.5,
    "value_cents": 150000,
    "fragile": true,
    "barcode": "TRACK-12345"
  }],
  "instructions": "Call 10 minutes before arrival",
  "metadata": {
    "order_source": "web",
    "customer_id": "CUST-12345"
  }
}'

# Generate signature
STRING_TO_SIGN="${TIMESTAMP}\nPOST\n/v1/orders\n${ORDER_DATA}"
SIGNATURE=$(echo -n "$STRING_TO_SIGN" | openssl dgst -sha256 -hmac "$SECRET_KEY" | sed 's/^.* //')
SIGNATURE_HEADER="v1=${SIGNATURE}"

# Make request
curl -X POST "${BASE_URL}/v1/orders" \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: ${PUBLIC_KEY}" \
  -H "X-Timestamp: ${TIMESTAMP}" \
  -H "X-Signature: ${SIGNATURE_HEADER}" \
  -H "Idempotency-Key: ${IDEMPOTENCY_KEY}" \
  -d "${ORDER_DATA}"

Response

On success (201 Created), you'll receive the order details:

Success Response (201)
{
  "order_id": "dc_9f7a1f2e3d4c5b6a",
  "partner_order_id": "PH-2025-000123",
  "status": "accepted",
  "tracking_url": "https://dropcolis.ca/track/dc_9f7a1f2e3d4c5b6a",
  "created_at": "2025-11-08T10:30:00Z",
  "service_level": "standard",
  "pickup": { ... },
  "dropoff": { ... },
  "parcels": [ ... ],
  "estimated_delivery": "2025-11-09T17:00:00-05:00"
}

Error Responses

Best Practices

Next Steps

  1. Track Your Order: Use GET /v1/orders/{order_id} to check order status
  2. Set Up Webhooks: Configure webhook endpoints to receive status updates automatically
  3. View Full Documentation: Check out the Swagger UI for interactive API exploration
  4. Explore Other Endpoints: Learn about rate quotes, order cancellation, and more
Try in Swagger UI View API Reference