<!-- SME [2026-07-03] Asset GPS multi-tenant admin docs index -->
<!-- SME [2026-06-30] Document continuous background tracking in API export -->
<!-- SME [2026-06-29] Streamline shipper visibility UI -->
<!-- SME [2026-06-29] Add shipper credential portal -->
<!-- SME [2026-06-28] Add unified shipper visibility V1 -->
<!-- SME [2026-06-28] Add Samsara GPS provider V1 -->
<!-- SME [2026-06-28] Document GPS provider framework -->
<!-- SME [2026-06-28] Export CheckPoint inbound API developer document -->

# CheckPoint Inbound API Developer Export

## Purpose

This standalone document is for developers building an inbound API connection from an external TMS into Exspeedite CheckPoint. It covers the server-to-server load initialize endpoint, the JSON contract, validation errors, examples, and the surrounding integration expectations.

This is the copy/share version of the API documentation. It is documentation only and does not change CheckPoint runtime behavior.

## Related Documents

- [CheckPoint GPS Provider Framework](checkpoint_gps_provider_framework.md): strategy for provider-agnostic GPS automation, starting with Samsara and Motive, including vehicle mapping, polling, webhooks, geofence ownership, and state-aware event translation. PeopleNet planned.
- Asset GPS admin UI (not part of inbound TMS API): `/gps-integrations.php` — per-company Samsara/Motive credentials, vehicle mapping, ELD refresh. Permissions and schema: `track/developers.php#asset-gps` and `track/dev/checkpoint_schema.html#gps-provider-integrations`.
- Continuous Background Tracking add-on (native driver app): tenant must enable in Settings Hub; dispatch with `tracking_mode: "continuous"`. Driver APIs documented on `track/developers.php#continuous-tracking`. Full spec: `docs/private/continuous_background_tracking_addon_spec.md`.
- [CheckPoint Unified Shipper Visibility Platform Spec](checkpoint_unified_shipper_visibility_spec.md): enterprise shipper portal/API spec for shipment-centric multi-carrier visibility, HMAC access, privacy controls, and active-load cutoff rules.

## Base URL and Primary Endpoint

Base URL:

```text
https://exspeeditecheckpoint.com
```

Primary inbound endpoint:

```text
POST /v1/tracking/initialize.php
```

Full URL:

```text
https://exspeeditecheckpoint.com/v1/tracking/initialize.php
```

The endpoint accepts one load per request. The body should be JSON and must include an ordered `stops` array.

## Authentication

Every request must include a tenant-scoped bearer token generated for the CheckPoint company workspace.

```http
Authorization: Bearer YOUR_CHECKPOINT_TOKEN
Content-Type: application/json
```

Authentication is server-side only. Do not put the bearer token in browser JavaScript, desktop UI code, mobile app code, or any client-facing TMS page. A TMS button such as "Send to CheckPoint" should call the TMS backend, and the backend should add the bearer token before posting to CheckPoint.

CheckPoint stores the hash of the bearer token and updates the API client's `last_used_at` timestamp after successful authentication.

## Unified Shipper Visibility API V1

Enterprise shippers can poll active shipments across carriers with HMAC authentication. This API is shipment-centric only: it never exposes empty truck movement, delivered/cancelled/unassigned loads, driver phone/name, rates, broker fields, internal notes, or raw provider payloads.

Endpoint:

```http
GET /api/v1/shipper/active-shipments.php
```

Compatibility path when the `track` folder is the web docroot:

```http
GET /v1/shipper/active-shipments.php
```

Required headers:

```http
X-Shipper-UUID: 7d62d2c5-5e67-4e20-9e34-0a2c0f64d812
X-Timestamp: 2026-06-28T23:39:00Z
X-Signature: hex_hmac_sha256
```

Canonical signing string:

```text
METHOD + "\n" +
PATH + "\n" +
CANONICAL_QUERY + "\n" +
X_TIMESTAMP + "\n" +
SHA256_HEX(BODY)
```

Credential ownership is split deliberately: carrier admins use the public `X-Shipper-UUID` to tag eligible loads, while shipper admins sign in at `/shipper-login.php` to manage their private API secret. Carrier workspaces never see or rotate the shipper API secret.

For this V1 implementation, CheckPoint shows the raw shipper API secret once in the Shipper Portal on rotation, stores only `SHA256(secret)`, and verifies `X-Signature` using `SHA256(secret)` as the HMAC key. Clients should compute `secret_key = SHA256(one_time_secret)` and then sign the canonical string with HMAC-SHA256. Timestamps older than five minutes are rejected.

