Yardstik API (1.0)

Introduction

Yardstik is a modern, RESTful API-driven background screening service offering many screens and services to run against potential employees, tenants, or other use cases. Yardstik utilizes resource-oriented URLs. We authenticate these routes via a single API key and leverage JSON in all responses, resulting in a seamless integration.

Since the founding of Yardstik in 2020, many companies across a variety of industries have utilized our human security platform.

For more information, please visit yardstik.com. For a more personal approach, reach out to our support team (support@yardstik.com) to get in touch with our Engineers.

Understanding our Integration

To ensure a smooth integration of your application with Yardstik, we have outlined the basic user flow below. When you have a candidate that you want to perform a background check or screening on, these are the steps that one would follow to complete the process:

  1. An applicant/candidate is selected to perform a background check and/or screening on.
  2. You create an invitation for the candidate.
  3. The candidate receives an invite email, leading them to the candidate intake form.
  4. The candidate fills out the required information needed to perform the background checks requested.
  5. Once the candidate signs the legal and consent forms, and all required information is provided, it is sent to our verification team who will perform a background check on the candidate and return a status depending on the results.
  6. Once the results are ready, you now have a complete background check and/or screening on your candidate, and can decide what the next steps are.

Note: You have the option to place the responsibility of paying for the background check and/or screening on the candidate. They will complete this step during the intake process, before their information is sent to our verification team.

The screens and information gathered are determined by the account package that is used. The account packages contain information on what is required and will compile the correct collection steps in the candidate intake form, resulting in a smooth user experience for the candidate.

Getting Credentialed

Before you immerse yourself in the amazing world of background check integrations, you must first become registered and credentialed to use our product. Reach out to our support team at support@yardstik.com to get the necessary permissions and setup information.

To make the process go faster here is some of the information that is required to make an account.

Permissible purpose:

As a company that is registered in the United States, we are heavily regulated by federal, state, and local levels of government, and primarily by the Fair Credit Reporting Act (FCRA). This law requires you to supply the candidate with the reason why the background check is being performed.

Some examples:

Permissible Purpose Description
Tenant The candidate is a potential tenant for your rental unit.
Employment The candidate is a potential employee or contractor for your company. Or, the candidate is a current employee that requires periodic background checks or screenings to maintain their employment with your company.

Legal Business Name: The name of your company, as it appears on any government registration forms.

Owner's Email: The email address of whoever is assigned as the Yardstik Account Owner from your company, and who will be the main contact for communication to and from Yardstik.

First and Last Name: The first and last name of the Yardstik Account Owner.

With this information we can get your account set up rather quickly even if the business aspect may need some more time.

Dashboard

Although we are an API first company, we have a user-friendly interface that allows you to manage your account. Using the interface, you can create API keys, manage candidate invites, view reports of background check and/or screening results (unless you are using the embedded views), track decisions on those results, and more. If you already have a user account set up, access the Dashboard here.

Authentication

Here at Yardstik, we authenticate your API requests using API keys. The API key is passed in the header of a request under the Authorization: Account [YOUR API KEY]. Along with this it is recommended that you include Accept: application/json (if you do not include this, you may experience some unexpected errors).

How to get your first API Key

Now that you have a credentialed account and are able to log in, you can obtain your first API key and start sending requests!

Getting your first API key is as simple as signing into the Dashboard, clicking on the Developer tab, and selecting the API Keys menu option. On this page, input a name for your API key (this cannot be edited later on, so be sure to choose a unique name) and click the Create button. After this, a window containing your full API key will appear once (and only once).

NOTE: WE DO NOT SAVE API KEYS. MAKE SURE YOU COPY THE API KEY BEFORE CLOSING THE WINDOW.

Keeping your API key safe

It is good practice to withhold your API keys from anyone who doesn't need them. If someone gets access to one of your API keys, they have complete access to all API calls on your company's behalf. We recommend not hardcoding the API Key anywhere in your application and to not send the API key on any platform that isn't secure.

If you believe that your API key has been compromised, you can delete it from the Dashboard and create a new API key. If you need help, don't hesitate to reach out to Support for assistance.

API key best practices

  • Do not embed API keys directly in code.
  • Do not store API keys in files inside your source code.
  • Delete unused API keys.
  • Regenerate your API keys periodically.
  • Always store your API keys encrypted.
  • Restrict access to the API keys to only those who need it.
  • Do not share your API keys, not even with us.

Getting Started

This will walk you through the necessary steps to successfully run a background check using Yardstik's API

Get your API key

You can manage your API keys from your account dashboard at any time. Once your Yardstik account has been created, login to your dashboard, go to Developer Settings and create your first API key.

Authenticate with Yardstik

Yardstik uses HTTP API key authentication. Authentication with Yardstik is easy, simply include an account API key from your Developer Settings in the header of all your API requests.

Example Authenticated Request:

curl -X GET https://api.yardstik.com/accounts \
    -H 'Authorization: Account [YOUR_API_KEY]' \
    -H 'Accept: application/json'

Example Authenticated Response:

[
    {
        "id": "cc0df11d-a502-47ec-8aa1-ba0738030ca7",
        "account_name": "Global Dynamics",
        "first_name": "Nathan",
        "last_name": "Stark",
        "email_address": "nathan.stark@globaldynamics.com",
        "url": "https://www.globaldynamics.com",
        "tech_email_address": "it@globaldynamics.com",
        "support_email_address": "support@globaldynamics.com",
        "support_phone": "541-555-4376",
        "actions_email_address": "hr@globaldynamics.com",
        "compliance_email_address": "hr@globaldynamics.com",
        "logo": "https://vignette.wikia.nocookie.net/eureka/images/d/dd/Global_dynamics.jpg",
        ...
    },
    ...
]

If you are seeing a response similar to this one then you are authenticated and can make requests to the API 🎉

Create an Invitation Flow

This is an example of how to create an invitation using the API. There are 2 steps in this process. First you must create a candidate. A candidate can be created by using the Create a Candidate Route

After you complete this request, you should see a response that looks like the example below.

Example Candidate Response:

{
"id":  "1111111-23c9-4f70-bcd3-332d6dd9aacf",
"object":  "candidate",
"full_name":  "Kirk Boehm",
"first_name":  "Kirk",
"middle_name":  null,
"no_middle_name":  false,
"last_name":  "Boehm",
"email":  "Jameson_Grimes@example.net",
"phone":  "+7514747858",
"ssn_masked":  null,
"additional_data":  {},
"guardian":  {},
"account":  {
    "id":  "15d9fd10-3927-4de6-a504-221971680f0e",
    "account_name":  "Company"
},
...
}
}

Now that you have created a candidate, you can invite that candidate to complete their form using the invitation route. You will need the candidate id from the previous request along with the account package id that includes the screens to be run on the candidate.

Note:

  • The candidate_id attribute is required.
  • The account_package_id attribute is required. See Account Packages for more information.

Example Invitation Request:

curl --location --request POST 'https://api.yardstik.com/invitations' \
--header 'Authorization: Account [API KEY HERE]' \
--header 'Content-Type: application/json' \
--data-raw '{
    "account_package_id": "ID",
    "candidate_id": "ID",
    "invitation_code": "" optional
}'

Example Invitation Response:

{
    "id": "ID",
    "status": "invite_sent",
    "invitation_code": null,
    "external_id": null,
    "platform_service_id": null,
    "expires_at": "2021-08-25T21:40:56.062Z",
    "canceled_at": null,
    "confirmation_code": "VWJ-14798",
    "account_id": "ID",
    "account_name": "",
    "logo": "URL",
    "report_urls": [],
    "styles": {
        "primary_color": "#007BFF",
        "secondary_color": "#FFCD01"
    },
    "candidate": {
       ...
    },
    "account": {
        "account_name": "example Company",
        "support_email_address": "",
        "support_phone": "+111111111"
    },
    "meta": {
        "entity": "https://app.yardstik.com/invitations/ID",
        "apply": "https://profile.yardstik.com/candidates/ID/apply?report_id=ID&account_package_id=ID"
    },
    "report": {
        "id": "ID",
        "status": "created"
    }
}

The candidate will now receive an email asking them to complete the form. In the meta tag of the response, there is a key named apply. This is the link that they will be sent.

Invitation Status

Status Definition
invite_sent The invitation has been sent, no other action has been taken by the candidate yet.
viewed The invitation has been viewed by the candidate, but not clicked yet.
clicked The invitation link has been clicked by the candidate to view the report, but they have not completed the intake form.
completed The invitation has been completed by the candidate and the report will be in progress.
canceled The invitation has been canceled by the account.
expired The invitation has expired. For more details about expirations, see Invitations.

See Invitations for more information about the invitation resource.

Listen for Webhooks

Yardstik uses webhooks to push events to your application when various events related to your resources occur. After registering a webhook for a specific webhook type, the URL you register will receive POST requests when the event occurs in your account.

See Webhooks Resource for details about available API calls.

Webhooks Types

