CROP
ProjectsCROP Frontend

Delivery API Testing Guide

This document provides testing instructions and curl examples for the CROP Delivery Services API.

Delivery API Testing Guide

Overview

This document provides testing instructions and curl examples for the CROP Delivery Services API.

API Base URL: https://delivery-service-222426967009.us-east1.run.app

Supported Providers:

  • ups - UPS shipping (requires credentials)
  • clinton_tractor - Local pickup/delivery (mock provider for testing)

CROP Source Identification

All shipments created through the CROP platform include source markers for identification:

FieldFormatExample
referenceCROP-{env}-{orderId}CROP-prod-ORD-12345
instructionsCROP-{env} | {notes}CROP-prod | Leave at door

Where {env} is one of: dev, stage, prod, unknown


API Endpoints

1. Health Check

Check if the API is running and connected to dependencies.

curl -s "https://delivery-service-222426967009.us-east1.run.app/health" | jq .

Response:

{
  "status": "healthy",
  "database": "connected",
  "providers": ["ups", "clinton_tractor"]
}

2. Get Providers

List available shipping providers.

curl -s "https://delivery-service-222426967009.us-east1.run.app/providers" | jq .

Response:

["ups", "clinton_tractor"]

3. Get Shipping Rates

Get shipping rates from all available providers.

curl -s -X POST "https://delivery-service-222426967009.us-east1.run.app/rates" \
  -H "Content-Type: application/json" \
  -d '{
    "from_address": {
      "name": "Clinton Tractor",
      "street": "6500 Collamer Road",
      "city": "East Syracuse",
      "state": "NY",
      "postal_code": "13057",
      "country": "US"
    },
    "to_address": {
      "name": "Test Customer",
      "street": "123 Main St",
      "city": "New York",
      "state": "NY",
      "postal_code": "10001",
      "country": "US"
    },
    "packages": [{
      "weight": 2,
      "length": 30,
      "width": 20,
      "height": 15,
      "value": 100
    }],
    "reference": "CROP-dev-TEST-001",
    "instructions": "CROP-dev | Test order"
  }' | jq .

Response:

[
  {
    "provider": "clinton_tractor",
    "service_type": "Clinton Tractor In-Store Pickup",
    "cost": 0.0,
    "currency": "USD",
    "estimated_days": 0,
    "estimated_date": null
  },
  {
    "provider": "ups",
    "service_type": "UPS Ground",
    "cost": 12.50,
    "currency": "USD",
    "estimated_days": 3,
    "estimated_date": "2026-01-24"
  }
]

Note: UPS rates require valid credentials configured in the backend.


4. Create Shipment

Create a new shipment with the selected provider.

curl -s -X POST "https://delivery-service-222426967009.us-east1.run.app/shipments?provider=clinton_tractor" \
  -H "Content-Type: application/json" \
  -d '{
    "from_address": {
      "name": "Clinton Tractor",
      "street": "6500 Collamer Road",
      "city": "East Syracuse",
      "state": "NY",
      "postal_code": "13057",
      "country": "US"
    },
    "to_address": {
      "name": "Test Customer",
      "street": "123 Main St",
      "city": "New York",
      "state": "NY",
      "postal_code": "10001",
      "country": "US"
    },
    "packages": [{
      "weight": 2,
      "length": 30,
      "width": 20,
      "height": 15,
      "value": 100
    }],
    "reference": "CROP-dev-ORDER-12345",
    "instructions": "CROP-dev | Please handle with care"
  }' | jq .

Response:

{
  "success": true,
  "shipment": {
    "shipment_id": "CT-CT-66532632",
    "tracking_number": "CT-66532632",
    "provider": "clinton_tractor",
    "status": "pending",
    "service_type": "Default",
    "label_url": null,
    "created_at": "2026-01-21T15:28:29.285124"
  },
  "message": "Shipment created successfully"
}

5. Track Shipment

Get tracking information for a shipment.

# Replace CT-66532632 with your tracking number
curl -s "https://delivery-service-222426967009.us-east1.run.app/shipments/CT-66532632" | jq .

Response:

{
  "tracking_number": "CT-66532632",
  "provider": "clinton_tractor",
  "status": "in_transit",
  "current_location": null,
  "estimated_delivery": "2026-01-23T15:28:38.255580",
  "events": [
    {
      "timestamp": "2026-01-20T15:28:38.255590",
      "location": "Clinton, IA",
      "description": "Shipment in transit"
    }
  ]
}

6. Cancel Shipment

Cancel an existing shipment.