Carrier admins do not need this contract on the operational Shipper Visibility page. They link local customer names to global shippers, preview the portal, and copy a 24-hour preview/share URL from the Carrier / Shipper Links table.

### HMAC Code Samples

PHP:

```php
$secret = getenv('CHECKPOINT_SHIPPER_SECRET');
$shipperUuid = getenv('CHECKPOINT_SHIPPER_UUID');
$path = '/api/v1/shipper/active-shipments.php';
$timestamp = gmdate('Y-m-d\TH:i:s\Z');
$body = '';
$canonical = "GET\n{$path}\n\n{$timestamp}\n" . hash('sha256', $body);
$signingKey = hash('sha256', $secret);
$signature = hash_hmac('sha256', $canonical, $signingKey);
```

Python:

```python
import datetime, hashlib, hmac, os

secret = os.environ["CHECKPOINT_SHIPPER_SECRET"]
path = "/api/v1/shipper/active-shipments.php"
timestamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
body = b""
canonical = f"GET\n{path}\n\n{timestamp}\n{hashlib.sha256(body).hexdigest()}"
signing_key = hashlib.sha256(secret.encode()).hexdigest().encode()
signature = hmac.new(signing_key, canonical.encode(), hashlib.sha256).hexdigest()
```

Node:

```js
import crypto from "node:crypto";

const secret = process.env.CHECKPOINT_SHIPPER_SECRET;
const path = "/api/v1/shipper/active-shipments.php";
const timestamp = new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
const body = "";
const canonical = `GET\n${path}\n\n${timestamp}\n${crypto.createHash("sha256").update(body).digest("hex")}`;
const signingKey = crypto.createHash("sha256").update(secret).digest("hex");
const signature = crypto.createHmac("sha256", signingKey).update(canonical).digest("hex");
```

Optional initialize/manual/CSV load fields:

| Field | Type | Description |
| --- | --- | --- |
| `global_shipper_uuid` | string | Optional global shipper UUID that binds this load to the shipper API while active. |
| `shipper_reference` | string | Optional PO, BOL, order, or customer reference returned to the shipper. |
| `shipper_visibility_enabled` | boolean | Optional kill switch. Defaults on when `global_shipper_uuid` is provided. |

Sample request:

```bash
CANONICAL=$'GET\n/api/v1/shipper/active-shipments.php\n\n2026-06-28T23:39:00Z\ne3b0c44298fc1c149afbf4c8996fb924...'
SIGNATURE=$(printf "%s" "$CANONICAL" | openssl dgst -sha256 -hmac "$SHA256_SECRET_KEY" -hex | awk '{print $2}')

curl "https://exspeeditecheckpoint.com/api/v1/shipper/active-shipments.php" \
  -H "X-Shipper-UUID: 7d62d2c5-5e67-4e20-9e34-0a2c0f64d812" \
  -H "X-Timestamp: 2026-06-28T23:39:00Z" \
  -H "X-Signature: $SIGNATURE"
```

Sample response:

```json
{
  "shipper_uuid": "7d62d2c5-5e67-4e20-9e34-0a2c0f64d812",
  "generated_at": "2026-06-28T23:39:00Z",
  "shipments": [
    {
      "shipment_id": "EXP-10001",
      "load_number": "EXP-10001",
      "shipper_reference": "PO 4500099123",
      "carrier_name": "Example Carrier LLC",
      "status": "in_transit",
      "visibility_state": "active",
      "origin": { "name": "Pickup DC", "city": "Anoka", "state": "MN", "scheduled_at": "2026-06-29T13:00:00Z" },
      "destination": { "name": "Receiving", "city": "Dallas", "state": "TX", "scheduled_at": "2026-06-30T18:00:00Z" },
      "current_location": { "lat": 41.8781, "lng": -87.6298, "timestamp": "2026-06-28T23:37:12Z", "freshness": "fresh", "source": "provider_gps" },
      "eta": { "estimated_arrival_at": "2026-06-30T17:20:00Z", "confidence": "medium", "status": "unknown" }
    }
  ],
  "correlation_id": "shp_20260628233900_ab12cd34ef56"
}
```

Visibility rules:

- Only `track_load_snapshots.status = active` is returned.
- `shipper_visibility_enabled = 0`, missing `global_shipper_uuid`, completed, cancelled, closed, delivered, expired, and unassigned loads are omitted.
- Provider GPS is shown only when matched to an active visible load by `tms_vehicle_id` or `power_unit`.
- Every API request is written to `global_shipper_api_log` without storing secret material.

HMAC errors:

| HTTP | Error code | Meaning |
| --- | --- | --- |
| `401` | `MISSING_HMAC_HEADERS` | Missing `X-Shipper-UUID`, `X-Timestamp`, or `X-Signature`. |
| `401` | `INVALID_SHIPPER_UUID` | The shipper UUID is not valid UUID format. |
| `401` | `EXPIRED_HMAC_TIMESTAMP` | The timestamp is outside the five-minute replay window. |
| `401` | `SHIPPER_NOT_ACTIVE` | The global shipper is disabled or not found. |
| `403` | `INVALID_HMAC_SIGNATURE` | The signature is not a 64-character lowercase hex HMAC. |
| `403` | `HMAC_SIGNATURE_MISMATCH` | The canonical string or signing key does not match CheckPoint. |

## Quickstart Flow

1. Generate or receive the CheckPoint API bearer token for the correct client workspace.
2. Store the token in a server-side secret store or environment variable.
3. Add a TMS backend action that builds one load payload.
4. Choose `direct_driver` when the TMS has the driver phone, or `private_link` when the carrier/driver should enter it privately.
5. Validate required fields, E.164 phone format, stop sequence, milestone type, location name, city, and state before sending.
6. POST JSON to `https://exspeeditecheckpoint.com/v1/tracking/initialize.php`.
7. Store the response and log `error_code`, `message`, and `details` for failed requests.
8. Optionally subscribe to Integration Events so CheckPoint can call back to the TMS as the load progresses.

## Payload Contract

### Top-Level Required Fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `load_number` | string | Yes | TMS load, shipment, order, or pro number. Must be unique while active for the tenant. |
| `carrier_name` | string | Yes | Carrier or vendor name shown in CheckPoint. |
| `stops` | array | Yes | Non-empty ordered array of stop objects. |
| `driver_name` | string | Conditional | Required for `direct_driver`; optional for `private_link`. |
| `driver_phone` | string | Conditional | Required for `direct_driver`; must be E.164, for example `+13125550119`. Do not send for `private_link`. |
| `tms_vehicle_id` | string | Optional | TMS tractor, vehicle, or power-unit identifier used to match mapped GPS provider telemetry (Samsara or Motive after admin mapping). |
| `power_unit` | string | Optional | Alias/display value for the tractor or power unit. CheckPoint can use it as a secondary provider GPS matching key. |

### Direct-Driver Mode

Use direct-driver mode when the TMS has the driver's phone number and is allowed to send it to CheckPoint.

```json
{
  "driver_assignment_mode": "direct_driver",
  "driver_name": "Maria Santos",
  "driver_phone": "+13125550119"
}
```

If `driver_assignment_mode` is omitted and `driver_phone` is present, CheckPoint treats the request as direct-driver mode. New integrations should still send `driver_assignment_mode` explicitly.

In direct-driver mode, CheckPoint creates the tracking token and immediately attempts to send the first tracking SMS.

### Private-Link Mode

Use private-link mode when the broker or dispatcher should not receive or transmit the driver's phone number.

```json
{
  "driver_assignment_mode": "private_link",
  "carrier_contact_email": "dispatch@carrier.example"
}
```

In private-link mode, CheckPoint creates the load, returns `assignment_url`, and emails the assignment link when a valid recipient exists. The carrier or driver enters the driver name and phone on a token-gated CheckPoint page. SMS is sent only after that private assignment is completed.

`carrier_contact_email` is recommended. If it is missing, CheckPoint can fall back to `notification_emails` for the assignment email.

### Continuous Background GPS (add-on)

Default tracking remains **ping** (web link, no app). Continuous mode is optional per load when the tenant has enabled the add-on in CheckPoint Settings Hub.

| Field | Type | Description |
| --- | --- | --- |
| `tracking_mode` | string | `ping` (default) or `continuous`. |
| `background_ping_interval_seconds` | integer | Optional per-load override, 10–900 seconds. Uses tenant default (usually 60) when omitted. |

```json
{
  "load_number": "TMS-104901",
  "carrier_name": "Blue River Transport",
  "driver_name": "Alex Driver",
  "driver_phone": "+13125550119",
  "tracking_mode": "continuous",
  "background_ping_interval_seconds": 60,
  "stops": [ "... ordered stops ..." ]
}
```