Webhook Type Description
candidate.created A candidate has been created.
candidate.updated A candidate has been updated.
candidate.deleted A candidate has been deleted.
candidate.consented Candidate has completed their PII, signed their disclosures, and consented to the background check.
candidate.paid Candidate has paid for their background check.
transaction.created A payment transaction has been created.
transaction.updated A payment transaction has been updated.
transaction.deleted A payment transaction has been deleted.
invitation.created An invitation has been created.
invitation.updated An invitation has been updated.
invitation.deleted An invitation has been deleted.
report.created A report has been created.
report.updated A report has been updated.
report.deleted A report has been deleted.
account.updated An account has been updated.
sub_account.active The Subaccount was activated by a Yardstik Agent.

Example Retrieve Webhook Types Request:

curl -X GET https://api.yardstik.com/webhook_types \
    -H 'Authorization: Account [YOUR_API_KEY]' \
    -H 'Accept: application/json'

Example Retrieve Webhook Types Response:

[
    {
        "id": "2c188600-e7ff-4039-bcb2-03a6dab99c13",
        "system_name": "candidate.created",
        "description": "A new candidate has been created."
    },
    {
        "id": "48a9b600-e7ff-4039-bcb2-04cddab97ba8",
        "system_name": "report.completed",
        "description": "A new report has been completed."
    }
]

As you can see from the response, each webhook type will have an associated id, system_name, and description. You may use the id and system_name when referencing the webhook type when creating new webhooks.

Webhook Signature

Setting up the API Key

Webhook signatures can be set up to securely validate that a POST request came from Yardstik. To set up a webhook signature, create a key named WEBHOOK_SIGNATURE (see: Authentication). Your webhook signature is the API key created in the Authentication section. Make sure you copy the key before leaving the page, as it will not be saved. Store the key in a .env file with the name WEBHOOK_SIGNATURE.

The Algorithm

Yardstik will use your WEBHOOK_SIGNATURE token to sign the webhook body we send to the callback url, and include it in the x-yardstik-webhook-signature header. Yardstik uses a HMAC hex digest to compute the hash.

Verifying Authenticity

A verification function can be used to validate the HMAC-SHA256 value using a crypto library of your choice, such as the Node.js standard crypto module. Make sure to add the library as a dependency at the top of your script. The function should calculate a hash using your WEBHOOK_SIGNATURE key, and ensure that the result matches the hash from Yardstik.

Code Sample

The following code sample displays one way to validate the webhook response.

{
  var body = {
      "id":"bd17432e-80fb-4519-a82f-64343be8ca76",
      "event":"updated",
      "resource_id":"0aa4bc0b-ef11-4799-b38e-c27fdf0fd0b5",
      "account_id":"16fba427-2ab5-4ed0-8a37-16ab51519a5e",
      "account_name":"Skynet",
      "resource_type":"invitation",
      "resource_url":"https://api.yardstik.com/invitations/0aa4bc0b-ef11-4799-b38e-c27fdf0fd0b5"
    }

  const hash = crypto.createHmac('sha256', WEBHOOK_SIGNATURE).update(JSON.stringify(body)).digest('hex');
}

This code block will create a hash that can be validated directly against the x-yardstik-webhook-signature header. The function above uses your WEBHOOK_SIGNATURE key, the payload sent to the API (body), and the crypto library from Node.js. Additional sample webhook responses, POST bodies, and more are available in the Using Webhooks section.

Support

If your webhook signature has been lost or compromised, you can decommission it from the Dashboard and create a new one. You can view best practices for keeping your keys safe here. If your webhook signature isn't working, don't hesitate to reach out to support.

Using webhooks

Listening for candidate.created Webhook

For example, you may register a webhook for candidate.created. This webhook will be triggered when a new candidate is created.

You can create a new webhook using the Create Webhook Route.

Example Create candidate.created Webhook Response:

{
    "id": "a87b1e1a-e9aa-4929-9f30-ad1f9b481a8c",
    "url": "https://www.yourcompany.com/webhooks/candidate_created",
    "webhook_type": "candidate.created"
}

Example candidate.created Webhook POST body:

{
  "id": "dcd9a3db-d885-4695-8a92-5556126000c5",
  "event": "created",
  "resource_id": "67cae505-0bac-4eaf-a255-95421d04e303",
  "account_id": "e829bc40-89eb-4054-94e3-7e826373f8ec",
  "account_name": "Venture Industries",
  "resource_type": "candidate",
  "resource_url": "https://api.yardstik.com/candidates/67cae505-0bac-4eaf-a255-95421d04e303"
}

Now that the webhook was triggered, you should receive the response body presented above. You can use this to get the candidate from the resource_url key.

Listening for report.created Webhook

Let's say you also want to be notified when a background report has been started. To do so, you can register for the report.created event.

Example Create report.created Webhook Request:

curl -X POST https://api.yardstik.com/accounts/[YOUR_ACCOUNT_ID]/webhooks \
    -H 'Authorization: Account [YOUR_API_KEY]' \
    -H 'Accept: application/json'
    -H 'Content-Type: application/json' \
    --data-raw '{
        "webhook_type_id": "48a9b600-e7ff-4039-bcb2-04cddab97ba8",
        "url": "https://www.yourcompany.com/webhooks/report_created"
    }'

Again, you would create a webhook for report.created.

Example Create report.created Webhook Response:

{
    "id": "89ade71a-e9aa-4929-9f30-ad1f93245abf",
    "url": "https://www.yourcompany.com/webhooks/report_created",
    "webhook_type": "report.created"
}

And once a report is created, you will be sent this:

Example report.created Webhook POST body:

{
  "id": "e7331072-7865-4dca-9cd2-1643656a84c7",
  "event": "created",
  "resource_id": "e7e0b119-7714-44a2-900e-9b98a4e5b1c6",
  "account_id": "e829bc40-89eb-4054-94e3-7e826373f8ec",
  "account_name": "Venture Industries",
  "resource_type": "report",
  "resource_url": "https://api.yardstik.com/reports/e7e0b119-7714-44a2-900e-9b98a4e5b1c6"
}

Listening for sub_account.active Webhook

If you are an Admin for a platform account and want to manage your subaccount, you can do so using the sub_account.active webhook. If you are not sure whether you are managing a platform account or not, there is more information here.

Example Create sub_account.active Webhook Request:

curl -X POST https://api.yardstik.com/accounts/[YOUR_ACCOUNT_ID]/webhooks \
    -H 'Authorization: Account [YOUR_API_KEY]' \
    -H 'Accept: application/json'
    -H 'Content-Type: application/json' \
    --data-raw '{
        "webhook_type_id": "48a9b600-e7ff-4039-bcb2-04cddab97ba8",
        "url": "https://www.yourcompany.com/webhooks/sub_account_active"
    }'

Example Create sub_account.active Webhook Response:

{
    "id": "89ade71a-e9aa-4929-9f30-ad1f93245abf",
    "url": "https://www.yourcompany.com/webhooks/report_completed",
    "webhook_type": "sub_account.active"
}

Example sub_account.active Webhook POST body:

{
  "id": "ca64ad1a-2018-41c4-b369-dd5c3c1581dc",
  "event": "active",
  "resource_id": "21e2830c-b886-4234-a31d-5fa316069b21",
  "account_id": "e829bc40-89eb-4054-943-7e826373f8ec",
  "account_name": "Venture Capital",
  "resource_type": "sub_account",
  "resource_url": "https://api.yardstik.com/accounts/21e2830c-b88e-42e-a5ed-5e316069b21"
}

This webhook can be used to determine when a subaccount under your platform account is created, so that you can perform whatever operations are needed.

Reports

Once a candidate has submitted their information and the report has been completed, you may view the report results by retrieving the report.

Example Report Request

curl -X GET https://api.yardstik.com/reports/[reportID] \
    -H 'Authorization: Account [YOUR_API_KEY]' \
    -H 'Accept: application/json'

Example Report Response

{
    "id": "74deed63-8bae-431f-ab56-af2139e261e4",
    "reference_id": null,
    "candidate_id": "018e6289-78e9-45b8-9c8e-9d78f8b4fba4",
    "account_id": "cc0df11d-a502-47ec-8aa1-ba0738030ca7",
    "status": "completed",
    "decision": "clear",
    "account_name": "General Dynamics",
    "report_url": "[URL to Report PDF]"
    "adverse_action_id": null,
    "report_screenings": [
        {
            "screening": "NationalCriminal"
        },
        ...
    ],
    ...
}

Once a report has been completed, it will be assigned a status. The available statuses can be found below.

Report Status

Status Types: There are many different statuses that a candidate's report can be in. Below is a table that describes what each of the statuses mean.

