curl --request GET \
--url https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber} \
--header 'Accept: <accept>' \
--header 'AccessToken: <api-key>'import requests
url = "https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}"
headers = {
"Accept": "<accept>",
"AccessToken": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Accept: '<accept>', AccessToken: '<api-key>'}};
fetch('https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: <accept>",
"AccessToken: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "<accept>")
req.Header.Add("AccessToken", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}")
.header("Accept", "<accept>")
.header("AccessToken", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = '<accept>'
request["AccessToken"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"dot_number": "1234456",
"legal_name": "BENNIE SAYLOR",
"garaging_state": "OH",
"num_power_units": 0,
"years_business": null,
"eligibility": {
"eligible": true,
"decline_reasons": [],
"warnings": [
{
"rule": "inactive_carrier",
"message": "Carrier MCS-150 status is not active (status: I). Requires underwriting review."
},
{
"rule": "authority_data_unavailable",
"message": "Operating authority data is not available for this DOT number. Unable to verify active authority."
},
{
"rule": "already_bound_other_agency",
"message": "This DOT is already bound with another agency. You can quote, but a signed Broker of Record (BOR) is required to bind."
}
]
},
"service_available": true,
"dot_not_found": false,
"screened_at": "2026-10-21T00:25:33+00:00"
}{
"error": "Invalid DOT number. Must be 1-8 digits."
}{
"error": "Rate limit exceeded. Temporarily banned.",
"retry_after": 3600,
"retry_after_human": "1 hour",
"scope": "pre_screen"
}{
"error": "Pre-screen failed. Please try again."
}{
"error": "Our data provider is temporarily unavailable. Please try again in a few minutes, or contact us for assistance."
}Pre-Screen a DOT Number
Run Cover Whale’s DOT pre-screen for a carrier and get back the eligibility verdict plus a small pre-fill payload. This is the same check the Cover Whale submission page runs when an agent types in a DOT number, exposed so you can pre-qualify a carrier before building a quote.
What eligible means
eligibility.eligible is true when no decline rule fired. It does not mean the submission will be accepted. A carrier can come back eligible: true and still carry warnings that require underwriting review — see the example response below, where the carrier’s federal registration is inactive and its operating authority could not be verified, yet eligible is true. Treat eligible: true as “clear to quote”, never as “clear to bind”.
Declines versus warnings
decline_reasons and warnings are separate lists and behave differently:
decline_reasons— a hard stop. Any entry here setseligibletofalse.warnings— advisory. Warnings never changeeligible. They tell you what an underwriter will look at, and some are phrased “Requires underwriting review”.
The same situation never appears in both lists. Every rule is permanently one or the other; the two enumerations are in the response-field descriptions below.
Rate limits
Two ceilings apply, both counted against your own account rather than a shared network address, so another partner’s traffic can never consume your allowance:
- 60 requests per minute
- 250 requests per day
Either ceiling returns 429 with a Retry-After header giving the seconds to wait, and a body carrying retry_after, a human-readable retry_after_human, and the scope that was limited. Sustained breaches add a temporary block, which returns the same 429 shape with a longer retry_after.
Batch workloads are supported inside those ceilings. If 250 screens a day is too tight for your volume, contact us — the limit is raisable per account without a code change.
Two “no answer” cases you must handle separately
service_available: falsewith a503— the federal data source is temporarily unreachable. Retry later; the carrier may be perfectly fine.dot_not_found: truewith a200— the request succeeded and our carrier data provider holds no record for this DOT yet;warningswill carryfmcsa_record_pending. This is an answer, not a failure, and is not a404. You can continue and supply the carrier details yourself; the DOT is re-checked automatically when you quote.
What this endpoint never returns
Federal safety scores, out-of-service percentages, inspection and crash counts, addresses beyond the state, and the evidence behind any cancellation-related decline are all deliberately withheld. The message in decline_reasons is the whole of what is disclosed. Where a carrier is already bound elsewhere, the other agency is never named.
curl --request GET \
--url https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber} \
--header 'Accept: <accept>' \
--header 'AccessToken: <api-key>'import requests
url = "https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}"
headers = {
"Accept": "<accept>",
"AccessToken": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Accept: '<accept>', AccessToken: '<api-key>'}};
fetch('https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: <accept>",
"AccessToken: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "<accept>")
req.Header.Add("AccessToken", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}")
.header("Accept", "<accept>")
.header("AccessToken", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.coverwhale.dev/v1/submission/pre-screen/{dotNumber}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Accept"] = '<accept>'
request["AccessToken"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"dot_number": "1234456",
"legal_name": "BENNIE SAYLOR",
"garaging_state": "OH",
"num_power_units": 0,
"years_business": null,
"eligibility": {
"eligible": true,
"decline_reasons": [],
"warnings": [
{
"rule": "inactive_carrier",
"message": "Carrier MCS-150 status is not active (status: I). Requires underwriting review."
},
{
"rule": "authority_data_unavailable",
"message": "Operating authority data is not available for this DOT number. Unable to verify active authority."
},
{
"rule": "already_bound_other_agency",
"message": "This DOT is already bound with another agency. You can quote, but a signed Broker of Record (BOR) is required to bind."
}
]
},
"service_available": true,
"dot_not_found": false,
"screened_at": "2026-10-21T00:25:33+00:00"
}{
"error": "Invalid DOT number. Must be 1-8 digits."
}{
"error": "Rate limit exceeded. Temporarily banned.",
"retry_after": 3600,
"retry_after_human": "1 hour",
"scope": "pre_screen"
}{
"error": "Pre-screen failed. Please try again."
}{
"error": "Our data provider is temporarily unavailable. Please try again in a few minutes, or contact us for assistance."
}Authorizations
JWT returned as AccessToken by the /authentication endpoint (the Cognito ID token carrying the email claim). It expires after 3600 seconds.
Path Parameters
The carrier's DOT number: 1 to 8 digits, and not zero. Anything else returns 400 without a screen being run.
^\d{1,8}$Response
Screen completed. Check eligibility.eligible, and read warnings even when it is true.
The DOT number you asked about, echoed back.
"1234456"
Carrier legal name. May be null when the federal record is incomplete.
"BENNIE SAYLOR"
Two-letter state of the carrier's physical address. May be null.
"OH"
Declared power-unit count. May be 0 or null — 0 is a real declared value, not missing data.
0
Years in business. May be null when the federal record does not carry it.
null
The verdict. eligible is true when decline_reasons is empty, and is unaffected by warnings.
Show child attributes
Show child attributes
False when the federal data source could not be reached. A screen with this false is returned as a 503, except when the DOT is on the exclusion list, which takes precedence.
true
True when the request succeeded but our carrier data provider holds no record for this DOT yet. A 200, not a 404 — newly issued or recently updated federal registrations can take several days to reach the provider's feed. When this is true, warnings carries fmcsa_record_pending with the detail. This is not a decline: you can continue and supply the carrier details yourself, and the DOT is re-checked automatically when you quote.
false
When the screen ran. ISO 8601 with offset. Use it for your own caching and audit.
"2026-10-21T00:25:33+00:00"