TMS connectors only set these fields on initialize. Background GPS is posted by the CheckPoint driver app to `POST /v1/tracking/background-ping.php` using the load token — not by the TMS server. Milestone web check-in via `ping.php` still works on continuous loads.

Driver deep link for app onboarding: `checkpoint://track?token={64_hex}` (extract token from `tracking_url`).

### Rich Load Fields

Optional rich load fields accepted by the endpoint:

| Field | Type | Description |
| --- | --- | --- |
| `reference_numbers` | string or array | BOL, PO, shipment, order, customer reference, or other identifiers. Arrays are stored as comma-separated text. |
| `commodity_description` | string | Freight description. |
| `total_weight_lbs` | number | Total weight in pounds. |
| `piece_count` | integer | Piece count. |
| `pallet_count` | integer | Pallet or skid count. |
| `freight_dimensions` | string | Dimensions, cube, stackability, or freight shape notes. |
| `freight_class` | string | LTL freight class. |
| `nmfc_number` | string | NMFC number. |
| `special_properties` | string | Hazmat, reefer, fragile, temperature, odor, or other special properties. |
| `trailer_type` | string | Dry van, reefer, flatbed, box truck, or similar. |
| `equipment_specs` | string | Length, doors, liftgate, air-ride, food-grade, or other equipment details. |
| `driver_assist` | string | Driver assist, count, unload, or labor requirements. |
| `securement_requirements` | string | Tarping, straps, chains, load bars, blankets, or similar. |
| `onboard_tools` | string | Pallet jack, PPE, load locks, straps, or other tools. |
| `detention_layover_terms` | string | Free time, detention, layover, or accessorial terms. |
| `tracking_expectations` | string | Check-in cadence, photo expectations, call-ahead, or customer visibility notes. |
| `routing_hos_notes` | string | Routing, hours-of-service, or team-driver notes. |
| `team_driver_required` | boolean | Stored as a load flag. |
| `required_paperwork` | string | BOL, POD, seal paperwork, weight tickets, photos, or other required documents. |
| `special_instructions` | string | Load-level instructions or site rules. |
| `broker_name` | string | Internal dispatcher/broker context only. |
| `broker_contact` | string | Internal dispatcher/broker context only. |

Important: `broker_name` and `broker_contact` are internal CheckPoint fields. They are not exposed to driver pages, public share payloads, or current customer-facing Integration Events.

### Custom User Fields

CheckPoint supports ten tenant-configurable custom fields:

```text
user1, user2, user3, user4, user5, user6, user7, user8, user9, user10
```

Payload keys stay stable as `user1` through `user10`. Display labels are configured per tenant in Company Profile and are used by customer-facing outputs that include custom fields.

Preferred simple form:

```json
{
  "user1": "Retail division 42",
  "user2": "Customer PO 77219",
  "user3": "TMS lane CHI-DAL"
}
```

The endpoint also accepts nested `custom_fields` as an object or as an array of `{ "key": "...", "value": "..." }` objects.

Custom user fields are customer-safe only if the tenant puts customer-safe data in them. Do not send passwords, API keys, SSNs, payment data, bank data, medical data, or other sensitive regulated data in `user1` through `user10`.

### Notification Email Preferences

Email notifications are opt-in. CheckPoint sends no regular load notification emails unless `notification_emails` includes valid recipients and at least one email preference is true.

| Field | Type | Description |
| --- | --- | --- |
| `notification_emails` | array or comma-separated string | Recipients for requested notifications. Invalid email values are ignored. |
| `email_notifications.load` | boolean | Email when the load is created. |
| `email_notifications.pickup` | boolean | Email when pickup is completed. |
| `email_notifications.stopoffs` | boolean | Email when a `transit` stop-off is completed. |
| `email_notifications.checkpoints` | boolean | Email for every driver checkpoint. |
| `email_notifications.delivered` | boolean | Email when final delivery is completed. |

Legacy top-level booleans are also accepted: `email_load`, `email_pickup`, `email_stopoffs`, `email_checkpoints`, and `email_delivered`. New integrations should use the nested `email_notifications` object.

### Stop Array Requirements

