Skip to content
Developers
POST

Order background checks for a driver

POST/api/vendor/v1/orders

Order the services selected by the request flags using multipart/form-data and an Idempotency-Key. Reuse the same key and body to retrieve the same order; a different body returns 409.

Authorization

  • X-API-Keystringrequired

    The environment's prefix (snt_test_ on this server; GET /me returns 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 charactersrequired

    A value of your choosing, unique per order (a UUID, say): printable ASCII, at most 64 characters.

Request body

multipart/form-datarequired

  • first_namestringrequired
  • last_namestringrequired
  • middle_namestring
  • name_suffixstring
  • date_of_birthstring · daterequired

    YYYY-MM-DD.

  • license_numberstringrequired
  • license_statestringrequired

    The two-letter state code.

  • class_typestring

    The license class (A, B, C...).

  • issue_datestring · date
  • expiry_datestring · date
  • mc_numberstringrequired

    The 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.

  • ssnstring

    The driver's full SSN, digits with optional dashes or spaces. Required with CDLIS, refused without it.

  • cdl_imagefilerequired

    The front of the CDL.

  • back_of_cdlfile

    The back of the CDL (optional).

  • mvr_requestedany

    Omitted means false; request at least one service.

  • psp_requestedany

    Omitted means false; request at least one service.

  • cdlis_requestedany

    Omitted means false; request at least one service.

  • driver_reviews_requestedany

    Omitted means false; request at least one service.

