API Overview

To get started, register a free CrowdTrust Application by clicking the sign up button.

Our API can only be accessed with a public API key and a secret key which are generated by creating Bad Actor User via the API.

Please submit all questions via the Feedback tab.

Developer Requirements

The CrowdTrust Developer Guidelines will change as the CrowdTrust API matures. Please check this page to stay compliant.

Conduct

  • Responsibly manage and protect user data
  • Never abuse privacy

Expectations

  • Unless expressed otherwise, data retrieved via the CrowdTrust API may not be cached or saved for an unreasonable length of time.
  • You must explain in clear, easy to understand terms what you intend to do with any CrowdTrust service (ex. Bad Actor Check).
  • Should you choose to leverage the CrowdTrust API in your third party application you must clearly note in your user policy that this application is not directly supported by CrowdTrust Inc. CrowdTrust Inc makes no claims about this application. This application is not endorsed or certified by CrowdTrust Inc.
  • You must not share your API Key or secret key to any third party for any reason.
  • Your application and any consumers thereof, may not misrepresent, falsify or change any data produced or retrieved from the CrowdTrust API.
  • You may not collect or distribute user information on behalf of CrowdTrust.

Rights

  • CrowdTrust makes no claims to ownership of new software developed by third party developers
  • CrowdTrust claims no rights to software development done by third parties.

Application Approval and Review

  • CrowdTrust may request a full review of the application.
  • All CrowdTrust applications may be subject to future changes. Applications may not be grandfathered in.
  • Your application may not allow parties to engage in illegal activites

Guarantees

  • CrowdTrust makes no guarantees regarding API uptime or availability and is not responsible for losses or damages incurred through the utilization or abuse of the CrowdTrust API.

Liabilities

  • Unless expressed otherwise, CrowdTrust provides no insurance for your application which covers your entity.
  • Liabilities that result in a malfunction of your application are the responsibility of your company, service or application.
  • CrowdTrust claims no liability for the stability of third party applications.

Terms

  • This agreement begins as of the first date you register with CrowdTrust, Inc. CrowdTrust reserves the right to make changes to the Developer Guidelines at any time. By using the CrowdTrust API or any Web UI components tied to the CrowdTrust API, you agree to these terms.
  • For additional information please consult our Terms of Service on the sign up page.
  • All questions should be submitted via the feedback form or you may email admin@crowdtrust.com

Step 1 - API Keys

  • CrowdTrust will typically provide access within 24 hours or less.

Register Your Application

  • Register an application. A confirmation email will be sent to the submitted email address. A 'terms of service' token will be generated. The token must be included in the initial request to create a Bad Actor User account.

Create Your Accounts (LIVE + TEST)

  • To create a pair of Bad Actor User accounts (Both a LIVE account & a TEST account) please POST a request to the following end point:
  • https://www.crowdtrust.com/bacapi/account
  • Ex. (Assuming cURL is installed)
    curl -v -H "Content-Type: application/json" -X POST --data "@bacUserRequest.json" https://www.crowdtrust.com/bacapi/account

Create Account Parameters

    Note: All fields are required unless marked asOptional. Fields marked asRecommended are recommended for applications but not required to make the process work.
    Field Description
    email The email address for communication, notifications, and account information
    tosToken The 'terms of service' token sent via email after registering an application
    organizationName The name of the organization this account is for
    webhookRecommended An end point hosted by the client that handles updates and notifications from the CrowdTrust system via the POST method. A webhook is generally submitted during account creation and every Bad Actor Target will inherit the url.
    firstNameOptional The first name of the account holder
    lastNameOptional The last name of the account holder
    phoneOptional The contact phone number of the account holder
  • Should you choose to send a webhook URL, the url MUST be over SSL.

Example Request

    {
      "firstName": "John",
      "lastName": "Smith",
      "email": "testEmail@crowdtrust.com",
      "webhook": "https://www.testPlatform.com/service/webhook",
      "phone": "240-333-5555",
      "organizationName": "TestPlatform Inc.",
      "tosToken": "8a7gh3k4"
    }
    						

Getting Your API Keys

  • An email containing your api key + secret key will be sent upon success. The email will contain a pair of keys for both your LIVE account and TEST account.
  • A successful response will also return the api key + secret key for your LIVE & TEST accounts:
  • {
      "apiKey": "myApiKey",
      "secretKey": "va35va34av3a23..",
      "testApiKey": "myTestApiKey",
      "testSecretKey": "3ava635ava343av..."
    }
    						