`stops` must be a JSON array with at least one object. Each stop must include:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `stop_sequence` | integer | Yes | 1-based stop order. Must be `1` or greater. |
| `milestone_type` | string | Yes | One of `pickup`, `transit`, or `delivery`. |
| `location_name` | string | Yes | Facility, shipper, consignee, crossdock, or safe fallback name. |
| `city` | string | Yes | Stop city. |
| `state` | string | Yes | Stop state or region. Two-letter state code recommended. |

Use `transit` for stop-offs, crossdocks, partial deliveries, check calls, and other intermediate stops.

Optional stop fields:

| Field | Type | Description |
| --- | --- | --- |
| `address1` | string | Street address. |
| `zip` | string | Postal code. |
| `scheduled_at` | string | Date/time. ISO 8601 recommended. |
| `time_window_start` / `window_start` | string | Appointment or receiving window start. |
| `time_window_end` / `window_end` | string | Appointment or receiving window end. |
| `appointment_type` / `appointment_status` | string | Appointment, FCFS, call-for-appointment, or similar. |
| `load_unload_type` / `loading_type` / `unloading_type` | string | Live, drop, preloaded, unload type, or similar. |
| `facility_hours` | string | Facility hours. |
| `appointment_process` | string | Appointment or check-in process. |
| `dock_instructions` | string | Dock, guard shack, or check-in instructions. |
| `access_rules` | string | Gate, PPE, security, parking, or access rules. |
| `stop_restrictions` / `restrictions` | string | Stop restrictions. |
| `driver_instructions` / `instructions` | string | Driver-facing instructions. |

## Validation and Error Dictionary

Error response shape:

```json
{
  "success": false,
  "error_code": "INVALID_STOP_MILESTONE_TYPE",
  "message": "Stop 2 milestone_type must be pickup, transit, or delivery.",
  "details": {
    "stop_sequence": 2,
    "field": "milestone_type",
    "allowed": ["pickup", "transit", "delivery"]
  }
}
```

| HTTP | Error code | Cause | Fix |
| --- | --- | --- | --- |
| `401` | `INVALID_BEARER_TOKEN` | Token is missing, invalid, inactive, expired, or from another workspace. | Verify the company token and send it as `Authorization: Bearer ...` from server-side code. |
| `400` | `MISSING_MANDATORY_FIELDS` | Required top-level fields are missing. `details.missing_fields` lists exact fields. | Send `load_number`, `carrier_name`, and `stops`. In direct-driver mode also send `driver_name` and `driver_phone`. |
| `400` | `INVALID_DRIVER_ASSIGNMENT_MODE` | `driver_assignment_mode` is not `direct_driver` or `private_link`. | Send one of the two allowed values. |
| `400` | `INVALID_DRIVER_PHONE` | Direct-driver mode has a blank or non-E.164 `driver_phone`. | Normalize to E.164 before posting, for example `+13125550119`. |
| `400` | `INVALID_STOPS_PAYLOAD` | `stops` is missing, empty, not an array, or contains a non-object stop. | Send `stops` as a JSON array of stop objects and log the raw outbound request body. |
| `400` | `INVALID_STOP_SEQUENCE` | A stop has a missing, zero, negative, or non-numeric `stop_sequence`. | Send 1-based integer stop sequences starting at `1`. |
| `400` | `INVALID_STOP_MILESTONE_TYPE` | A stop is missing `milestone_type` or uses an invalid value. | Send `pickup`, `transit`, or `delivery`. Map stop-offs to `transit`; do not send only a local `type` field. |
| `400` | `MISSING_STOP_LOCATION_NAME` | A stop has blank `location_name`. | Send facility, shipper, consignee, crossdock, or a fallback like `Transit Stop`. |
| `400` | `MISSING_STOP_CITY_STATE` | A stop is missing `city`, `state`, or both. | Populate city and state for every stop. |
| `409` | `LOAD_ALREADY_ACTIVE` | The same `load_number` is already active for the same tenant. | Close/cancel the active load or send a unique load number. |
| `500` | `SERVER_ERROR` | Unexpected server exception. | Retry later if appropriate and contact support with load number, timestamp, and connector logs. |

Treat HTTP `400` validation responses as non-retryable until the outbound JSON changes. Treat `409` as a business conflict. Retry only network failures and selected server failures with backoff.

## Examples

### Direct-Driver Minimal JSON