# Replace CT-66532632 with your tracking number
curl -s -X POST "https://delivery-service-222426967009.us-east1.run.app/shipments/CT-66532632/cancel" | jq .

Response:

{
  "success": true,
  "message": "Shipment cancelled successfully"
}

7. Validate Address

Validate a shipping address using UPS Address Validation API.

curl -s -X POST "https://delivery-service-222426967009.us-east1.run.app/addresses/validate" \
  -H "Content-Type: application/json" \
  -d '{
    "street": "123 Main St",
    "city": "New York",
    "state": "NY",
    "postal_code": "10001",
    "country": "US"
  }' | jq .

Response:

{
  "is_valid": true,
  "candidates": [
    {
      "AddressKeyFormat": {
        "AddressLine": "123 MAIN ST",
        "PoliticalDivision2": "NEW YORK",
        "PoliticalDivision1": "NY",
        "PostcodePrimaryLow": "10001",
        "PostcodeExtendedLow": "1234",
        "CountryCode": "US"
      }
    }
  ]
}

Full Test Cycle Example

Run a complete create → track → cancel cycle:

#!/bin/bash
# Full delivery API test cycle

API_URL="https://delivery-service-222426967009.us-east1.run.app"

echo "=== 1. Health Check ==="
curl -s "$API_URL/health" | jq .

echo -e "\n=== 2. Get Rates ==="
RATES=$(curl -s -X POST "$API_URL/rates" \
  -H "Content-Type: application/json" \
  -d '{
    "from_address": {"name":"Clinton Tractor","street":"6500 Collamer Road","city":"East Syracuse","state":"NY","postal_code":"13057","country":"US"},
    "to_address": {"name":"Test","street":"123 Main St","city":"New York","state":"NY","postal_code":"10001","country":"US"},
    "packages": [{"weight":2,"length":30,"width":20,"height":15}],
    "reference": "CROP-dev-FULLTEST",
    "instructions": "CROP-dev | Full test cycle"
  }')
echo "$RATES" | jq .

echo -e "\n=== 3. Create Shipment ==="
SHIPMENT=$(curl -s -X POST "$API_URL/shipments?provider=clinton_tractor" \
  -H "Content-Type: application/json" \
  -d '{
    "from_address": {"name":"Clinton Tractor","street":"6500 Collamer Road","city":"East Syracuse","state":"NY","postal_code":"13057","country":"US"},
    "to_address": {"name":"Test","street":"123 Main St","city":"New York","state":"NY","postal_code":"10001","country":"US"},
    "packages": [{"weight":2,"length":30,"width":20,"height":15}],
    "reference": "CROP-dev-FULLTEST",
    "instructions": "CROP-dev | Full test cycle"
  }')
echo "$SHIPMENT" | jq .

# Extract tracking number
TRACKING=$(echo "$SHIPMENT" | jq -r '.shipment.tracking_number')
echo -e "\nTracking Number: $TRACKING"

echo -e "\n=== 4. Track Shipment ==="
curl -s "$API_URL/shipments/$TRACKING" | jq .

echo -e "\n=== 5. Cancel Shipment ==="
curl -s -X POST "$API_URL/shipments/$TRACKING/cancel" | jq .

echo -e "\n=== Test Complete ==="

Error Responses

422 Validation Error

{
  "detail": [
    {
      "loc": ["body", "from_address", "postal_code"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

404 Not Found

{
  "detail": "Shipment not found"
}

500 Internal Server Error

{
  "detail": "Internal server error"
}

Integration Tests

Run the integration tests:

bun test lib/delivery-api/__tests__/delivery-api.integration.test.ts

  • Frontend client: lib/delivery-api/client.ts
  • Source markers: lib/delivery-api/source-marker.ts
  • Types: lib/delivery-api/types.ts
  • Unit tests: lib/delivery-api/source-marker.test.ts

Commits

CommitDescription
1d508ddAdd CROP source identification to shipment requests
283ce6cFix lint/typecheck errors
ad984a3Add double-marker protection and unit tests

Notes

  1. Clinton Tractor is a mock provider for testing. It simulates shipment creation, tracking, and cancellation without real carrier integration.

  2. UPS Integration requires valid credentials:

    • UPS_CLIENT_ID
    • UPS_CLIENT_SECRET
    • UPS_ACCOUNT_NUMBER
  3. CROP Markers are passed to the backend but the backend task to use them in tracking numbers is pending. See docs/backend-tasks/CROP_SOURCE_IDENTIFICATION.md.

On this page