Status Definition
expired A report may become expired when tied to an invitation. For more details about invitations and expirations, see Invitations.
pre_adverse An account owner or user has decided that there are violations that could disqualify the candidate from employment. Once a candidate is in this status, they will have a limited amount of time to respond before they are either in the final adverse or proceed status. More details can be found here.
final_adverse The candidate pre_adverse response time window has expired and they either didn't reply or they didn't give enough evidence to go into proceed.
consider The report has come back with one or more violations that may disqualify the candidate. An account user needs to review the report.
ys_qa_review This status means that we have found records on the report and it is being handled by our Verification Specialist. This status will only happen if your account adverse action process is handled by Yardstik.
created The report was successfully created. Processing has not begun.
pending_approval The report is in processing, but requires guardian consent before advancing. A Yardstik Verification Specialist has reached out to the guardian provided and is awaiting response.
approved_to_process Guardian consent has been provided and reviewed. The Yardstik Verification Specialist approves the report to advance to the next workflow status.
exception There is an issue with the report (e.g., SSN is incorrect) (contact support).
canceled The report was canceled through user action or API request.
dispute The candidate has filed a dispute against the report data provided. A Yardstik Operations team member will handle the dispute process.
info_requested The information that the candidate originally supplied was not enough to complete the verification. A Yardstik Verification Specialist has reached out to them to gather the rest of the required information.
processing A Yardstik Verification Specialist is researching the report.
pending A screening in the report is awaiting response from a third party system. e.g., County Criminal records check.
queued This is an ephemeral status used when a report has multiple screenings in process sequential, where one has been completed while the others are queued to advance to the next workflow status.
archived This is an internal status used to designate a report as invalid and mark it for deletion, following the Yardstik Data Retention Policy.
proceed The report has come back with some data that may disqualify the candidate. The account user has decided the data was not sufficient to disqualify them and has completed the report.
clear The screenings in the report are complete. The research process did not produce any disqualifying information about the candidate.

See Reports for more information.

Sample Redirect Flow

To create a candidate, collect the candidate's information and send the information gathered to our /candidates route via a POST method. This will be processed by our system and return a candidate ID that is used to create a report.

Using the candidate ID, along with your account ID and an account package ID, you will POST this data to the /reports endpoint and generate a new report. This will return the apply url, which will be given to the candidate to fill out the intake form.

Once the candidate fills out the form and submits disclosures, the report will begin processing.

alt text

Adverse Action Process

When a report comes back with the a consider status, this indicates that there were some violations that may disqualify the candidate for employment or tenancy.

From here, the candidate is reviewed by either a client user or an API user to make the final decision on whether or not the candidate is disqualified. If the candidate is set to pre_adverse, then as required by the FCRA, a pre_adverse action email will be sent on your behalf to the candidate based on the timeline selected (days). The number of days provides time for the candidate to respond to you with any further information to use in the decision process. If there is no response, the final adverse action will be sent automatically following the number of days selected. According to the FCRA, the minimum number of days a candidate is allowed to respond to an adverse action is 7 days. This time frame can be extended in the account notifications settings.

When creating an adverse action you must consider that not all adverse actions act the same. The vast majority will work the way presented above and below. If the candidate is completing a background screening in order to become a tenant in an apartment complex, there is no need to have this process. They will go directly into the final adverse status. When the tenant is placed directly into final adverse, a reason must be selected. This will be presented to the denied tenant.

Note that only reports set to consider can be placed in the pre_adverse status.

Here is the route documentation for how to Create a Adverse Action for a Report.

Adverse Action Flow

Example Adverse action Error Response

{
   {
      "title": "Report Not Found",
      "detail": "The report was not found",
      "meta": {
        "report_id": "INVALID_REPORT_ID"
       },
    "src": {},
    "status": 404
  }
}

Adverse Action Violations

During the process of creating an adverse action, you may need to provide a list of violations.

If a report comes back with a status of consider, then there may be an additional step. If the violations don't disqualify the candidate, your account can proceed with the candidate. If they do, then you need to create an Adverse Action Letter.

When an Adverse Action Letter is created in Yardstik, an email is sent to the candidate. The email will contain the details of what could disqualify them from the position, and what their next steps are.

If the candidate is from the state of Georgia or California, then when you create the adverse action email, you need to provide an explanation of what specifically disqualified them from the position. When you try to create an adverse action and it fails, a proper message will be returned to you. Check the 422 Unprocessable Entity Response at the Create a Adverse Action Route.

We call these explanations violations. These violations are included in the adverse action letter that is emailed to the candidate in question.

How do I know if the violations parameter is required?

In the response of the Get a Report Route, you will have the adverse_action_settings key.

Example:

  adverse_action_settings: {
    "mandatory_selection_of_violations": false
  }

In the response, you have the mandatory_selection_of_violations key, which tells you whether you should or should not send violations when creating a new adverse action.

Which violations can I send?

In the response of the Get a Report Route, you will have the report_screenings key, which is an array. For each report screening, you will have records, which is also an array. Finally, inside each record you will have violations, which is another array.

A record may not have violations. For example, a clear report will probably not have any violations.

For each violation, you will have a description, and it also could have a disposition and disposition_date.

You can map all the violations and select the ones you want to send to the candidate.

Here's an example of a full report response:

{
    "id": "2ee83662-ea17-4233-95b9-288ee3fcb9ff",
    "reference_id": null,
    "candidate_id": "66bdcd96-adf8-4b8a-b599-ea0040a11b79",
    "status": "consider",
    "response_status": null,
    "submitted_at": "2021-04-26T22:33:18.269Z",
    "completed_at": "2021-04-30T15:44:24.333Z",
    "created_at": "2021-04-26T21:51:06.880Z",
    "decision": "",
    "usage_amount": null,
    "process_sequentially": true,
    "created_by": "cool_email@yardstik.com",
    "permissible_purpose": {
        "id": "a2c00755-b57e-40e1-9876-2c5640ce53be",
        "name": "Employment",
        "configurations": { "initial_status": "pre_adverse" }
      }
    },
    "candidate": {
        "id": "66bdcd96-adf8-4b8a-b599-ea0040a11b79",
        "full_name": "John Clean",
        "email": "cool_email@yardstik.com",
        "phone_masked": null,
        "date_of_birth_masked": "#######-12",
        "ssn_masked": null,
        "driver_license_number_masked": null,
        "full_address": {
            "address": "Mineapolis",
            "zip_code": "12345",
            "city": "Mineapolis",
            "state": "MN"
        },
    },
    "account_id": "d210dcdd-c9d4-4ced-a594-8402cb6a2ab4",
    "account_name": "Account Name",
    "report_url": null,
    "adverse_action_id": null,
    "report_screenings": [
        {
            "id": "e11b7d00-9b55-4879-8f6e-c3859f16347d",
            "type": "Criminal",
            "label": "CountyCriminal",
            "name": "CountyCriminal",
            "status": "consider",
            "order": 0,
            "decision": "Consider",
            "response_status": "ready",
            "created_at": "2021-04-26T22:33:18.218Z",
            "report_url": "",
            "elapsed_timing": "1 week",
            "records": [
                {
                    "category": {
                        "key": "County",
                        "value": "NY-NYOCA"
                    },
                    "messages": [],
                    "violations": [],
                    "personal_data": {},
                    "other_information": {
                        "jurisdiction": "NY-NYOCA",
                        "pending_notes": null
                    }
                }
            ],
            "comments": []
        },
        {
            "id": "c6851635-9ce4-47ce-a246-531fbe36aac0",
            "type": "Criminal",
            "label": "StateCriminalCourt",
            "name": "StateCriminalCourt",
            "status": "consider",
            "order": 0,
            "decision": "Consider",
            "response_status": "ready",
            "created_at": "2021-04-26T22:33:18.228Z",
            "report_url": "",
            "elapsed_timing": "1 week",
            "records": [
                {
                    "category": {
                        "key": "State",
                        "value": "NEW YORK"
                    },
                    "messages": [],
                    "violations": [
                        {
                            "comments": null,
                            "sentence": "24 Months Or Pretrial Intervention Next Court Date 01/01/2021",
                            "file_date": "2021-03-20",
                            "case_number": "ABCDEFG",
                            "description": "Felony",
                            "disposition": "Court: Pre Trial Intervention",
                            "jurisdiction": "NEW YORK",
                            "offense_date": null,
                            "count_offense": "1. Possession Of Schedule 4 Substance",
                            "dob_on_record": "XXXX-04-01",
                            "ssn_on_record": null,
                            "name_on_record": "MESS, HANK",
                            "disposition_date": "2021-03-20"
                        },
                        {
                            "description": "This one Has Only the description",
                        }
                    ],
                    "personal_data": {},
                    "other_information": {
                        "jurisdiction": "NEW YORK",
                        "pending_notes": null
                    }
                },
                {
                    "category": {
                        "key": "State",
                        "value": "MINNESOTA"
                    },
                    "messages": [],
                    "violations": [
                        {
                            "comments": null,
                            "sentence": "24 Months Or Pretrial Intervention Next Court Date 10/08/2015",
                            "file_date": "2014-08-20",
                            "case_number": "POIUYTREWQ",
                            "description": "Felony",
                            "disposition": "Court: Pre Trial Intervention",
                            "jurisdiction": "MINNESOTA",
                            "offense_date": null,
                            "count_offense": "1. Possession Of Schedule 4 Substance",
                            "dob_on_record": "XXXX-04-01",
                            "ssn_on_record": null,
                            "name_on_record": "MESS, HANK",
                            "disposition_date": "2015-09-18"
                        },
                        {
                            "comments": null,
                            "sentence": "24 Months Or Pretrial Intervention Next Court Date 10/08/2015",
                            "file_date": "2014-08-20",
                            "case_number": "502008CF012155YXYXMB",
                            "description": "Felony",
                            "disposition": "Court: Pre Trial Intervention",
                            "jurisdiction": "MINNESOTA",
                            "offense_date": null,
                            "count_offense": "2. Possession Of Schedule 2 Substance",
                            "dob_on_record": "XXXX-04-01",
                            "ssn_on_record": null,
                            "name_on_record": "MESS, HANK",
                            "disposition_date": "2014-09-18"
                        },
                        ...
                    ],
                    "personal_data": {},
                    "other_information": {
                        "jurisdiction": "MINNESOTA",
                        "pending_notes": null
                    }
                }
            ],
            "comments": []
        }
    ],
    "report_screenings_total": 2,
    "report_screenings_completed": 2,
    "elapsed_timing": "4 days",
    "package_name": "State Criminal Court",
    "comments": [],
    "course": {
        "has_courses": false,
        "courses_completed": false
    },
    "meta": {
        "entity": "https://app.yardstik.com/reports/1234....",
        "apply": "https://profile.yardstik.com/candidates/1234
    },
    "adverse_action_settings": {
        "mandatory_selection_of_violations": false
    }
}