```json
{
  "load_number": "TMS-104482",
  "carrier_name": "Blue River Transport",
  "driver_assignment_mode": "direct_driver",
  "driver_name": "Maria Santos",
  "driver_phone": "+13125550119",
  "stops": [
    {
      "stop_sequence": 1,
      "milestone_type": "pickup",
      "location_name": "Exspeedite Chicago DC",
      "city": "Chicago",
      "state": "IL"
    },
    {
      "stop_sequence": 2,
      "milestone_type": "delivery",
      "location_name": "Dallas Retail Pool",
      "city": "Dallas",
      "state": "TX"
    }
  ]
}
```

### Private-Link Minimal JSON

```json
{
  "load_number": "TMS-104483",
  "carrier_name": "Blue River Transport",
  "driver_assignment_mode": "private_link",
  "carrier_contact_email": "dispatch@blueriver.example",
  "stops": [
    {
      "stop_sequence": 1,
      "milestone_type": "pickup",
      "location_name": "Exspeedite Chicago DC",
      "city": "Chicago",
      "state": "IL"
    },
    {
      "stop_sequence": 2,
      "milestone_type": "delivery",
      "location_name": "Dallas Retail Pool",
      "city": "Dallas",
      "state": "TX"
    }
  ]
}
```

### Multi-Shipment / Multi-Stop Flattened Stop List

When a TMS has multiple shipments, pickups, deliveries, or stop-offs under one tracked load, flatten them into one ordered `stops` array.

```json
{
  "load_number": "TMS-204900",
  "carrier_name": "Roadstar Carrier Inc.",
  "driver_assignment_mode": "private_link",
  "carrier_contact_email": "dispatch@roadstar.example",
  "reference_numbers": ["Shipment A: SHP-1001", "Shipment B: SHP-1002"],
  "stops": [
    {
      "stop_sequence": 1,
      "milestone_type": "pickup",
      "location_name": "Chicago Plant 1",
      "city": "Chicago",
      "state": "IL",
      "scheduled_at": "2026-07-01T13:00:00Z",
      "driver_instructions": "Pickup Shipment A."
    },
    {
      "stop_sequence": 2,
      "milestone_type": "pickup",
      "location_name": "Joliet Warehouse",
      "city": "Joliet",
      "state": "IL",
      "scheduled_at": "2026-07-01T16:00:00Z",
      "driver_instructions": "Pickup Shipment B."
    },
    {
      "stop_sequence": 3,
      "milestone_type": "transit",
      "location_name": "Memphis Crossdock",
      "city": "Memphis",
      "state": "TN",
      "scheduled_at": "2026-07-02T03:00:00Z",
      "driver_instructions": "Stop-off: unload 6 pallets and get dock receipt."
    },
    {
      "stop_sequence": 4,
      "milestone_type": "delivery",
      "location_name": "Dallas Retail Pool",
      "city": "Dallas",
      "state": "TX",
      "scheduled_at": "2026-07-02T16:30:00Z"
    }
  ]
}
```

### Rich Payload Example

```json
{
  "load_number": "TMS-104482",
  "carrier_name": "Blue River Transport",
  "driver_assignment_mode": "direct_driver",
  "driver_name": "Maria Santos",
  "driver_phone": "+13125550119",
  "driver_email": "maria.santos@example.com",
  "reference_numbers": "BOL 88421, PO 77219",
  "commodity_description": "Packaged retail goods",
  "total_weight_lbs": 38250,
  "piece_count": 440,
  "pallet_count": 22,
  "freight_dimensions": "22 standard pallets, non-stackable",
  "trailer_type": "53 dry van",
  "equipment_specs": "Swing doors, food-grade trailer",
  "driver_assist": "Driver count required at delivery",
  "required_paperwork": "Signed BOL and POD with signature/time/photo",
  "special_instructions": "No stacking. Report damage before departure.",
  "broker_name": "Northstar Brokerage",
  "broker_contact": "ops@northstar.example, 312-555-0199",
  "user1": "Retail division 42",
  "user2": "Customer PO 77219",
  "user3": "TMS lane CHI-DAL",
  "notification_emails": ["ops@example.com", "customer@example.com"],
  "email_notifications": {
    "load": true,
    "pickup": true,
    "stopoffs": true,
    "checkpoints": false,
    "delivered": true
  },
  "stops": [
    {
      "stop_sequence": 1,
      "milestone_type": "pickup",
      "location_name": "Exspeedite Chicago DC",
      "address1": "1200 W Logistics Way",
      "city": "Chicago",
      "state": "IL",
      "zip": "60632",
      "scheduled_at": "2026-06-25T14:00:00Z",
      "time_window_end": "2026-06-25T16:00:00Z",
      "appointment_type": "appointment",
      "load_unload_type": "live",
      "facility_hours": "0800-1700",
      "dock_instructions": "Check in at guard shack, use dock 12"
    },
    {
      "stop_sequence": 2,
      "milestone_type": "transit",
      "location_name": "Memphis Crossdock",
      "address1": "88 Riverport Rd",
      "city": "Memphis",
      "state": "TN",
      "zip": "38118",
      "scheduled_at": "2026-06-26T03:00:00Z",
      "driver_instructions": "Stop-off: unload 6 pallets and get dock receipt."
    },
    {
      "stop_sequence": 3,
      "milestone_type": "delivery",
      "location_name": "Dallas Retail Pool",
      "address1": "4400 Distribution Dr",
      "city": "Dallas",
      "state": "TX",
      "zip": "75241",
      "scheduled_at": "2026-06-26T16:30:00Z"
    }
  ]
}
```

