How can we help?

How to Connect Custom Integrations

Noga Tubi
Noga Tubi
  • Updated

Overview

Before starting, we recommend reading the Introduction to Custom Integration article

Kindly remember that custom integrations:

  • Support syncing users, licenses, roles, and last used dates
  • Cannot sync expenses, even if the integrated app contains expense data
  • Work best for onboarding/offboarding/license optimization scenarios

To build your own integration and push user and license data into Torii you will need to follow the below 4 steps process.

Note, steps 3 & 4 require some technical knowledge.

IT - Setup/ Preparation

  • STEP 1 - Get Torii API key
  • STEP 2 - Create a new Custom Integration

Technical - Use the API to upload and sync users

  • STEP 3 - Upload the data to Torii
  • STEP 4 - Sync the data to Torii

STEP 1 - Get Torii API Key

Prerequisite - Torii admin permission is required

  1. Go to Settings >> API Access
  2. Click on Generate API key
  3. In Generate API Key make sure you select the Full access option
  4. Make sure you store the API key somewhere safe because you will not be able to see it again after step 5. If, for some reason, you ever lose your API key, you can always generate a new one.
  5. Click Got it

STEP 2 - Create a new Custom Integration

  1. Go to the Integrations page,
  2. Scroll down and click the ADD CUSTOM INTEGRATION tile
  3. Find the App you want to integrate
  4. Click Add integration
  5. Copy the App account ID and store it somewhere safe
  6. Close the window

STEP 3 - Upload the data to Torii

Prerequisites - Generate a JSON file named ‘users_file.json’ in the working folder and verify it complies with the "File schema"
Click here for Torii's full API documentation

💡 Make sure you replace the placeholders in the API calls with your variables, e.g. replace API_KEY with the API key you generated in step 1.

 

There are 2 techniques you can use to upload the data to Torii

  1. For files up to 3MB - use the Upload File (up to 3MB) API or run the following command:
    curl --request POST "https://api.toriihq.com/v1.0/files/upload" \
    --header "Authorization: Bearer API_KEY" \
    --header "Content-Type: multipart/form-data" \
    --form 'type="customIntegrationData"' \
    --form 'file=@"FULL/PATH/TO/FILE"'
  2. For files larger than 3MB, follow the process below:
    1. Create a one-time URL upload link
    2. Upload the file to S3
    3. Update Torii with the upload information
    1. Create a one-time, private URL upload link - use the Get parameters for uploading files API or run the following command:
      curl "https://api.toriihq.com/v1.0/files/url?name=users_file.json&type=application/json" \ 
      --header "Authorization: Bearer API_KEY"
      You should get a response that looks like this:
      {
      "uploadFileParameters": {
      "url": "https://torii-app-test.s3.us-west-2.amazonaws.com/uploads/23/1704790932720/users_file.json?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAWVLDEIRX6X6UEP5I%2F20240109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20240109T090212Z&X-Amz-Expires=300&X-Amz-Signature=09c8a054052a4c069a40f0ada5771742bb3f38ee12a6974e7cfbbef08ad9726c&X-Amz-SignedHeaders=host&x-amz-acl=private&x-id=PutObject",
      "filePath": "1704790932720/users_file.json"
      }
      }
      The url is used in step 2 and the filePath is used in step 3.

      Note

      • These parameters are embedded in the upload file parameters; consider it when

      writing the code.

      • The upload URL is valid for a short period of time, so make sure to upload the file

      before it expires.

    2. Upload the file to S3 - use the url from the response and run the following command:
      curl --request PUT S3_URL --data @'FULL/PATH/TO/FILE' 
      // Example
      curl --data @'/Users/user/Downloads/users_file.json' -X PUT "https://torii-app-test.s3.us-west-2.amazonaws.com/uploads/23/1704790932720/users_file.json?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAWVLDEIRX6X6UEP5I%2F20240109%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20240109T090212Z&X-Amz-Expires=300&X-Amz-Signature=09c8a054052a4c069a40f0ada5771742bb3f38ee12a6974e7cfbbef08ad9726c&X-Amz-SignedHeaders=host&x-amz-acl=private&x-id=PutObject"

      Note

      If you are pasting the URL in your terminal, make sure it doesn’t add any escape characters (e.g. \)



    3. Update Torii with the upload information - use the Store file information in DB API or run the following command:
      curl "https://api.toriihq.com/v1.0/files" \ 
      --header "Authorization: Bearer API_KEY" \
      --header "Content-Type: application/json"
      -data '{"path":"S3_FILE_PATH","type":"customIntegrationData"}'

      You should get a result with the Torii upload ID like in the below example:
      Save the id value for step 4