Pagination

All top-level API resources have support for bulk fetches via list API methods. Yardstik uses page-based pagination via the page and per_page parameters. For instance, you can list invitations, candidates, and reports.

Standard Request

Example Paginated Request

curl -X GET https://api.yardstik.com/invitations?page=2&per_page=25 \
    -H 'Authorization: Account [YOUR_API_KEY]' \
    -H 'Accept: application/json'

Paginated list API Request Parameters:

Parameter Description
page The page number to retrieve.
type: integer
default: 1
per_page The number of records per page.
type: integer
default: 50
minimum: 1
maximum: 200

The page parameter determines which page of results will be returned in the response, and defaults to 1 if not set or set to an invalid type. If the value of page exceeds the total_number of pages available, the response will include an empty data array.

The per_page parameter determines the maximum number of results included in each response. The maximum value allowed is 200, with a default value of 50.

  • If there are fewer resources available than the per_page value, the response will include all available resources.
  • If you pass more than 200, the response will still include only 200.
  • If the per_page value is an invalid type, the default value of 50 is used.

Standard Response

Paginated list API Response Structure

Example Paginated Response

{
    "object": "list",
    "meta": {
        "page": 2,
        "per_page": 25,
        "total_count": 137,
        "total_pages": 6
    },
    "data": [
        {
            "object": "invitation",
            "id": "18e00b78-e620-4ecf-a01a-eb810f1b6751",
            ... additional response attributes based on resource schema
        },
        {
            "object": "invitation",
            "id": "d0102680-e2de-4af8-9034-f88ccb4ad267",
            ... additional response attributes based on resource schema
        },
        ... additional resources in the page
    ]
}

The standard response for all top-level list API requests will include at least these attributes:

Attribute Description
object The type of object returned.
type: string
default: "list"
meta Metadata associated with the response.
Attributes:
Attribute Description
page The page number of the response.
type: integer
per_page The number of results per page.
type: integer
total_count The total number of resources available.
type: integer
total_pages The total number of pages available.
type: integer
data An array of the requested resources.
type: array
Notes: May be an empty array [] if no resources are available.

Filter and Sort

For all listing endpoints, we support a filtering query param called query that allows you to pass a field name and a matcher to use to filter the results down a specific set. We also support two query params called order_by and order that let you pass the field name you want to order by, and the direction you want the results ordered. When combined with Pagination, this allows you to build a custom UI that lists out resources with ease.

Filtering

Parameter Description
query Field name to filter on.
type: string

Get only reports created before Jan 1 2021

curl -g -X GET \
  'https://api.yardstik.com/reports?query[created_at_lt]=2022-01-01' \
  -H 'Authorization: Account [YOUR_API_KEY]' \
  -H 'Accept: application/json'

Get only reports updated after Jan 1 2021

curl -g -X GET \
  'https://api.yardstik.com/reports?query[updated_at_gteq]=2022-01-01T00:00:00.000Z'
  -H 'Authorization: Account [YOUR_API_KEY]' \
  -H 'Accept: application/json'

Get reports created between March 23 2021 and April 1 2021

curl -g -X GET \
  'https://api.yardstik.com/reports?query[created_at_lt]=2021-04-01&query[created_at_gt]=2021-03-23' \
  -H 'Authorization: Account [YOUR_API_KEY]' \
  -H 'Accept: application/json'

Matchers

Predicates Description Notes
*_eq Equal query[status_eq]=created
Individual check, to do multiple see *_in
*_not_eq Not equal query[status_not_eq]=created
Individual check, to do multiple see *_not_in
*_lt Less than query[created_at_lt]=2022-01-01
*_lteq Less than or equal to query[created_at_lteq]=2022-01-01
*_gt Greater than query[created_at_gt]=2022-01-01
*_gteq Greater than or equal to query[created_at_gteq]=2022-01-01
*_null Is null query[completed_at_null]=true
*_not_null Is not null query[completed_at_not_null]=true
*_in Match any value in array query[status_in][]=clear&query[status_in][]=consider
*_not_in Match none of the values in array query[status_not_in][]=clear&query[status_not_in][]=consider
*_start Starts with query[status_start]=con
*_not_start Does not start with query[status_not_start]=con
*_end Ends with query[status_end]=sider
*_not_end Does not end with query[status_not_end]=sider
*_cont Contains query[status_cont]=con
*_not_cont Does not contain query[status_not_cont]=con
*_true Is true query[active_true]=true
*_false Is false query[active_false]=true

Sorting

Parameter Description
order_by Field name to sort on.
type: string
order Specifies the direction to sort.
Accepts asc and desc.
Defaults to asc when not passed
type: string

Order candidates by created_at in default ascending order (oldest first)

curl -g -X GET \
  'https://api.yardstik.com/reports?order_by=created_at
  -H 'Authorization: Account [YOUR_API_KEY]' \
  -H 'Accept: application/json'

Order candidates by updated_at in descending order (newest first)

curl -g -X GET \
  'https://api.yardstik.com/reports?order_by=updated_at&order=desc
  -H 'Authorization: Account [YOUR_API_KEY]' \
  -H 'Accept: application/json'

Combine it all together

You can use pagination, querying and ordering all on the same call to fully control the results. This will get all reports created between March 23 2021 and April 1 2021 and order them by the created_at field with newest first while limiting the results to 20 per page.

curl -g -X GET \
  'https://api.yardstik.com/reports?query[created_at_lt]=2021-04-01&query[created_at_gt]=2021-03-23&order_by=created_at&order=desc&page=1&per_page=20' \
  -H 'Authorization: Account [YOUR_API_KEY]' \
  -H 'Accept: application/json'

Errors

We return a number of standard HTTP errors. Below are some of the most common errors that you may run into while developing.

Status Definition
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
422 Unprocessable Entity
500 Internal Server Error

Below are the status codes with more information on what could have occurred.

Bad Request

The server cannot process the request. This error is most likely due to malformed request syntax.

  • code: 400
  • status: Bad Request

Bad Request

Response Schema: application/json
errors
Array of strings
application/json
{
  • "errors": [
    ]
}

Unauthorized

Similar to a 403 Forbidden, but specifically when authentication is provided and has failed, or not been provided.

This error is most likely due to not including or having a malformed API key in the request header.

  • code: 401
  • status: Unauthorized

Unauthorized

Response Schema: application/json
errors
Array of strings
application/json
{
  • "errors": [
    ]
}

Forbidden

The request is valid, but you are unable to execute the request. This error is most likely due to the API key not having the necessary permissions, or a prohibited action is attempted, such as creating a duplicate record where one already exists.

  • code: 403
  • status: Forbidden

Forbidden

Response Schema: application/json
errors
Array of strings
application/json
{
  • "errors": [
    ]
}

Not Found

The requested resource could not be found but may be available in the future. This error is often encountered when an id that does not exist is passed in a request. If you encounter this error, ensure that you are referencing the correct id and that it exists in your account.

  • code: 404
  • status: Not Found
{
  {
    "title": "Report Not Found",
    "detail": "The report was not found",
    "meta": {
      "report_id": "INVALID_REPORT_ID"
     },
    "src": {},
    "status": 404
  }
}

Unprocessable Entity

The request was well-formed, but was unable to be processed due to semantic errors. This error is most likely due to including invalid data in POST, PATCH, and PUT requests. Refer to the request documentation to ensure you are supplying the required attributes, and that the attribute types are correct.

  • code: 422
  • status: Unprocessable Entity

Unprocessable Entity

Response Schema: application/json
detail
string

Detailed message about the error.

meta
object

An object with more details about the response error.

src
object

An object containing references to the source of the error.

status
integer

Status code of the error.

title
string

A brief title of the error.

application/json
{
  • "title": "Resource not updated",
  • "detail": "There was a problem updating this resource.",
  • "meta": { },
  • "src": { },
  • "status": 422
}

Internal Server Error

An internal server error occurred due to an unexpected condition, and is most likely due to an issue with our servers. If you encounter such an error, please reach out to support@yardstik.com and we will work with you to resolve the issue.

  • code: 500

  • status: Internal Server Error