### cURL Example

```bash
curl -X POST "https://exspeeditecheckpoint.com/v1/tracking/initialize.php" \
  -H "Authorization: Bearer YOUR_CHECKPOINT_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "load_number": "TMS-104482",
    "carrier_name": "Blue River Transport",
    "driver_assignment_mode": "direct_driver",
    "driver_name": "Maria Santos",
    "driver_phone": "+13125550119",
    "stops": [
      {
        "stop_sequence": 1,
        "milestone_type": "pickup",
        "location_name": "Exspeedite Chicago DC",
        "city": "Chicago",
        "state": "IL"
      },
      {
        "stop_sequence": 2,
        "milestone_type": "delivery",
        "location_name": "Dallas Retail Pool",
        "city": "Dallas",
        "state": "TX"
      }
    ]
  }'
```

## Expected Success Responses and HTTP Statuses

Successful initialize requests return HTTP `200`.

Direct-driver response example:

```json
{
  "success": true,
  "status": "initialized",
  "load_number": "TMS-104482",
  "sms_sent": true,
  "email_sent": false,
  "email_requested": false,
  "email_recipients": 0,
  "driver_assignment_status": "assigned",
  "assignment_email_sent": false,
  "assignment_email_recipients": 0,
  "planned_route": null,
  "tracking_url": "https://exspeeditecheckpoint.com/tracking/start.php?token=...&milestone=pickup&stop=1"
}
```

Private-link response example:

```json
{
  "success": true,
  "status": "initialized",
  "load_number": "TMS-104483",
  "sms_sent": false,
  "email_sent": false,
  "email_requested": false,
  "email_recipients": 0,
  "driver_assignment_status": "pending_assignment",
  "assignment_email_sent": true,
  "assignment_email_recipients": 1,
  "planned_route": null,
  "assignment_url": "https://exspeeditecheckpoint.com/carrier/assign.php?token=..."
}
```

Response notes:

- `sms_sent` reports whether the initial driver SMS send attempt succeeded.
- `email_sent` covers requested load-created notification email, not private assignment email.
- `assignment_email_sent` covers private-link assignment email delivery attempts.
- `tracking_url` is returned for direct-driver mode.
- `assignment_url` is returned for private-link mode.
- `planned_route` may be `null` or may contain route enrichment fields when available.

## What the TMS Should Not Call Directly

External TMS developers should only call the server-to-server initialize endpoint unless CheckPoint explicitly documents another endpoint for the integration.

Do not call these directly from the TMS connector:

- Driver pages such as `/tracking/start.php` except by opening the returned `tracking_url` for a human driver.
- Driver load-info endpoints such as `/v1/tracking/load-info.php` (driver app only).
- Driver ping/checkpoint endpoints such as `/v1/tracking/ping.php` (driver browser/app).
- Driver background GPS endpoint `/v1/tracking/background-ping.php` (native app only).
- Admin endpoints under `/v1/admin/`.
- Dashboard endpoints under `/v1/dashboard/`.
- Share endpoints under `/v1/share/` except by opening a returned share URL for a viewer.

CheckPoint owns driver tracking links, GPS check-ins, milestone advancement, dashboard data, private assignment pages, SMS delivery, and load completion workflow after initialization.

## Outbound Integration Events

Integration Events are outbound from CheckPoint to the TMS or customer endpoints. They are not part of "API into CheckPoint", but developers usually need the round-trip picture.

CheckPoint can fire transportation-style status updates for events including:

```text
dispatched, picked_up, arrived_stop, delivered, pod_submitted,
eta_updated, geofence_arrival, exception_alert, status_update
```

Supported output channels include email, secure JSON webhook, or both depending on subscription settings. The payload is a 214-style visibility update, not formal EDI 214.

Webhook receiver requirements:

- Use an HTTPS endpoint.
- Accept `POST` with `Content-Type: application/json`.
- Return a `2xx` status for success.
- If an auth token is configured in CheckPoint, expect `Authorization: Bearer <token>`.
- Make the receiver idempotent by `load_number`, `event_type`, and status timestamp.
- Do not require broker/internal fields. `broker_name` and `broker_contact` are intentionally excluded from customer-facing Integration Events.

Example outbound webhook shape:

```json
{
  "output_type": "214_style_visibility",
  "message_type": "transportation_style_status_update",
  "event_type": "arrived_stop",
  "load_number": "TMS-104482",
  "status": {
    "code": "X1",
    "label": "Arrived at stop",
    "description": "Driver arrived at Stop / Stop-off",
    "timestamp_utc": "2026-06-26T03:05:00+00:00"
  },
  "load": {
    "load_number": "TMS-104482",
    "carrier_name": "Blue River Transport",
    "reference_numbers": "BOL 88421, PO 77219",
    "commodity_description": "Packaged retail goods",
    "custom_fields": [
      { "key": "user1", "label": "Division", "value": "Retail division 42" }
    ],
    "stops": [
      { "stop_sequence": 1, "milestone_type": "pickup", "location_name": "Exspeedite Chicago DC" },
      { "stop_sequence": 2, "milestone_type": "transit", "location_name": "Memphis Crossdock" },
      { "stop_sequence": 3, "milestone_type": "delivery", "location_name": "Dallas Retail Pool" }
    ],
    "eta_at": "2026-06-26T16:30:00+00:00",
    "share_url": "https://exspeeditecheckpoint.com/share.php?token=..."
  },
  "current_location": {
    "lat": 35.1495,
    "lng": -90.049,
    "milestone_type": "transit",
    "stop_sequence": 2,
    "timestamp_utc": "2026-06-26T03:05:00+00:00"
  },
  "context": {
    "source": "checkpoint"
  }
}
```

## Logging, Audit, and Security Recommendations

- Store bearer tokens in a server-side secret manager or environment variable.
- Log the CheckPoint HTTP status, `error_code`, `message`, and `details`.
- Log a sanitized copy of outbound JSON for failed validation, but never log bearer tokens or full driver phone numbers.
- Normalize driver phones to E.164 before posting.
- Use unique, stable `load_number` values that dispatchers recognize.
- Treat HTTP `400` as a payload defect, HTTP `409` as an active-load conflict, and HTTP `500` as a server failure.
- Use exponential backoff for network failures and selected `500` errors.
- Do not send secrets, SSNs, payment data, or regulated data in custom user fields.
- Keep `broker_name` and `broker_contact` internal and do not expect them in customer-facing outbound payloads.

## QA Acceptance Checklist

Use this checklist before production traffic:

- Direct-driver minimal payload returns HTTP `200`.
- Direct-driver response includes `tracking_url`.
- Direct-driver phone is normalized to E.164 and the first SMS is attempted.
- Private-link minimal payload returns HTTP `200`.
- Private-link response includes `assignment_url`.
- Private-link SMS is not sent until the private assignment is completed.
- A multi-stop payload with pickup, `transit`, and delivery returns HTTP `200`.
- Missing `load_number` returns `MISSING_MANDATORY_FIELDS`.
- Invalid bearer token returns HTTP `401` and `INVALID_BEARER_TOKEN`.
- Formatted direct-driver phone returns `INVALID_DRIVER_PHONE`.
- Empty or non-array `stops` returns `INVALID_STOPS_PAYLOAD`.
- Invalid stop sequence returns `INVALID_STOP_SEQUENCE`.
- Invalid stop milestone returns `INVALID_STOP_MILESTONE_TYPE`.
- Blank stop location returns `MISSING_STOP_LOCATION_NAME`.
- Missing stop city or state returns `MISSING_STOP_CITY_STATE`.
- Re-sending the same active `load_number` returns HTTP `409` and `LOAD_ALREADY_ACTIVE`.
- Logs show request status without exposing bearer tokens or full driver phone numbers.
- If Integration Events are enabled, the TMS webhook receiver accepts HTTPS JSON POSTs and returns `2xx`.
