Ruby SDK for utilizing the Crystal Connect API. Compute with personality in mind!
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Crystal Ruby SDK

CircleCI Gem Version

This gem provides access to Crystal, the world's largest and most accurate personality database!

API Summary


Want to use our raw API?

Find the docs here:

Want to learn more about us?

Visit our website:

Need an Organization Access Token?

Get in touch with us at


Here's how to install it:

$ gem install crystal_sdk

Here's how you use it:

Synchronous Flow (Recommended)


require 'crystal_sdk'

# Set your Organization Access Token
CrystalSDK.key = "OrgToken"

# Fetch the profile
  profile ={
    first_name: "Drew",
    last_name: "D'Agostino",
    email: "",
    company_name: "Crystal",
    location: "Nashville, TN",
    text_sample: "I, Drew, the founder of Crystal, think that ...",
    text_type: "various"

  print "Profile found!"
  print "First Name: #{}"
  print "Last Name: #{}"
  print "Predicted DISC Type: #{}"
  print "Prediction Confidence: #{}"
  print "DISC Image: #{}"

  print "Personality Overview: #{profile.recommendations.overview}"
  print "Personality Qualities: #{profile.recommendations.qualities}"

  print "Likely motivations: #{profile.recommendations.motivations}"
  print "Likely behaviors: #{profile.recommendations.behavior}"

  print "Tips on emailing: #{profile.recommendations.emailing}"
  print "Tips on communication: #{profile.recommendations.communication}"
  print "Tips on building trust: #{profile.recommendations.building_trust}"
  print "Tips on selling: #{profile.recommendations.selling}"
  print "Tips on working together: #{profile.recommendations.working_together}"

rescue CrystalSDK::Profile::NotFoundError
  print "No profile was found"

rescue CrystalSDK::Profile::NotFoundYetError => e
  print "Profile search exceeded time limit: #{}"

rescue CrystalSDK::Profile::RateLimitHitError
  print "The organization's API rate limit was hit"

rescue CrystalSDK::Profile::NotAuthedError => e
  print "Org token was invalid: #{e.token}"

rescue StandardError => e
  print "Unexpected error occurred: #{e}"


Email Samples

  request_id = '4969f4c3-6d5e-42e1-bf73-342fe8c8a3f1'
  email_samples = CrystalSDK::EmailSample.all(request_id)
  email_samples.each do |sample|
    print "label: #{sample[:label]}"
    print "description: #{sample[:description]}"
    print "text: #{sample[:text]}"

Asynchronous Flow (For bulk analysis)

When requesting large amounts of profiles, or when wanting to have more fine-grained control over performance, we recommend using our asynchronous flow. It allows us to process your requests in parallel and get the information back to you more quickly. There are a couple options for using this capability.

Option 1: Background Processing (Large Lists + Passive Enrichment)

Sometimes, it isn't important to have the profile information immediately. Especially when dealing with larger jobs or passive data enrichment. In that case, we allow you to save the Request ID and pull information from the request at a later time via this ID.

query = { first_name: "Drew", ... }

# Send the request to Crystal
profile_request = CrystalSDK::Profile::Request.from_search(query)

# Pull out the Profile Request ID (string)
profile_request_id =

# Save the Request ID somewhere (DB, Queue, Hard Drive..)

# Later, pull up the Request ID and pull information about it
saved_req =

if saved_req.did_finish? && saved_req.did_find_profile?
  profile = CrystalSDK::Profile.from_request(saved_req)

We try and store your request for a few days after the request has been started. Your Request ID should work when you try to pull information from it for at least that period of time!

Option 2: Polling (Small Lists + Realtime Enrichment)

The option we use internally in the SDK, is to poll for request information periodically until a set timeout has been reached:


# Start the request
query = { first_name: "Drew", ... }
profile_request = CrystalSDK::Profile::Request.from_search(query)

# Poll server until request finishes
MAX_RETRIES.times do

  # If the request hasn't finished, wait and loop again
  unless profile_request.did_finish?

  # Get profile information
  if profile_request.did_find_profile?
    profile = CrystalSDK::Profile.from_request(profile_request)


# Use the profile if it was found

Polling can be extended to poll for multiple profiles. It gives the efficiency of our parallel processing, while writing code that behaves synchronously.

This option is great if you want information as fast as possible while keeping open network connections and code complexity to a minimum. It is especially useful if you are requesting multiple profiles and can process the profiles one at a time, as each individual profile comes in (as opposed to waiting for all of them to come in before processing anything).


  • Clone the repository:

    git clone

  • Run rspec tests:


  • Open up an IRB console with the gem loaded to play around with it:

    rake console

  • Make a code change

  • Check that the tests still pass

  • Make a pull request!

We will review the Pull Request to make sure that it does not break the external specification of the gem and that it fits with the overall mission of the SDK!

We also encourage people to build further libraries that utilize our SDK and extend the use of the Connect API!