Embeddable Views

Yardstik has published a public npm library for utilizing Yardstik embeddable views:

https://www.npmjs.com/package/@yardstik/embeddable-sdk

Installation

The Yardstik embeddable-sdk library is available as an npm package.

  • with npm npm i @yardstik/embeddable-sdk

  • with yarn yarn add @yardstik/embeddable-sdk

Getting Started

Here is a quick example to get you started:

import { Yardstik } from '@yardstik/embeddable-sdk';

Available Views

Each available page view is a separate method on the exported Yardstik library object. The currently supported views are as follows:

  1. CandidateReportIframe: Allows the user to view and interact with a candidate report.
  2. AccountDisclosuresIframe: Allows the user to view and agree to account level agreements and terms.

Creating an Instance of an Available View

To create an instance of the desired view, which will be attached to a specified container on your page, call the applicable method and pass in the configuration object. For example:

  const yardstikReport = new Yardstik.CandidateReportIframe(
    {
      token: myToken,
      reportId: myReportId,
      container: containerRef.current,
      domain: myDomain
    }
  );

CandidateReportIframe

The config object for the CandidateReportIframe takes the following parameters:

token: string - JWT for authorization

reportId: string - The ID of the report that you would like to review

container: HTMLElement - Container to which the iframe will be attached

domain: string - Yardstik domain that you would like to call

width?: string - Optional width of the iframe

height?: string - Optional height of the iframe

fullScreen?: boolean - Optional, if true, iframe will fill the entire page

AccountDisclosureIframe

The config object for the AccountDisclosureIframe takes the following parameters:

token: string - JWT for authorization

accountId: string - The ID of the account that you would like to review

container: HTMLElement - Container to which the iframe will be attached

domain: string - Yardstik domain that you would like to call

width?: string - Optional width of the iframe

height?: string - Optional height of the iframe

fullScreen?: boolean - Optional, if true, iframe will fill the entire page

Obtaining JWT

To obtain a JWT to include in the config object (from your backend), make a request to the JWT Route using your API token for authorization.

Shared Methods For Use By Parent Page

Each view has a shared method that can be called by the parent page and utilized for customization and performance.

destroy: When called, the destroy method will remove the iframe from its parent container. This method can be used by the parent page for clean-up.

yardstikReport.destroy()

Message Events

In order to allow the parent to take action, each iframe view is set up to post certain message events to the parent page in which it is contained.

loaded: Each iframe instance will post a 'loaded' message event when the iframe content has fully loaded. The parent page could listen for this event to trigger an action, such as rendering the iframe visible or turning off a loading animation. For example:

  yardstikReport.on('loaded', () => {
    console.log("The iframe is ready.");
    setIframeReady(true)
  ;})

expiration: Each iframe instance will post an 'expiration' message event when the authorization token has expired. The parent can listen for this event to trigger an action, such as requesting a new JWT from your backend to refresh the session or instructing the user to refresh the page, so that a new token is generated. For example:

  yardstikReport.on('expiration', () => {
  console.log("The JWT has expired.");
  setTokenExpired(true);
})

Subaccounts

The Subaccount is basically an Account with a Parent Account associated with it.

With this association the Parent Account can provide a white label experience for the Subaccounts.

To create a Subaccount you have first to be enabled to do that, please reach out to support@yardstik.com in case you want to create and manage Subaccounts.

There are two important parameters you should provide when create a Subaccount: a Permissible Purpose and one or more Account Package.

To check the request details to create a Subaccount access: Create Subaccount Route

Permissible Purposes

Every account has at least one Permissible Purpose, a Permissible Purpose is a reason why a report is being requested on the Candidate. Here is a list of the possible Permissible Purposes:

  • Employment
  • Tenant
  • Consumer account review to meet requirements

Since an Account can have more than one Permissible Purpose, during the creation of a Subaccount you have to provide a permissible_purpose_id or the Subaccount that is being created.

To know what Permissible Purposes the Parent Account has, check the Get Account Route and in the response body will have permissible_purposes from the array you can determine the id of a given permissible purpose.

When you create a Subaccount, set the permissible_purpose_id with the id of the permissible_purposes you wish to use from the Parent Account.

You can set only one permissible_purpose_id for the Subaccount.

Account Packages

An Account Package contains the Screens that we will run for a Candidate. Any time you create an Invitation or a Report, an account_package_id must be provided.

During the creation of a Subaccount one or more Account Packages can be defined.

The list of AccountPackages that can be provided for the Subaccount can be found in here: Account Packages List.

When you create a Subaccount you will have to provide account package ids for: account_packages as an array with at least the id. So when the Subaccount is created it also creates the AccountPackages with the same configurations of the Parent Account.

Inside the account_packages your objects must follow this format:

  • id: The Parent AccountPackage ID.
  • name: The name for the Subaccount AccountPackage, if not provided will be the same as the Parent AccountPackage
  • paid_by: With the possible options of account or candidate. If not provided will be the same as the Parent AccountPackage.

Note: The paid_by param defines who will pay for the Report, if it's the Account or the Candidate. In case it's the Candidate a Payment form will show to the Candidate provide his credit card information and the report will only start to be processed after the payment is completed.

Example in how to provide the account_packages parameter:

  "account_packages": [
      {
          "id": "The UUID of one of the Parent AccountPackage",
          "name": "The Name for the Subaccount AccountPackage",
          "paid_by": "candidate"
      },
      {
          "id": "The UUID of one of the Parent AccountPackage",
          "name": "If not provided will be the same as the Parent AccountPacakge",
          "paid_by": "account"
      }
  ]

Click in here for more details how to create a Subaccount

Credentialing the Subaccount

After the Subaccount is created, an email will be sent to the Owner of the Subaccount, the Owner is created based on the parameter email_address provided during the Subaccount creation.

In that email, the Owner of the Subaccount will have a link that will take then to our application where it will ask them to sign the legal documents.

After the Owner signs the Legal Documents, our onboard specialists will review all the information provided and may require more information or more documents to be signed.

When everything is finished, the Subaccount will be credentialed and the Owner will be notified and it can start using Yardstik's platform.

Note: Only after the account is credentialed that the API Key generated on the Subaccount create route will be active. Once the API key is active it can be used to manage Yardstik resources via the API. You can also subscribe to the Webhook Type: account.updated so when any of Subaccount is updated you will receive a callback and you can check if that account is with the status credentialed.

If you encounter any error or have questions, please reach out to support@yardstik.com

Accounts

Accounts are your primary resource for configuring the Yardstik platform.
Use this to manage users, settings, and API keys.

List all accounts

List all accounts that you have access to.

SecurityApiKey
Request
query Parameters
order
string

Order listing results in ascending or descending order, when using order_by.
Accepted values are asc or desc. If not passed, defaults to ascending asc.

Examples:
order=desc
order_by
string

Order listing results by a specific property.

Examples:
order_by=created_at
page
integer

The page number to retrieve.

per_page
integer

The maximum number of results per page.

query
string

Filter listing results by a specific property.

Examples:
query[created_at_gteq]=2022-01-01T00:00:00.000Z
Responses
200

OK

400

Bad Request

401

Unauthorized

403

Forbidden

404

Not Found

get/accounts
Request samples
Response samples
application/json
[
  • {
    }
]

Create an API key

Generate a new API key.

SecurityApiKey
Request
path Parameters
accountId
required
string
Request Body schema: application/json
name
string

The name of the API key

Responses
201

Created

401

Unauthorized

403

Forbidden

404

Not Found

422

Unprocessable Entity

post/accounts/{accountId}/api_token
Request samples
application/json
{
  • "name": "string"
}
Response samples
application/json
{
  • "id": "70adc786-904b-4954-9adb-0ede9f949c62",
  • "api_token": "c6b6e55f-5b3a-479a-9ea8-d95d13856c7d",
  • "name": "Checking x",
  • "header": "Authorization: User c6b6e55f-5b3a-479a-9ea8-d95d13856c7d"
}

Get all settings

Account settings for a given account ID.

SecurityApiKey
Request
path Parameters
accountId
required
string
Responses
200

OK

401

Unauthorized

404

Not Found

get/accounts/{accountId}/settings
Request samples
Response samples
application/json
{
  • "styles": {
    },
  • "invitations": {
    },
  • "report_notifications": {
    }
}

Get an account setting

Get a single account setting for the given account ID and setting key.

SecurityApiKey
Request
path Parameters
accountId
required
string
settingKey
required
string
Responses
200

OK

401

Unauthorized

404

Not Found

get/accounts/{accountId}/settings/{settingKey}
Request samples
Response samples
application/json
{
  • "primary_color": "FFCD01",
  • "secondary_color": "FFCD01"
}

Update an account setting

Update an account setting for the given account ID and setting key.

SecurityApiKey
Request
path Parameters
accountId
required
string
settingKey
required
string
Request Body schema: application/json
object
Responses
200

OK

400

Bad Request

401

Unauthorized

403

Forbidden

404

Not Found

422

Unprocessable Entity

patch/accounts/{accountId}/settings/{settingKey}
Request samples
application/json
{
  • "primary_color": "FFCD01"
}
Response samples
application/json
{ }

