Order background checks for a driver
/api/vendor/v1/ordersOrders the services in services (or, without it, every service
enabled for the vendor) for one driver. Each service is billed on
your monthly invoice at the price in effect when the order was
placed. The answer is 202 with the order and its services; poll the
order every 30 seconds (Retry-After) until it is
final.
Send multipart/form-data, at most 32 MB in all. The CDL
images may be JPEG, PNG, WEBP, HEIC or PDF, at most 15 MB each; the
type is read from the file's bytes, and a PDF is stored as its first
page.
Every order needs an Idempotency-Key. Retrying with the same key and
the same body (from any of the vendor's API keys) answers with the
order already placed, marked Idempotent-Replayed: true, and orders
nothing again; the same key with a different body is 409 idempotency_conflict. The key belongs to the vendor and never
expires.
Nothing is created or billed when an order is refused. MVR is refused
(422 mvr_state_unavailable) for a license state it can't be pulled
for through the vendor API (a state that needs the carrier's own
access code or credentials, MVR switched off, a manual pull, no
price); a Driver Reviews-only order for that state is fine.
The ssn is accepted only with CDLIS and is required with it. It is
never returned, logged or shown anywhere, and it is erased once CDLIS
has finished.
10 orders a minute per vendor, replays included.
Authorization
X-API-KeystringrequiredThe environment's prefix (
snt_test_on this server;GET /mereturns the environment), 8 characters,_, then the secret. Shown once, when the key is created in the Sentinel Developers portal. A key works only against the server that issued it.
Headers
Idempotency-Keystringat most 64 charactersrequiredA value of your choosing, unique per order (a UUID, say): printable ASCII, at most 64 characters.
Request body
first_namestringrequiredlast_namestringrequiredmiddle_namestringname_suffixstringdate_of_birthstring · daterequiredYYYY-MM-DD.
license_numberstringrequiredlicense_statestringrequiredThe two-letter state code.
class_typestringThe license class (A, B, C...).
issue_datestring · dateexpiration_datestring · datemc_numberstringrequiredThe carrier's MC (or MX / FF) docket number, for example MC-123456. You are responsible for sending the right one. It is stored on the order and shown on your invoice; the carrier doesn't need to be a Sentinel customer.
servicesstringComma-separated, for example
mvr,psp. Without it, every service enabled for your account runs.ssnstringThe driver's full SSN, digits with optional dashes or spaces. Required with CDLIS, refused without it.
external_referencestringat most 255 charactersYour own reference for the order, returned with it.
driver_consent_confirmedbooleanrequiredMust be true. You confirm that you have the driver's consent.
consent_obtained_atstring · date-timerequiredWhen you collected the driver's consent, with a timezone.
consent_versionstringrequiredThe version of the consent wording you collected it under. This server accepts
vendor-2026-10-v1.cdl_imagefilerequiredThe front of the CDL.
cdl_image_backfileThe back of the CDL (optional).
Responses
200Idempotent-Replayedheader · stringtruewhen the answer is an order already placed with this Idempotency-Key.Locationheader · stringThe order's address, to poll.
Cache-Controlheader · stringno-store: order results are never cached.
order_idstring · uuidrequiredstatusstringrequiredunder_reviewwhile any service is held for Sentinel staff,processingwhile any service runs, thencompleted,failedorpartially_completed.finalbooleanrequiredTrue once every service is
completedorfailed.safety_scoreobject | nullrequiredNull for an order without MVR or PSP, before the score is calculated, and while the order or its MVR is under review.
ShowHide 5 fields
scoreintegerrequiredFrom 0 to 100.
gradestring | nullrequiredrisk_levelstring | nullrequiredreports_usedarray of stringrequiredcalculated_atstring · date-time | nullrequired
environmentstringrequiredmc_numberstringrequiredThe MC number sent with the order, normalised.
external_referencestring | nullrequiredservicesarray of objectrequiredShowHide 7 fields
servicestringrequiredstatusstringrequiredExtensible: a later version may add values. Treat a value you don't know as not final until
finalsays so. (Whether a result is billed is on the Billing page, not here.)reasonstring | nullrequiredExtensible: a later version adds reasons; show an unknown one as is.
report_unavailable(processing): the report is finished but its file is not available right now; Sentinel staff are alerted.identity_review(under_review): the MVR names a different person than the one ordered for. The whole order is held until staff release it.manual_review(under_review): the MVR needs Sentinel staff before its report can be served.report_review(under_review): the report needs Sentinel staff before it can be served.provider_failed(failed): the provider or Sentinel could not complete the check.no_record(failed): the provider answered that it has no record of this driver (an MVR every provider of the state answered so for; a PSP FMCSA has no record for). Billed as NO_HIT.no_report(failed): the provider finished without a report.timed_out(failed): not finished by the order's deadline.identity_unverified(failed): still held foridentity_reviewat the deadline.record_deleted(failed): the order's data was deleted on request.
statestring | nullrequiredThe license state of the MVR (MVR only).
completed_atstring · date-time | nullrequiredfile_urlstring | nullrequiredThe report PDF (MVR, PSP, CDLIS), once the service is
completed. Download it with your API key. A link from the list can briefly answer404after the file becomes unavailable.resultobject | nullrequiredDriver Reviews only, once it is
completed.ShowHide 2 fields
foundbooleanrequiredFalse when no review of the driver was found.
reviewsarray of objectrequiredShowHide 3 fields
ratingnumber | nullrequiredtextstring | nullrequireddatestring · date | nullrequired
created_atstring · date-timerequiredpollobjectrequiredShowHide 2 fields
urlstringrequiredafter_secondsintegerrequired
202Retry-Afterheader · integerOnly while the order is not final: seconds to wait before polling it.
Locationheader · stringThe order's address, to poll.
Idempotent-Replayedheader · stringtruewhen the answer is an order already placed with this Idempotency-Key.Cache-Controlheader · stringno-store: order results are never cached.
order_idstring · uuidrequiredstatusstringrequiredunder_reviewwhile any service is held for Sentinel staff,processingwhile any service runs, thencompleted,failedorpartially_completed.finalbooleanrequiredTrue once every service is
completedorfailed.safety_scoreobject | nullrequiredNull for an order without MVR or PSP, before the score is calculated, and while the order or its MVR is under review.
ShowHide 5 fields
scoreintegerrequiredFrom 0 to 100.
gradestring | nullrequiredrisk_levelstring | nullrequiredreports_usedarray of stringrequiredcalculated_atstring · date-time | nullrequired
environmentstringrequiredmc_numberstringrequiredThe MC number sent with the order, normalised.
external_referencestring | nullrequiredservicesarray of objectrequiredShowHide 7 fields
servicestringrequiredstatusstringrequiredExtensible: a later version may add values. Treat a value you don't know as not final until
finalsays so. (Whether a result is billed is on the Billing page, not here.)reasonstring | nullrequiredExtensible: a later version adds reasons; show an unknown one as is.
report_unavailable(processing): the report is finished but its file is not available right now; Sentinel staff are alerted.identity_review(under_review): the MVR names a different person than the one ordered for. The whole order is held until staff release it.manual_review(under_review): the MVR needs Sentinel staff before its report can be served.report_review(under_review): the report needs Sentinel staff before it can be served.provider_failed(failed): the provider or Sentinel could not complete the check.no_record(failed): the provider answered that it has no record of this driver (an MVR every provider of the state answered so for; a PSP FMCSA has no record for). Billed as NO_HIT.no_report(failed): the provider finished without a report.timed_out(failed): not finished by the order's deadline.identity_unverified(failed): still held foridentity_reviewat the deadline.record_deleted(failed): the order's data was deleted on request.
statestring | nullrequiredThe license state of the MVR (MVR only).
completed_atstring · date-time | nullrequiredfile_urlstring | nullrequiredThe report PDF (MVR, PSP, CDLIS), once the service is
completed. Download it with your API key. A link from the list can briefly answer404after the file becomes unavailable.resultobject | nullrequiredDriver Reviews only, once it is
completed.ShowHide 2 fields
foundbooleanrequiredFalse when no review of the driver was found.
reviewsarray of objectrequiredShowHide 3 fields
ratingnumber | nullrequiredtextstring | nullrequireddatestring · date | nullrequired
created_atstring · date-timerequiredpollobjectrequiredShowHide 2 fields
urlstringrequiredafter_secondsintegerrequired
400errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
401WWW-Authenticateheader · string
errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
403errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
409Retry-Afterheader · integerin_progressonly: seconds to wait before retrying with the same key.
errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
413errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
415errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
422errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
429Retry-Afterheader · integerSeconds to wait before trying again.
errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.
503Retry-Afterheader · integerrate_limit_unavailableonly: seconds to wait before trying again.
errorobjectrequiredShowHide 4 fields
order_idstring · uuididempotency_conflictonly: the order the key already belongs to.codestringrequiredvalidation_error(400): the request is not valid; seefields.invalid_api_key(401): no key, a malformed, unknown or revoked key, or a key this server did not issue.api_key_expired(401): the key is past its 90 days. Create a new one.account_not_approved(403): staff have not approved the account yet.account_suspended(403): the account is suspended. Results can still be read; new orders are refused.service_not_enabled(403): an order names a service that is not enabled for the account (or none is).permission_denied(403): any other refusal.not_found(404): no such path or object. Any unknown path under/api/vendor/answers this, with or without a key; so does an order that is not yours (exactly like one that does not exist) and a report that can't be downloaded now.method_not_allowed(405).idempotency_conflict(409): the Idempotency-Key was already used for a different order (error.order_id).in_progress(409): an order with this Idempotency-Key is still being placed; seeRetry-After.payload_too_large(413): the request body or an image is too large.unsupported_media_type(415): the request body or an image has the wrong type.mvr_state_unavailable(422): MVR can't be ordered for the license state through the vendor API.rate_limited(429): seeRetry-After. Also answered, instead of 401, after more than 100 failed keys from one address or 10 on one key in 10 minutes.internal_error(500).rate_limit_unavailable(503): try again shortly.price_unavailable(503): a service can't be priced right now.request_failed: any other error, with its HTTP status.
messagestringrequiredFor people; may change. Use
codein your code.fieldsobject | nullrequiredPer-field messages, for validation errors.