Beginner5 min

Your First Carrier Lookup

Look up a motor carrier by DOT number, parse 280+ fields of authority, safety, insurance, and fleet data, then search by company name. You'll have a working integration in under 5 minutes.

What you'll learn

  • Look up any carrier by DOT number
  • Parse identity, authority, and insurance fields
  • Read ISS scores and BASIC percentiles
  • Search carriers by company name
  • Handle pagination with page and pageSize
  • Implement error handling and retries

Prerequisites

A sandbox key (sk_test_*). Sign up and find yours on the API Keys page. Sandbox is free, fixture-only. Activate live for $50 when you're ready for real data. You'll also need curl, Python 3, or Node.js 18+.
1

Look up a carrier by DOT number

The Carrier Profiles API returns a full profile for any of 4M+ FMCSA-registered carriers. The simplest lookup uses a DOT number — the unique identifier assigned to every motor carrier.

curl "https://api.carrierok.com/v2/profile?dot_number=568253" \
  -H "Authorization: Bearer YOUR_API_KEY"
Response200 OK
{
  "items": [
    {
      "dot_number": "568253",
      "legal_name": "HANSEN & ADKINS AUTO TRANSPORT INC",
      "docket": "MC277621",
      "authority_common": "Active",
      "authority_contract": "Active",
      "authority_age_common": "7937",
      "insurance_bipd_on_file": "1000000",
      "insurance_bipd_required": "1000000",
      "indicator_insurance": true,
      "iss_value": "45",
      "risk_score": "Low",
      "total_power_units": "897",
      "total_drivers": "897",
      "safety_rating_desc": "Satisfactory",
      "usdot_status": "Active"
    }
  ],
  "total_count": 1
}

The response contains an items array and a total_count. A DOT lookup returns exactly one result.

2

Understand the response

Each carrier profile contains 280+ fields. Here are the categories you'll use most:

CategoryKey Fields
Identitylegal_name, dot_number, docket, ein
Authorityauthority_common, authority_contract, authority_age_common
Insuranceinsurance_bipd_on_file, insurance_bipd_required, indicator_insurance
Safetyiss_value, risk_score, basic_percentile_*, safety_rating_desc
Fleettotal_power_units, total_drivers, cargo_carried
Contacttelephone_number, email_address, physical_address

All 7 BASICs

Unlike FMCSA's public SAFER system, CarrierOk computes and returns all 7 BASIC percentiles — including Crash Indicator and Hazmat, which FMCSA does not publish. Look for the basic_percentile_* fields.

See the complete field reference in the Carrier Profiles endpoint docs.

3

Search by company name

When you don't have a DOT number, search by company name. The API supports partial matching and returns paginated results.

curl "https://api.carrierok.com/v2/profile?company=hansen+adkins&pageSize=5" \
  -H "Authorization: Bearer YOUR_API_KEY"
Response200 OK
{
  "items": [
    {
      "dot_number": "568253",
      "legal_name": "HANSEN & ADKINS AUTO TRANSPORT INC",
      "physical_address_city": "LOS ALAMITOS",
      "physical_address_state": "CA",
      "authority_common": "Active",
      "total_power_units": "897"
    }
  ],
  "total_count": 1
}

You can also search by EIN, phone, email, address, VIN, or license plate. Each uses the same /v2/profile endpoint with different query parameters.

4

Paginate results

Company name searches can return many results. Use page and pageSize to page through them:

Python
import requests
import math

API_KEY = "YOUR_API_KEY"
BASE = "https://api.carrierok.com/v2/profile"

def fetch_all(company: str, page_size: int = 100):
    """Fetch all carriers matching a company name."""
    carriers = []
    page = 1

    while True:
        resp = requests.get(
            BASE,
            params={
                "company": company,
                "page": page,
                "pageSize": page_size,
            },
            headers={"Authorization": f"Bearer {API_KEY}"},
        )
        resp.raise_for_status()
        data = resp.json()

        carriers.extend(data["items"])

        total_pages = math.ceil(data["total_count"] / page_size)
        if page >= total_pages:
            break
        page += 1

    return carriers

results = fetch_all("werner")
print(f"Fetched {len(results)} carriers")

Default page size

The default page size is 100. The response always includes the total_count field so you can calculate remaining pages.
5

Handle errors

The API returns standard HTTP status codes. Here's a production-ready error handler:

Python
import time
import requests

def lookup_carrier(dot_number: str, api_key: str, retries: int = 3):
    """Look up a carrier with automatic retry on rate limits."""
    url = "https://api.carrierok.com/v2/profile"

    for attempt in range(retries):
        resp = requests.get(
            url,
            params={"dot_number": dot_number},
            headers={"Authorization": f"Bearer {api_key}"},
        )

        if resp.status_code == 200:
            data = resp.json()
            if data["items"]:
                return data["items"][0]
            return None  # DOT not found

        if resp.status_code == 429:
            wait = min(2 ** attempt, 30)
            print(f"Rate limited — retrying in {wait}s")
            time.sleep(wait)
            continue

        if resp.status_code == 401:
            raise ValueError("Invalid API key")

        resp.raise_for_status()

    raise TimeoutError("Max retries exceeded")
StatusMeaningAction
200SuccessParse items array
400Missing parametersCheck query string
401Invalid API keyVerify Authorization: Bearer header
429Rate limitedExponential backoff, then retry
503Service unavailableRetry after 5 seconds

See Rate Limits & Errors for the full error reference and rate limits.