Get an account

Account details.

SecurityApiKey
Request
path Parameters
accountId
required
string
Responses
200

OK

201

Created

400

Bad Request

401

Unauthorized

404

Not Found

get/accounts/{accountId}
Request samples
Response samples
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "account_name": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "owner_email": "user@example.com",
  • "email_address": "user@example.com",
  • "url": "string",
  • "tech_email_address": "user@example.com",
  • "support_email_address": "user@example.com",
  • "support_phone": "string",
  • "compliance_email_address": "user@example.com",
  • "actions_email_address": "user@example.com",
  • "address": {
    },
  • "logo": "string",
  • "meta": {
    },
  • "permissible_purposes": [
    ]
}

Subaccounts

Subaccounts are children of a parent account, and can be used to isolate resources and configuration settings.

List subaccounts

Retrieve a paginated list of all subaccounts that your account is parent of. See Pagination.

SecurityApiKey
Request
query Parameters
order
string

Order listing results in ascending or descending order, when using order_by.
Accepted values are asc or desc. If not passed, defaults to ascending asc.

Examples:
order=desc
order_by
string

Order listing results by a specific property.

Examples:
order_by=created_at
page
integer

The page number to retrieve.

per_page
integer

The maximum number of results per page.

query
string

Filter listing results by a specific property.

Examples:
query[created_at_gteq]=2022-01-01T00:00:00.000Z
Responses
200

List of subaccounts

400

Bad Request

401

Unauthorized

403

Forbidden

404

Not Found

get/sub_accounts
Request samples
Response samples
application/json
{
  • "object": "list",
  • "meta": {
    },
  • "data": [
    ]
}

Create a subaccount

Create a Subaccount from a parent account that has been enabled as a platform account.
To create a Subaccount you will need to provide one Permissible Purpose.
You also can provide the account_packages information of your parent Account.

Upon creating a new subaccount you will get a 201 Created response.
If you send another POST with the same account_name it will refresh the API token and return 200 OK with the existing account details.
To make any further updates to the new subaccount, use the new API key from that account and call the PATCH Accounts route.

SecurityApiKey
Request
Request Body schema:
account_name
required
string

Name of the subaccount.

Array of objects
actions_email_address
string

Actions email address of the subaccount.

additional_company_info
string

Any extra information that you want to provide.

required
object
company_phone_number
string

This is for our business verification purposes and will not be included on candidate communication. Must be E.164 format, e.g. +14155552671.

compliance_email_address
string

Compliance email address of the subaccount.

create_api_key
boolean

If false, an API key will not be created. This value defaults to true.

email_address
required
string

Email address of the subaccount primary contact. This user will be the owner of the subaccount, and will also be responsible for signing the legal documents for Account Accreditation.

See the documention about the Credentialing the Subaccount for more details.

first_name
required
string

First name of the subaccount primary contact.

last_name
required
string

Last name of the subaccount primary contact.

permissible_purpose_id
required
string <UUID>

The unique identifier for the subaccount permissible purpose.

support_email_address
string

Support email address of the subaccount.

support_phone
string

Support phone number of the subaccount. Must be E.164 format, e.g. +14155552671.

tech_email_address
string

Tech email address of the subaccount.

url
string

Relevant URL for subaccount.

Responses
200

Account already exists

201

Created

400

Bad Request

401

Unauthorized

404

Not Found

422

Unprocessable Entity

post/sub_accounts
Request samples
{
  • "email_address": "string",
  • "account_name": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "company_phone_number": "string",
  • "additional_company_info": "string",
  • "url": "string",
  • "tech_email_address": "string",
  • "support_email_address": "string",
  • "support_phone": "string",
  • "actions_email_address": "string",
  • "compliance_email_address": "string",
  • "permissible_purpose_id": "string",
  • "address": {
    },
  • "account_packages": [
    ],
  • "create_api_key": true
}
Response samples
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "account_name": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "owner_email": "user@example.com",
  • "email_address": "user@example.com",
  • "url": "string",
  • "tech_email_address": "user@example.com",
  • "support_email_address": "user@example.com",
  • "support_phone": "string",
  • "compliance_email_address": "user@example.com",
  • "actions_email_address": "user@example.com",
  • "address": {
    },
  • "logo": "string",
  • "meta": {
    },
  • "permissible_purposes": [
    ],
  • "api_tokens": [
    ]
}

Get a subaccount

You can get the details of any subaccount that your account is the parent of.

SecurityApiKey
Request
path Parameters
sub_account_id
required
string
Responses
200

OK

400

Bad Request

401

Unauthorized

404

Not Found

get/sub_accounts/{sub_account_id}
Request samples
Response samples
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "account_name": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "owner_email": "user@example.com",
  • "email_address": "user@example.com",
  • "url": "string",
  • "tech_email_address": "user@example.com",
  • "support_email_address": "user@example.com",
  • "support_phone": "string",
  • "compliance_email_address": "user@example.com",
  • "actions_email_address": "user@example.com",
  • "address": {
    },
  • "logo": "string",
  • "meta": {
    },
  • "permissible_purposes": [
    ]
}

Account Packages

Account packages are collections of background screens, searches, and verifications used to create a report.

Call the List Account Packages endpoint to get a list of packages available for you to create invitations or reports.
Use this to maintain a list of currently enabled packages for your account. As packages are added and removed from your account, this will allow you
to get the IDs and descriptions without hard coding them in your application.

List packages for an account

Returns a list of available Account Packages for the given account ID.

This list will be refreshed as new account packages are added or old ones are removed.
Use id from each package to order new reports or create invitations.
Do not use package_id to order a report, this is a reference ID to the parent package and typically only used internally.

Defaults to listing all report packages, to get monitor packages use the query param query[action_type_eq]=monitor

SecurityApiKey
Request
path Parameters
accountId
required
string
query Parameters
object
Examples:
query[action_type_eq]=report
query[action_type_eq]=monitor
Responses
200

OK

400

Bad Request

401

Unauthorized

403

Forbidden

404

Not Found

get/accounts/{accountId}/packages
Request samples
Response samples
application/json
[
  • {
    },
  • {
    }
]

Candidates

Candidates represent people you would like to conduct a background check on.
All candidates must consent to background checks before any screens can be run.
Use this resource to collect all Personally Identifiable Information (PII) required to request a report or invite the candidate.

List candidates

Retrieve a paginated list of candidates. See Pagination.

SecurityApiKey
Request
query Parameters
order
string

Order listing results in ascending or descending order, when using order_by.
Accepted values are asc or desc. If not passed, defaults to ascending asc.

Examples:
order=desc
order_by
string

Order listing results by a specific property.

Examples:
order_by=created_at
page
integer

The page number to retrieve.

per_page
integer

The maximum number of results per page.

query
string

Filter listing results by a specific property.

Examples:
query[created_at_gteq]=2022-01-01T00:00:00.000Z
Responses
200

List of candidates

401

Unauthorized

404

Not Found

get/candidates
Request samples
Response samples
application/json
{
  • "object": "list",
  • "meta": {
    },
  • "data": [
    ]
}

Create a candidate

The required attributes for a candidate vary depending on its intended use.