Responses

  • 200The order is completed.
    • Idempotent-Replayedheader · string

      true when the answer is an order already placed with this Idempotency-Key.

    • Locationheader · string

      The order's address, to poll.

    • Cache-Controlheader · string

      no-store: order results are never cached.

    • idstring · uuidrequired
    • statusstringrequired

      One of: processing, completed

    • mc_numberstringrequired
    • submission_datestring · date-timerequired
    • completed_datestring · date-time | nullrequired

      The order's final time when completed; otherwise null.

    • mvr_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • psp_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • cdlis_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • driver_reviews_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • mvr_filestring | nullrequired

      Authenticated download URL when completed; otherwise null.

    • psp_filestring | nullrequired

      Authenticated download URL when completed; otherwise null.

    • cdlis_filestring | nullrequired

      Authenticated download URL when completed; otherwise null.

    • driver_reviews_dataobject | nullrequired

      Reviews of the driver matched on the exact name and date of birth. Never the reviewer, the reviewing carrier or any record id.

      Show 2 fields
      • foundbooleanrequired

        False when no review of the driver was found.

      • reviewsarray of objectrequired
        Show 3 fields
        • ratingnumber | nullrequired
        • textstring | nullrequired
        • datestring · date | nullrequired
    • safety_scoreinteger | nullrequired
    • safety_gradestring | nullrequired
    • safety_risk_levelstring | nullrequired
  • 202The order is processing.
    • Retry-Afterheader · integer

      Seconds to wait before retrying.

    • Locationheader · string

      The order's address, to poll.

    • Idempotent-Replayedheader · string

      true when the answer is an order already placed with this Idempotency-Key.

    • Cache-Controlheader · string

      no-store: order results are never cached.

    • idstring · uuidrequired
    • statusstringrequired

      One of: processing, completed

    • mc_numberstringrequired
    • submission_datestring · date-timerequired
    • completed_datestring · date-time | nullrequired

      The order's final time when completed; otherwise null.

    • mvr_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • psp_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • cdlis_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • driver_reviews_statusstring | nullrequired

      processing: being worked on, including when Sentinel staff are checking it; completed: the report is ready; no_record: the provider has no record of this driver, billed as a no-record result. Null when not ordered.

      One of: processing, completed, no_record

    • mvr_filestring | nullrequired

      Authenticated download URL when completed; otherwise null.

    • psp_filestring | nullrequired

      Authenticated download URL when completed; otherwise null.

    • cdlis_filestring | nullrequired

      Authenticated download URL when completed; otherwise null.

    • driver_reviews_dataobject | nullrequired

      Reviews of the driver matched on the exact name and date of birth. Never the reviewer, the reviewing carrier or any record id.

      Show 2 fields
      • foundbooleanrequired

        False when no review of the driver was found.

      • reviewsarray of objectrequired
        Show 3 fields
        • ratingnumber | nullrequired
        • textstring | nullrequired
        • datestring · date | nullrequired
    • safety_scoreinteger | nullrequired
    • safety_gradestring | nullrequired
    • safety_risk_levelstring | nullrequired
  • 400validation_error: see fields, one list of messages per field.
    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 401invalid_api_key or api_key_expired.
    • WWW-Authenticateheader · string
    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 403account_not_approved, account_suspended or service_not_enabled.
    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 409idempotency_conflict (the key was used for a different body; error.order_id names that order) or in_progress (an order with this key is still being placed; retry after Retry-After).
    • Retry-Afterheader · integer

      in_progress only: seconds to wait before retrying with the same key.

    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 413payload_too_large: the body or an image is too large.
    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 415unsupported_media_type: the body is not multipart/form-data, or an image is not one of the accepted types.
    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 422mvr_state_unavailable: MVR can't be ordered for the license state; fields.license_state says why.
    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 429rate_limited. 120 reads and 10 orders a minute per vendor, across all of its keys.
    • Retry-Afterheader · integer

      Seconds to wait before trying again.

    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

  • 503rate_limit_unavailable (see Retry-After) or price_unavailable (a service has no price right now).
    • Retry-Afterheader · integer

      rate_limit_unavailable only: seconds to wait before trying again.

    • errorobjectrequired
      Show 4 fields
      • order_idstring · uuid

        idempotency_conflict only: the order the key already belongs to.

      • codestringrequired
        • validation_error (400).
        • invalid_api_key (401).
        • api_key_expired (401).
        • account_not_approved (403).
        • account_suspended (403).
        • service_not_enabled (403).
        • permission_denied (403).
        • not_found (404).
        • method_not_allowed (405).
        • idempotency_conflict (409).
        • in_progress (409).
        • payload_too_large (413).
        • unsupported_media_type (415).
        • mvr_state_unavailable (422).
        • rate_limited (429).
        • internal_error (500).
        • rate_limit_unavailable (503).
        • price_unavailable (503).
        • request_unavailable: another HTTP error.

        One of: validation_error, invalid_api_key, api_key_expired, account_not_approved, account_suspended, service_not_enabled, permission_denied, not_found, method_not_allowed, idempotency_conflict, in_progress, payload_too_large, unsupported_media_type, mvr_state_unavailable, rate_limited, internal_error, rate_limit_unavailable, price_unavailable, request_unavailable

      • messagestringrequired

        For people; may change. Use code in your code.

      • fieldsobject | nullrequired

        Per-field messages, for validation errors.

curl -X POST https://api-demo-safety.spotter.ai/api/vendor/v1/orders \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Idempotency-Key: string" \
  -F first_name=string \
  -F last_name=string \
  -F date_of_birth=2026-10-14 \
  -F license_number=string \
  -F license_state=FL \
  -F mc_number=string \
  -F mvr_requested=true \
  -F psp_requested=true \
  -F cdlis_requested=true \
  -F driver_reviews_requested=true \
  -F ssn=DRIVER_SSN \
  -F cdl_image=@cdl-front.jpg
{
  "id": "3f2b9c1e-7a4d-4e8b-9c61-5d0a8e2f4b17",
  "status": "processing",
  "mc_number": "string",
  "submission_date": "2026-10-14T15:04:05Z",
  "completed_date": "2026-10-14T15:04:05Z",
  "mvr_status": "processing",
  "psp_status": "processing",
  "cdlis_status": "processing",
  "driver_reviews_status": "processing",
  "mvr_file": "string",
  "psp_file": "string",
  "cdlis_file": "string",
  "driver_reviews_data": {
    "found": true,
    "reviews": [
      {
        "rating": 0,
        "text": "string",
        "date": "2026-10-14"
      }
    ]
  },
  "safety_score": 0,
  "safety_grade": "string",
  "safety_risk_level": "string"
}