Using Your TEST Account

  • You may utilize the CrowdTrust TEST account without incurring any charges. TEST billing information is set upon user creation for all TEST accounts.
  • All TEST endpoint URLs will be in the same format as LIVE URLs, except their path will start with 'bacapi/test/' instead of 'bacapi/'
  • All requests, parameters, and validation will be exactly the same for both TEST and LIVE. So if your are able to get things working with your TEST account, you only need to do the following to run against LIVE:
    1. Change the request URL paths to be '/bacapi/' instead of '/bacapi/test/'
    2. Send your LIVE api key in your request headers instead of the TEST api key
    3. Use your LIVE secret key during authorization instead of the TEST api key
    4. Update the Billing Information for your LIVE account
  • TEST billing information will be created by default for TEST accounts, so you can start using your TEST credentials immediately after creating your account. (LIVE accounts require valid billing information to be submitted before any Bad Actor checks can be created)

Step 2 - Authentication

Using HMAC Authentication

  • CrowdTrust's Bad Actor API is protected via our implementation of HMAC. In order to determine who is making requests to our API, we use HMAC on every incoming request (including those to the TEST endpoints).
  • In order to make any call to the API after you've created your account, you will need to generate a unique signature for each request. In order to do that you will need:
    1. Your API Key from account creation. This is used like a username so we can know who you are.
    2. Your Secret Key form account creation. You will use this to to create a hash of your signature.
    3. A method of generating an MD5 Hash of your entire request.
    4. A method of generating a HMAC-SHA256 Hash using your secret key.
    5. A method of Base64-encoding parameters.
  • The main idea with HMAC is that for each request, you take the important parts of the request, concatenate them into a single String, and then generate a HMAC-SHA256 hash of that String (let's call this your authorization signature). You pass this authorization signature along with the rest of your request via the Authorization Header.
  • On our end, we will use your API Key to look up your Secret Key. We will then inspect the request and build the SAME signature using the important parts of the request and your Secret Key.
  • If the authorization signature generated matches the authorization signature you sent, then your request will be authenticated successfully!
  • By doing this simple process on each request, we get all of these great benefits:
    • We can verify that you are who you say you are. The API Key acts like a username, and the Secret Key acts like a password.
    • You are never passing your Secret Key in ANY request. As long as you protect your secret key, we can authenticate you and you will never have to worry about passing it to us.
    • Each request is completely atomic on its own, which is a critical aspect of RESTful design. You don't need to hit another authentication endpoint to get authentication tokens or cookies, you can just hit our endpoints and never need to maintain data between them.
    • No one can reuse or hijack your authorization signature and modify the contents of the request. Since the authorization signature contains the important parts of the request, if anything in the request is modified the authorization signature will no longer match.
    • We can prevent replay attacks by including a timestamp in the authorization signature.

Required Header Fields

  • For our HMAC Authentication, these are the HTTP Headers that we will use to validate your authorization signature (ALL FIELDS ARE REQUIRED, though they may be empty in some cases)
  • HTTP Header Description
    Authorization
    {APIKEY}:{HMAC-Signature}
    Your authorization signature which is made up your API Key and the HMAC signature that you generated using your request params.
    Content-MD5 An MD5 hash of the entire body of this request (normally the MD5-hash of the request JSON String). The String representation of the JSON content should be converted to its byte representation, hashed using the MD5 algorithm and then Base64 encoded. Call toString on the resulting base64 encoded hash and use the result in your signature.
    NOTE: For GET requests, this will be an empty-string, NOT the MD5 Hash of an Empty String.
    Content-Type The Content-Type of this request. For any requests to the CrowdTrust BACAPI that pass data, this will be
    application/json
    NOTE: When SIGNING GET requests, this should be an empty string. When SENDING the actual request this header should be empty or null (NOT an empty string).
    Date A timestamp representing the date and time this request was created. This will be used to limit how long this request is valid for. An example of the date-time format as specified by RFC 1123:
    Sun, 06 Nov 1994 08:49:37 GMT
    The endpoint will also accept:
    Sunday, 06-Nov-94 08:49:37 GMT
    and
    Sun Nov  6 08:49:37 1994
    NOTE: This should always be passed in respect to UTC (GMT) Time.

Authorization Parameters

  • For our HMAC Authentication, these are the Parameters used to generate your authorization signature string. (ALL FIELDS ARE REQUIRED, though they may be empty in some cases)
  • Parameter Description
    HTTP-Verb The HTTP-Verb of the request (ie GET, POST, PUT, DELETE)
    MD5-Content An MD5 Hash of the entire content of this request. This value should also be passed as the 'Content-MD5' header.
    Content-Type The Content-Type of this request. This value should also be passed as the 'Content-Type' header.
    Date A timestamp representing the date and time this request was created. This value should also be passed as the 'Date' header.
    NOTE: This should always be passed in respect to UTC (GMT) Time.
    Path The Path part of the URL of this request (ie 'bacapi/checks')

Building Authorization Header

  • The Authorization header is made of up to two parts concatenated as a string separated by a colon ":"
    • API Key
    • Signature
  • To generate the signature, we need to concatenate the Authorization Parameters together as a string. THE ORDER OF THE PARAMETERS MATTERS HERE, SO ENSURE THE STRING IS CONSTRUCTED IN THIS EXACT ORDER:
    String toSign = {HTTP-VERB} + "\n" +
    {Content-MD5} + "\n" +
    {Content-Type} + "\n" +
    {Date} + "\n" +
    {Path}
  • Once the 'toSign' string has been created, you should use your Secret Key to generate a HMAC-SHA256 hash of the string.
  • You should then Base64 Encode the result, and this becomes your Signature
  • Concatenate your API Key and this signature (separate by a colon) and you now have your full Authorization Header.
  • Here is a Java code sample that constructs a valid Authorization Header:
  • private String createAuthHeader(String httpVerb, String contentMD5, String contentType, String timestamp, String path, String apiKey, String secret) {
    
      // Generate 'toSign' String
      String toSign = createHMACStringToSign(httpVerb, contentMD5, contentType, timestamp, path);
    
      // Build Java SecretKey for signing
      SecretKey secretKey = buildSecretKey(secret);
    
      // Create Base64 Encoded, Hmac-SHA256 Hashed Signature using secret key
      String signature = encodeToBase64HMAC(secretKey, toSign);
    
      String authHeader = apiKey + ":" + signature;
    
      return authHeader;
    }
    
    private String createHMACStringToSign(String httpVerb, String contentMD5, String contentType, String timestamp, String path) {
    
      StringBuilder toSign = new StringBuilder();
      toSign.append(httpVerb).append("\n")
            .append(contentMD5).append("\n")
            .append(contentType).append("\n")
            .append(timestamp).append("\n")
            .append(path);
    
      return toSign.toString();
    }
    
    public SecretKey buildSecretKey(String base64String) {
    
      byte[] encodedKey = Base64.decodeBase64(base64String);
      SecretKey toRet = new SecretKeySpec(encodedKey, 0, encodedKey.length, "HmacSHA256");
    
      return toRet;
    }
    
    public String encodeToBase64HMAC(SecretKey secretKey, String data) {
    
      String toRet = "";
    
      try {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(secretKey);
        byte[] rawHmac = mac.doFinal(data.getBytes());
        toRet = new String(Base64.encodeBase64(rawHmac));
      }
      catch(NoSuchAlgorithmException ex) { }
      catch(InvalidKeyException ex) { }
    
      return toRet;
    }
    							

Sending Request w/ HMAC Authentication

  • Once you've constructed the request you want to pass to the CrowdTrust Bad Actor Check API, use these steps to send the request:
    1. Create your Authorization Header and set it as the 'Authorization' header in the request
    2. Ensure you've set all the other required Headers in your request
    3. Send the request off to your endpoint and let the magic happen!
    Note: Any error while trying to authenticate the request will result in a 403 HTTP Status Code, but there will be no indicator as to what part of the authentication failed. This is done intentionally to ensure the best level of security and not help anyone try to reverse engineer their way into your account.
  • Here is another Java code sample for sending an authenticated request (this uses the 'createAuthHeader' method defined in the Authorization Header code sample):
  • public String sendRequestWithHMAC(String httpVerb, String url, String requestBody, String contentType, String apiKey, String secret) {
    
      String contentMD5 = "";
    
      // GET requests have empty MD5 Hash
      if (StringUtils.equalsIgnoreCase(httpVerb, "POST") || StringUtils.equalsIgnoreCase(httpVerb, "PUT")) {
        contentMD5 = encodeToBase64MD5(requestData);
      }
    
      // Extract the path of the URL
      URL requestUrl = new URL(url);
      String path = requestUrl.getPath();
    
      // Create UTC Timestamp of right now
      TimeZone tz = TimeZone.getTimeZone("UTC");
      Calendar c = Calendar.getInstance(tz);
      String timestamp = DatatypeConverter.printDateTime(c);
    
      String authHeader = createAuthHeader(httpVerb, contentMD5, contentType, timestamp, path, apiKey, secret);
    
      Client client = Client.create();
      WebResource.Builder builder = client.resource(url)
            .header("Date",  timestamp)
            .header("Authorization", authHeader);
    
      if (!StringUtils.isBlank(contentType)) {
        builder = builder.type(contentType);
      }
    
      ClientResponse response = null;
    
      if (StringUtils.equalsIgnoreCase(method, "POST")) {
        response = builder.post(ClientResponse.class, requestData);
      } else if (StringUtils.equalsIgnoreCase(method, "PUT")) {
        response = builder.put(ClientResponse.class, requestData);
      } else if (StringUtils.equalsIgnoreCase(method, "DELETE")) {
        response = builder.delete(ClientResponse.class);
      } else {
        response = builder.get(ClientResponse.class);
      }
    
      return response.getEntity(String.class);
    }
    
    public String encodeToBase64MD5(String contentToEncode)  {
    
      String toRet = "";
    
      try{
        MessageDigest digest = MessageDigest.getInstance("MD5");
        digest.update(contentToEncode.getBytes());
        toRet = new String(Base64.encodeBase64(digest.digest()));
      } catch(NoSuchAlgorithmException ex) { }
    
      return toRet;
    }
    							
  • For more walkthrough and code examples of doing HMAC, these are some great resources:
  • You can pull the current client project from here. The client can be run from the command line via the following commands:
    java -jar client.jar account:create {data.json} {verb} {URL Endpoint} {apiKey} {secretKey}
    java -jar client.jar execute {verb} {URL Endpoint} {apiKey} {secretKey}

Step 3 - Billing (Not Required For TEST)

  • We do not store any credit card information ourselves, we use Stripe to manage any sensitive billing data.
  • In order to begin using your LIVE account to submit Bad Actor Checks, you must submit valid billing information.
  • Users may POST a bad actor request containing billing information at the following end points:
  • LIVE:
    https://www.crowdtrust.com/bacapi/account/billing
    TEST:
    https://www.crowdtrust.com/bacapi/test/account/billing
  • You can also optionally modify your TEST account billing information if you would like to test out these endpoints.

Billing Parameters

    Note: Submitting valid billing information to your LIVE account will initiate charges.
    Parameter Description
    number The card number, as a string without any separators.
    exp_month Two digit number representing the card's expiration month.
    exp_year Two or four digit number representing the card's expiration year.
    cvc Card security code.
    name Cardholder's full name.
    address_line1 Billing Address line 1
    address_line2Optional Billing Address line 2
    address_city Billing City
    address_state Billing State (MM)
    address_zip Billing Zip code
    address_country Billing Country

Example Request

    {
      "number":"4242424242424242",
      "exp_month":6,
      "exp_year":2017,
      "cvc":"667",
      "name":"John Wayne",
      "address_line1":"1 Galaxy Way",
      "address_line2":"Apt 10c",
      "address_city":"brumburg",
      "address_zip":"20850",
      "address_state":"MD",
      "address_country":"US"
    }
    						

Step 4 - Submitting Bad Actor Check

  • CrowdTrust provides a number of convenient methods to help automate the due diligence process. One such method is the Bad Actor Check. This method provides a restful way to process a Bad Actor Check. Users must post the required data to the defined end point to start the process. Due to the complex nature of doing a Bad Actor Check, result times may vary (ranging from momentary results to several days).
  • While we can't rush the due diligence process we can make it easier to stay on top of the process. By sending an email or webhook, the CrowdTrust system can notify users of any errors during the process or when the process has been completed.
  • Users may POST a bad actor request at the following end points:
  • LIVE:
    https://www.crowdtrust.com/bacapi/checks
    TEST:
    https://www.crowdtrust.com/bacapi/test/checks
  • Ex. (Assuming cURL is installed)
    curl -v -H "Content-Type: application/json" -X POST --data "@badActorRequestTarget.json" https://www.crowdtrust.com/bacapi/checks

Bad Actor Check Parameters

    Note: All fields are required unless marked asOptional. Fields marked asRecommended are recommended for applications but not required to make the process work.
    Field Description
    firstName First legal name of applicant
    lastName Last legal name of applicant. Alias must be search via a separate request.
    dateOfBirth yyyy-MM-dd
    ssn In the United States, a Social Security number (SSN) is a nine-digit number issued to U.S. citizens, permanent residents, and temporary (working) residents
    regulationType The regulation type is represented by a single character. The api currently accepts 'A' or 'D'.
    platformName The platform name responsible for registering an applicant.
    workHistoryRecommended A list of companies where the applicant has held a C-Level position or similar. Please submit up to 7 years of work history.
    homeAddressesRecommended A list of addresses where the applicant currently or has lived. Please submit up to 7 years of history.

Example Request

    {
      "firstName": "Jack",
      "lastName": "Smith",
      "ssn": "222-65-9696",
      "dateOfBirth": "2014-07-10",
      "regulationType": "D",
      "platformName" : "Regulation D Platform",
      "workHistory":[  
          {  
             "company":"Berkling & co.",
             "title":"Board Member",
             "startDate":"2009-05-09",
             "endDate":""
          },
          {  
             "company":"Small Finance Guy",
             "title":"CEO",
             "startDate":"2002-08-04",
             "endDate":"2009-05-01"
          },
          {  
             "company":"IJustNeededAJobOutOfSchool Inc.",
             "title":"Associate",
             "startDate":"2000-06-01",
             "endDate":"2002-08-01"
          }
       ],
      "homeAddresses": [
        {
          "address1": "144 Crowded St",
          "address2": "Apt. 9",
          "city": "Brumburg",
          "state": "MD",
          "zip": "20485"
        }
      ]
    }
    						

Example Response

    {
      "searchId": "1253",
      "status": "Complete with Work History",
      "badActorCheckPass": "true",
      "firstName": "John",
      "lastName": "Smith",
      "ssn": "***-**-9696",
      "dateOfBirth": "1986-05-26",
      "regulationType": "D",
      "disqualifyingEventDate":"null",
      "workHistory":[  
          {  
             "company":"Berkling & co.",
             "title":"Board Member",
             "startDate":"2009-05-09",
             "endDate":""
          },
          {  
             "company":"Small Finance Guy",
             "title":"CEO",
             "startDate":"2002-08-04",
             "endDate":"2009-05-01"
          },
          {  
             "company":"IJustNeededAJobOutOfSchool Inc.",
             "title":"Associate",
             "startDate":"2000-06-01",
             "endDate":"2002-08-01"
          }
       ],
      "homeAddresses": [
    	{
          "address1": "144 Crowded St",
          "address2": "Apt. 9",
          "city": "Brumburg",
          "state": "MD",
          "zip": "20485"
        }
      ]
    }
    						
  • An email will be sent out when the Bad Actor Check has completed. Results will automatically be posted to the webhook in the format above.
  • Users may retrieve the status of a bad actor check at any time by executing a GET at the following URI:
  • LIVE:
    https://www.crowdtrust.com/bacapi/checks/{searchId}
    TEST:
    https://www.crowdtrust.com/bacapi/test/checks/{searchId}
  • Users may retrieve a PDF report via a GET at the following URL (restricted to the LIVE environment)
  • LIVE:
    https://www.crowdtrust.com/bacapi/checks/{searchId}/report

Error Handling

  • HTTP Requests which encounter errors will return with a HTTP Status Code representing the error type:
    • 400 - Bad Request (Something about the request was invalid)
    • 401 - Unauthorized (The request failed authentication)
    • 404 - Not Found (The requested data or resource does not exist)
    • 500 - Internal Server Error (An unexpected error, you can try again or notify CrowdTrust of the problem)

Error Fields

  • Error responses will also contain the status code and a message via JSON data in the response body. Some errors will contain additional information via the 'details' property.
  • Example error response body:
  • {
      "status": 404,
      "message": "This check does not exist"
    }
    						
  • Example error response body with details:
  • {
      "status": 400,
      "message": "Invalid Input",
      "details": {
        "field": "email",
        "cause": "The provided email is invalid"
      }
    }