If this resource is to be used in conjunction with the Invitations API (in which the invitation apply form collects the Applicant's personal information), the only strictly required Candidate attributes are:

  • first_name,
  • last_name,
  • email

If this resource is to be used to generate any other report type, other personal information is also required.

Attributes required to generate a Report include:

  • middle_name or no_middle_name
  • date_of_birth

Attributes required to generate a Report with a criminal check screening:

  • ssn
  • zip_code

Attributes required to generate a report with a Motor Vehicle Record (MVR) screening:

  • driver_license_number
  • driver_license_state

Attributes recommended to generate a report with an Identity Document Verification screening:

  • phone (mobile phone number)
SecurityApiKey
Request
Request Body schema: application/json
Array of objects

The addresses of the candidate.

date_of_birth
string or null <date-time>

The date of birth of the candidate.

driver_license_number
string or null

The drivers license number of the candidate.

driver_license_state
string or null

The state the candidates drivers license is issued by as ISO 3166-2 two letter code.

email
required
string

The email address of the candidate.

first_name
required
string

The first name of the candidate.

gender
string or null

The gender of the candidate.

last_name
required
string

The last name of the candidate.

object

Relevant links for a candidate

middle_name
string or null

The middle name of the candidate.

no_middle_name
boolean or null

True if candidate has no middle name, otherwise False or null..

phone
string or null

The primary SMS capable phone number of the candidate.
Must be E.164 format, e.g. +14155552671.

previous_driver_license_number
string or null

The previous drivers license number of the candidate.

previous_driver_license_state
string or null

The state the candidates previous drivers license is issued by as ISO 3166-2 two letter code.

ssn
string

The social security number of the candidate.
Must be in this format ###-##-####, e.g. 111-11-1111.

Responses
200

Candidate already exists.

201

Candidate was created successfully.

401

Unauthorized

404

Not Found

422

Unprocessable Entity

post/candidates
Request samples
application/json
{
  • "first_name": "string",
  • "middle_name": "string",
  • "no_middle_name": true,
  • "last_name": "string",
  • "email": "joe.clean@example.com",
  • "phone": "+14155552671",
  • "ssn": "111-22-3333",
  • "date_of_birth": "2019-08-24T14:15:22Z",
  • "gender": "string",
  • "driver_license_number": "string",
  • "driver_license_state": "string",
  • "previous_driver_license_number": "string",
  • "previous_driver_license_state": "string",
  • "meta": {
    },
  • "addresses": [
    ]
}
Response samples
application/json
{
  • "id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "object": "candidate",
  • "first_name": "string",
  • "middle_name": "string",
  • "no_middle_name": true,
  • "last_name": "string",
  • "email": "joe.clean@example.com",
  • "phone": "+14155552671",
  • "ssn_masked": "string",
  • "date_of_birth": "2019-08-24T14:15:22Z",
  • "gender": "string",
  • "driver_license_number": "string",
  • "driver_license_state": "string",
  • "previous_driver_license_number": "string",
  • "previous_driver_license_state": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "meta": {
    },
  • "addresses": {
    }
}

Get a candidate

Retrieve a candidate with the given ID.

SecurityApiKey
Request
path Parameters
candidate_id
required
string <uuid> (ResourceId) <= 50 characters

The candidate unique identifier.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
Responses
200

Candidate details.

401

Unauthorized

404

Not Found

get/candidates/{candidate_id}
Request samples
Response samples
application/json
{
  • "id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "object": "candidate",
  • "first_name": "string",
  • "middle_name": "string",
  • "no_middle_name": true,
  • "last_name": "string",
  • "email": "joe.clean@example.com",
  • "phone": "+14155552671",
  • "ssn_masked": "string",
  • "date_of_birth": "2019-08-24T14:15:22Z",
  • "gender": "string",
  • "driver_license_number": "string",
  • "driver_license_state": "string",
  • "previous_driver_license_number": "string",
  • "previous_driver_license_state": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "meta": {
    },
  • "addresses": {
    }
}

Update a candidate

Update a candidate with the given ID.

SecurityApiKey
Request
path Parameters
candidate_id
required
string <uuid> (ResourceId) <= 50 characters

The candidate unique identifier.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
Request Body schema: application/json
Array of objects

The addresses of the candidate.

date_of_birth
string or null <date-time>

The date of birth of the candidate.

driver_license_number
string or null

The drivers license number of the candidate.

driver_license_state
string or null

The state the candidates drivers license is issued by as ISO 3166-2 two letter code.

email
required
string

The email address of the candidate.

first_name
required
string

The first name of the candidate.

gender
string or null

The gender of the candidate.

last_name
required
string

The last name of the candidate.

object

Relevant links for a candidate

middle_name
string or null

The middle name of the candidate.

no_middle_name
boolean or null

True if candidate has no middle name, otherwise False or null..

phone
string or null

The primary SMS capable phone number of the candidate.
Must be E.164 format, e.g. +14155552671.

previous_driver_license_number
string or null

The previous drivers license number of the candidate.

previous_driver_license_state
string or null

The state the candidates previous drivers license is issued by as ISO 3166-2 two letter code.

ssn
string

The social security number of the candidate.
Must be in this format ###-##-####, e.g. 111-11-1111.

Responses
200

Candidate details.

401

Unauthorized

404

Not Found

422

Unprocessable Entity

patch/candidates/{candidate_id}
Request samples
application/json
{
  • "first_name": "string",
  • "middle_name": "string",
  • "no_middle_name": true,
  • "last_name": "string",
  • "email": "joe.clean@example.com",
  • "phone": "+14155552671",
  • "ssn": "111-22-3333",
  • "date_of_birth": "2019-08-24T14:15:22Z",
  • "gender": "string",
  • "driver_license_number": "string",
  • "driver_license_state": "string",
  • "previous_driver_license_number": "string",
  • "previous_driver_license_state": "string",
  • "meta": {
    },
  • "addresses": [
    ]
}
Response samples
application/json
{
  • "id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "object": "candidate",
  • "first_name": "string",
  • "middle_name": "string",
  • "no_middle_name": true,
  • "last_name": "string",
  • "email": "joe.clean@example.com",
  • "phone": "+14155552671",
  • "ssn_masked": "string",
  • "date_of_birth": "2019-08-24T14:15:22Z",
  • "gender": "string",
  • "driver_license_number": "string",
  • "driver_license_state": "string",
  • "previous_driver_license_number": "string",
  • "previous_driver_license_state": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "meta": {
    },
  • "addresses": {
    }
}

Delete candidate address.

Permanently delete a candidate's address by the given address id.

SecurityApiKey
Request
path Parameters
address_id
required
string <uuid> (ResourceId) <= 50 characters

The address ID.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
candidate_id
required
string <uuid> (ResourceId) <= 50 characters

The candidate ID.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
Responses
200

Deleted address details.

401

Unauthorized

404

Not Found

422

Unprocessable Entity

delete/candidates/{candidate_id}/addresses/{address_id}
Request samples
Response samples
application/json
{
  • "id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "object": "address",
  • "line1": "string",
  • "line2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "country": "string"
}

Proceed a report

Proceed a candidate for a report.
For more information about Proceed a Candidate.

SecurityApiKey
Request
path Parameters
candidateId
required
string
Request Body schema: application/json
report_id
required
string <UUID>

Unique identifier for the report.

Responses
200

OK

401

Unauthorized

404

Not Found

422

Unprocessable Entity

patch/candidates/{candidateId}/approve_by_report
Request samples
application/json
{
  • "report_id": "string"
}
Response samples
application/json
{
  • "id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "object": "candidate",
  • "first_name": "string",
  • "middle_name": "string",
  • "no_middle_name": true,
  • "last_name": "string",
  • "email": "joe.clean@example.com",
  • "phone": "+14155552671",
  • "ssn_masked": "string",
  • "date_of_birth": "2019-08-24T14:15:22Z",
  • "gender": "string",
  • "driver_license_number": "string",
  • "driver_license_state": "string",
  • "previous_driver_license_number": "string",
  • "previous_driver_license_state": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "meta": {
    },
  • "addresses": {
    }
}

Invitations

Invitations are used to invite candidates to complete a background check with Yardstik. When an invitation is created, the candidate will receive an email asking them to complete the screening package the invitation was created with.

Invitations have their own statuses that can be tracked using the GET operation. To see more details about available statuses, go to the Invitation Status section.

Note: By default, the invitation will expire 7 days after creation. The default invitation expiration settings may be changed in your dashboard in General Settings. Changing invitation expiration settings in your dashboard are only automatically applied to new invitations and will not impact existing invitations.

List Invitations

Retrieve a paginated list of invitations. See Pagination.

SecurityApiKey
Request
query Parameters
order
string

Order listing results in ascending or descending order, when using order_by.
Accepted values are asc or desc. If not passed, defaults to ascending asc.

Examples:
order=desc
order_by
string

Order listing results by a specific property.

Examples:
order_by=created_at
page
integer

The page number to retrieve.

per_page
integer

The maximum number of results per page.

query
string

Filter listing results by a specific property.

Examples:
query[created_at_gteq]=2022-01-01T00:00:00.000Z
Responses
200

List of invitations.

401

Unauthorized

404

Not Found

get/invitations
Request samples
Response samples
application/json
{
  • "object": "list",
  • "meta": {
    },
  • "data": [
    ]
}

Create an invitation.

Creates a new invitation and emails the candidate asking them to complete a report.

SecurityApiKey
Request
Request Body schema: application/json
account_package_id
string <uuid>

Account package ID you want to use for this invitation. Use id from List Account Packages

candidate_id
string <uuid>

ID of the candidate to invite.

Responses
201

Invitation was created successfully.

401

Unauthorized

404

Not Found

422

Unprocessable Entity

post/invitations
Request samples
application/json
{
  • "account_package_id": "263fabf2-df86-40fd-8915-3ea60c091d57",
  • "candidate_id": "2f28f791-f0fd-4155-a356-c24e996beeda"
}
Response samples
application/json
{
  • "id": "string",
  • "status": "string",
  • "external_id": "string",
  • "platform_service_id": "string",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "canceled_at": "2019-08-24T14:15:22Z",
  • "confirmation_code": "string",
  • "account_id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "account_name": "string",
  • "logo": "string",
  • "report_urls": [ ],
  • "styles": {
    },
  • "candidate": {
    },
  • "account": {
    },
  • "meta": {
    },
  • "report": {
    }
}

Get an invitation.

Retrieve an invitation with the given ID.

SecurityApiKey
Request
path Parameters
invitation_id
required
string <uuid> (ResourceId) <= 50 characters

The invitation ID.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
Responses
200

Invitation details.

401

Unauthorized

404

Not Found

get/invitations/{invitation_id}
Request samples
Response samples
application/json
{
  • "id": "string",
  • "status": "string",
  • "external_id": "string",
  • "platform_service_id": "string",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "canceled_at": "2019-08-24T14:15:22Z",
  • "confirmation_code": "string",
  • "account_id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "account_name": "string",
  • "logo": "string",
  • "report_urls": [ ],
  • "styles": {
    },
  • "candidate": {
    },
  • "account": {
    },
  • "meta": {
    },
  • "report": {
    }
}

Delete an invitation.

Permanently delete an invitation with the given ID.

SecurityApiKey
Request
path Parameters
invitation_id
required
string <uuid> (ResourceId) <= 50 characters

The invitation ID.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
Responses
204

No Content.

401

Unauthorized

404

Not Found

422

Unprocessable Entity

delete/invitations/{invitation_id}
Request samples
Response samples
application/json
{
  • "errors": [
    ]
}

Cancel an invitation.

Cancel an invitation with the given ID..

SecurityApiKey
Request
path Parameters
invitation_id
required
string <uuid> (ResourceId) <= 50 characters

The invitation ID.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
Responses
200

Invitation successfully canceled.

401

Unauthorized

404

Not Found

422

Unprocessable Entity

patch/invitations/{invitation_id}/cancel
Request samples
Response samples
application/json
{
  • "id": "string",
  • "status": "string",
  • "external_id": "string",
  • "platform_service_id": "string",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "canceled_at": "2019-08-24T14:15:22Z",
  • "confirmation_code": "string",
  • "account_id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "account_name": "string",
  • "logo": "string",
  • "report_urls": [ ],
  • "styles": {
    },
  • "candidate": {
    },
  • "account": {
    },
  • "meta": {
    },
  • "report": {
    }
}

Refresh an invitation.

Refresh an invitation with the given invitation_id.
Minimum expires_at date must be 24 hours in the future. There is no maximum.
Can only refresh when the invitation is in expired or canceled status.

SecurityApiKey
Request
path Parameters
invitation_id
required
string <uuid> (ResourceId) <= 50 characters

The invitation ID.

Example: 4f6cf35x-2c4y-483z-a0a9-158621f77a21
Request Body schema: application/json
expires_at
string <date-time>

The date when the invitation should expire. If this is not provided, the expiration date will be calculated based off the account notification settings.

Responses
200

Invitation successfully refreshed.

401

Unauthorized

404

Not Found

422

Unprocessable Entity

patch/invitations/{invitation_id}/refresh
Request samples
application/json
{
  • "expires_at": "2019-08-24T14:15:22Z"
}
Response samples
application/json
{
  • "id": "string",
  • "status": "string",
  • "external_id": "string",
  • "platform_service_id": "string",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "canceled_at": "2019-08-24T14:15:22Z",
  • "confirmation_code": "string",
  • "account_id": "4f6cf35x-2c4y-483z-a0a9-158621f77a21",
  • "account_name": "string",
  • "logo": "string",
  • "report_urls": [ ],
  • "styles": {
    },
  • "candidate": {
    },
  • "account": {
    },
  • "meta": {
    },
  • "report": {
    }
}

Reports

Reports contain the results of all background screens, searches, and verifications defined in the account package that was selected while creating the report.

See Getting Started.

List reports

Retrieve a paginated list of reports. See Pagination.

SecurityApiKey
Request
query Parameters
order
string

Order listing results in ascending or descending order, when using order_by.
Accepted values are asc or desc. If not passed, defaults to ascending asc.

Examples:
order=desc
order_by
string

Order listing results by a specific property.

Examples:
order_by=created_at
page
integer

The page number to retrieve.

per_page
integer

The maximum number of results per page.

query
string

Filter listing results by a specific property.

Examples:
query[created_at_gteq]=2022-01-01T00:00:00.000Z
Responses
200

List of reports.

401

Unauthorized

404

Unauthorized

get/reports
Request samples
Response samples
application/json
{
  • "object": "list",
  • "meta": {
    },
  • "data": [
    ]
}

Create a report

Create a new report. The report will be generated based on the candidate ID provided.
See Create Candidate for required attributes. The account packages available will be configured during onboarding by Yardstik.
Each account package will be configured with a set of screenings and configurations that determine the report flow and candidate experience.

To see available packages use List Account Packages.

SecurityApiKey
Request
Request Body schema: application/json
account_package_id
required
string <UUID>

The account package ID for the package you want use to create a report. Use id from List Account Packages.

candidate_id
required
string <UUID>

Unique identifier for the candidate.

reference_id
string

A reference ID that can be used for your application.

Responses
201

Created

401

Unauthorized

422

Unprocessable Entity

post/reports
Request samples
application/json
{
  • "candidate_id": "string",
  • "account_package_id": "string",
  • "reference_id": "string"
}
Response samples
application/json
{
  • "id": "string",
  • "reference_id": "string",
  • "candidate_id": "string",
  • "status": "string",
  • "response_status": "string",
  • "adjudication": "string",
  • "submitted_at": "string",
  • "completed_at": "string",
  • "created_at": "string",
  • "decision": "string",
  • "usage_amount": 0,
  • "process_sequentially": true,
  • "permissible_purpose": "string",
  • "created_by": "string",
  • "candidate": {
    },
  • "account_id": "string",
  • "account_name": "string",
  • "report_url": "string",
  • "adverse_action_id": "string",
  • "report_screenings": [
    ],
  • "elapsed_timing": "string",
  • "package_name": "string",
  • "comments": [ ],
  • "meta": {
    },
  • "adverse_action_settings": {
    }
}

Get a report

Get a report with the given ID.

SecurityApiKey
Request
path Parameters
reportId
required
string
Responses
200

OK

401

Unauthorized

404

Not Found

get/reports/{reportId}
Request samples
Response samples
application/json
{
  • "id": "string",
  • "reference_id": "string",
  • "candidate_id": "string",
  • "status": "string",
  • "response_status": "string",
  • "adjudication": "string",
  • "submitted_at": "string",
  • "completed_at": "string",
  • "created_at": "string",
  • "decision": "string",
  • "usage_amount": 0,
  • "process_sequentially": true,
  • "permissible_purpose": "string",
  • "created_by": "string",
  • "candidate": {
    },
  • "account_id": "string",
  • "account_name": "string",
  • "report_url": "string",
  • "adverse_action_id": "string",
  • "report_screenings": [
    ],
  • "elapsed_timing": "string",
  • "package_name": "string",
  • "comments": [ ],
  • "meta": {
    },
  • "adverse_action_settings": {
    }
}

Adverse Actions

Actions taken upon a report due to findings that may disqualify the candidate for employment.

See Adverse Action Process.

Create an Adverse Action

Create an Adverse Action on a report with the given ID.

During the creation of the Adverse Action, in the violations parameter the only required information is the description

The parameter violations may be required in some scenarios.
Check the Adverse Action Violations Section for details when this parameter is required or not.

For more information about Adverse Action.

SecurityApiKey
Request
path Parameters
reportId
required
string
Request Body schema: application/json
Array of objects
Responses
200

OK

401

Unauthorized

404

Not Found

422

Unprocessable Entity

post/reports/{reportId}/adverse_actions
Request samples
application/json
{
  • "violations": [
    ]
}
Response samples
application/json
{
  • "id": "string",
  • "status": "string",
  • "title": "string",
  • "text": "string",
  • "expires_at": "string",
  • "created_at": "string",
  • "updated_at": "string",
  • "violations": [
    ],
  • "comments": [
    ],
  • "applicant_first_name": "string",
  • "account_name": "string",
  • "logo": "string",
  • "styles": { }
}

Cancel an Adverse Action

Cancel an Adverse Action on a report with the given ID.
For more information about Adverse Action

SecurityApiKey
Request
path Parameters
adverse_action_id
required
string
Responses
200

OK

401

Unauthorized

404

Not Found

422

Unprocessable Entity

patch/adverse_actions/{adverse_action_id}/cancel
Request samples
Response samples
application/json
{
  • "id": "string",
  • "status": "string",
  • "title": "string",
  • "text": "string",
  • "expires_at": "string",
  • "created_at": "string",
  • "updated_at": "string",
  • "violations": [
    ],
  • "comments": [
    ],
  • "applicant_first_name": "string",
  • "account_name": "string",
  • "logo": "string",
  • "styles": { }
}

Webhooks

Webhooks are used to connect Yardstik with other applications, and can be configured to notify users of various events.

See Getting Started.

List all webhooks

Retrieve a list of webhooks for the given account ID.

SecurityApiKey
Request
query Parameters
order
string

Order listing results in ascending or descending order, when using order_by.
Accepted values are asc or desc. If not passed, defaults to ascending asc.

Examples:
order=desc
order_by
string

Order listing results by a specific property.

Examples:
order_by=created_at
page
integer

The page number to retrieve.

per_page
integer

The maximum number of results per page.

query
string

Filter listing results by a specific property.

Examples:
query[created_at_gteq]=2022-01-01T00:00:00.000Z
Responses
200

OK

400

Bad Request

401

Unauthorized

403

Forbidden

404

Not Found

get/webhooks
Request samples
Response samples
application/json
[
  • {
    }
]

Create a webhook

Create a webhook

SecurityApiKey
Request
Request Body schema: application/json
url
string
webhook_type_id
string
Responses
201

Created

401

Unauthorized

403

Forbidden

404

Not Found

422

Unprocessable Entity

post/webhooks
Request samples
application/json
{}
Response samples
<