STEP 4 - Sync the uploaded file to Torii

  1. Use the Sync custom integration API or run the following command:
    curl --request PUT "https://api.toriihq.com/v1.0/services/sync/custom" \
    --header "Authorization: Bearer API_KEY"
    --data '{"idFile":"FILE_ID", "idAppAccount": "APP_ACCOUNT_ID"}'
  2. Replace the API_KEY, FILE_ID from the previous step (Upload ID)
  3. Replace the APP_ACCOUNT_ID you received from Torii in STEP 2 (add custom integration) like in the below example:

mceclip4.png

You should get a response indicating that the operation was successful, like in the below example:

Error Message: in case of an error, a relevant message like "Illegal file structure, Wrong file id, Wrong account", etc. will be displayed.

Last Notes:

  1. The syncs are NOT incremental, meaning that on each sync you must provide all the users you currently have in the systems (and not only new ones for example)
  2. It may take some time for the sync to complete. To confirm a successful sync, Go to Integration window (1) and make sure the hourglass (2) disappeared and a green checkmark (3) is displayed.

Q & A

Q: Can I sync absolutely any app with Torii?
A: Yes, as long as the data is structured according to the Torii file schema.

Q: How often will data be pushed into Torii & Does Torii support date synchronization with custom integrations?
A: You can decide how often you want to push the data into Torii. We recommend pushing the data regularly, so it stays up to date. When data has not been synced for more than 10 days, we show an alert in the UI.

Q: Can I perform workflow actions for a custom app?
A: Yes, through custom action configuration

Q: What happens when disconnecting custom integration?
A: The app account is revoked, and no more syncs are possible. You can always reconnect the same account. Read this article to learn what happens to your data when you disconnect an integration

Q: How do I delete and update users?
A: Each time a new file is pushed, the old data is overwritten. If users were removed from the file - they would be removed from the app in Torii. If user attributes were updated in the file - they will be updated in Torii.


File schema

The file should include the following information. Note that fields must have the exact field name as shown in the following table:

Field Name

Description

Type

Required

users

Users using the application

User[]

(see user object below)

Yes

licenses

Licenses used in your org

License[]

(see license object below)

No


User

Field Name

Description

Type & Options

Required

Id

Unique identifier of a user in the application

String

No

email

The user's unique email

String

Yes

firstName

The user's first name

String

No

lastName

The user's last name

String

No

status

The status of the user in Torii. Only active users are displayed as users of the application

Enum (active/deleted)

Default: active

No

externalStatus

The status of the user as it appears on the application’s site

String

No

roles

Array of roles the user has in the application

String[]

No

lastUsedDate

The last date the user used the application

Date

ISO 8601 (YYYY-MM-DD)

No


License

Field Name

Description

Type & Options

Required

name

Unique name

String

Yes

unassignedAmount

Number of licenses that are not assigned to users

Number

No

users

Users under this license

licenseUser[]

(see licenseUser object below)

No

pricePerUser

How much does it cost per user

Number
Units: cents
(e.g. $35.2 should be sent as 3520)

No


License User

Field Name

Description

Type & Options

Required

email

User's email

String

Yes

licenseStatus

License status.

If not provided, will be defined by user status

Enum

(active/inactive/deleted)

No

lastUsedDate

Last date user used the license

Date

ISO 8601 (YYYY-MM-DD)

No

Return up

Was this article helpful?

1 out of 1 found this helpful

Have more questions? Submit a request