Headless Mode

Learn how to use headless mode in Alloy Embedded

Overview

If your product requirements insist on using your own interface at all times, look no further than Alloy's Embedded Headless Mode. Headless Mode makes it fast and easy to completely own the end to end user interface experience without displaying any Alloy-branded components (i.e. the Alloy Modal, etc).

Getting Started

When using Headless, a typical user flow looks like this:

Let's explore this flow in more detail.

Create a User on Alloy

To begin, you'll need to create a user in Alloy by calling the /users endpoint like below:

curl --request POST \
     --url https://embedded.runalloy.com/users \
     --header 'Authorization: YOUR_BEARER_KEY' \
     --header 'accept: application/json'

Sample Response

{
    "userId": "6634f9aa6adb117b4c47d8ab"
}

This method returns a userId for the user created in Alloy.

List Integrations

To list the integrations you have created in Alloy, use any userId or username you have previously created:

curl --request GET \
     --url https://embedded.runalloy.com/2024-03/integrations?userId=ANY_USER_ID \
     --header 'Authorization: YOUR_BEARER_KEY' \
     --header 'accept: application/json'

Display and Collect Auth Fields

At this point, your user has been created on Alloy and they can see a list of integrations you support on your app. Next, users need to connect/link their third-party app account to your app. To create that connection, we'll need to render a list of fields required by the 3PA (third-party app) the user has selected.

To determine what auth fields to show for the integration a user has selected, make a request to the metadata/credentials endpoint. Replace APP_NAME with the name of the integration the user has selected. e.g Shopify:

curl --request GET \
     --url https://embedded.runalloy.com/2024-03/metadata/credentials/APP_NAME \
     --header 'Authorization: YOUR_BEARER_KEY' \
     --header 'accept: application/json'

The APP_NAME can be found in the response returned by the List integrations endpoint.

Sample Response

Here's a sample response for the Shopify app.

{
    "data": {
        "name": "shopify",
        "icon": "https://cdn.runalloy.com/icons/shopify.png",
        "isOauth": true,
        "properties": [
            {
                "name": "shopSubdomain",
                "displayName": "Shop Subdomain",
                "description": "Enter your store subdomain. If your store domain is example.myshopify.com, the subdomain would be example."
            }
        ]
    }
}

From the response above, we can tell that Shopify uses OAuth for authentication - SeeisOauth: true. We can also see the auth fields to display to end-users in data.properties. The only auth field to display and collect for Shopify is Shop subdomain. An example is shown below:

Once a user has entered the required auth field(s), the next step is to obtain a credentialId for the user.

Getting a CredentialId

A credentialId allows your app to perform actions like reading and writing data on behalf of the end-user once authenticated.

Typically, authentication is handled via the Alloy Modal. But to leverage a truly headless experience, you can ditch the modal completely. This is where our programmatic credential endpoints come in.

First, you'll need to determine if the third-party app uses OAuth or non-OAuth for authentication. See the Display and Collect Auth fields section for more.

Custom OAuth (Optional)

When using Headless mode on Alloy, users will see the Alloy Automation is requesting access to... screen on the third-party app. To display your branding instead of Alloy's, you'll need to obtain approval from the third-party app. Read this tutorial to learn more about using Custom OAuth with Headless mode.

Getting a CredentialId for OAuth Apps

If the 3PA uses OAuth, follow the steps below to obtain a credentialId.

  1. Collect the required Auth fields from the User
  2. Obtain an oauthURL to redirect users to by calling the GET headless/oauthUrl endpoint and passing the values obtained in Step 1 as parameters. This endpoint will always take userId and app as its first two parameters. The other auth fields collected from a user should be appended to the endpoint.
    Here's an example using Shopify and the Shopify shop sub-domain - the only auth field required for a user to connect their Shopify account to your app.
    Sample Request
    curl --request GET \
         --url https://embedded.runalloy.com/2024-03/headless/oauthUrl?userId=YOUR_USER_ID&app=shopify&shopSubdomain=YOUR_SHOPIFY_SHOP_SUBDOMAIN \
         --header 'Authorization: YOUR_BEARER_KEY' \
         --header 'accept: application/json'
    

Sample Response

{
    "data": {
        "oauthUrl": "https://api.runalloy.com/api/strategy/shopify/authorize?userId=YOUR_USER_ID&shopSubdomain=YOUR_SHOPIFY_SHOP_SUBDOMAIN"
    }
}
  1. Redirect the user to the 3PA using theoauthURL obtained in Step 2. This will allow them to grant permissions to your app using OAuth.
  2. Once the user has granted permission, a credentialId is created for the user in Alloy. You'll use this credentialId to make future requests for the selected 3PA integration on behalf of the user.

To see a list of credentialId created for a user, make a request to the List User Credentials endpoint. An example request is shown below:

curl --request GET \
     --url https://embedded.runalloy.com/2024-03/users/USER_ID/credentials \
     --header 'Authorization: bearer YOUR_API_KEY' \
     --header 'accept: application/json'

Getting a CredentialId for non-OAuth Apps

To create a non-OAuth credential, as in the case of NetSuite, use the POST Create API Key Credential endpoint as seen below:

Sample Request

curl --request POST \
     --url https://embedded.runalloy.com/2024-03/headless/credentials \
   	 --header 'Content-Type: application/json' \
   	 --header 'Authorization: Bearer YOUR_API_KEY' \
   	 --data {
  "userId": "YOUR_USER_ID",
  "credential": {
    "type": "netsuite",
    "data": {
      "realm": "123",
      "consumerKey": "4567",
      "consumerSecret": "6789",
      "tokenId": "0000",
      "tokenSecret": "11111"
    }
  }
}

Remember to replace realm, consumerKey, consumerSecret, tokenId and tokenSecret with values from the user input.

Sample Response

This endpoint returns a credentialId as seen below.

{
    "success": true,
    "credentialId": "65b6fd48e4142dd86c387f5e"
}

Start Installation

At this point, we can create an installation for the user. An installation creates an instance of a connection between your app - Alloy - and a third-party app the user has connected with.

To create an installation, make a request to the POST headless/startinstallation endpoint, like below:

curl --request POST \
     --url https://embedded.runalloy.com/2024-03/headless/startinstallation \
     --header 'Authorization: bearer YOUR_API_KEY' \
     --header 'accept: application/json'
     --data {
  "userId": "YOUR_USER_ID",
  "credentialId": "YOUR_CREDENTIAL_ID",
  "integrationId": "YOUR_INTEGRATION_ID"
}

The POST headless/startinstallation endpoint returns an installationId. You'll need to store this for use in Completing the installation.

How to find your IntegrationID

To obtain an integrationId for use in creating an installation, navigate to Alloy > Integrations > SELECT INTEGRATION (e.g. Netsuite). In the address bar of your browser, you would see a URL like ..../integrations/661e92e38eb4d42f032be2d0. Copy the string starting with 66. This piece of string is your integrationId for that integration.

User-defined Data Mappings

Skip to Completing the installation if you do not require any user-defined data mappings.

Some integrations may require end users to map values to the 3PA as seen in this article.

Let's assume your app allows end-users to send a message to a Slack channel once they connect their Slack account to your app. End-users can provide the specific channel and the messages they want to send by checking the Configurable by user checkbox as seen below.

Typically, the end user will provide their own data mappings for the Channel and Message within the Alloy Modal. However, if you want a truly headless experience, you'll need to leverage the POST headless/startInstallation endpoint.

Sample Request

This endpoint takes a userId, an array of credentialIds, and the integrationId of the integration to render headlessly.

curl --location 'https://embedded.runalloy.com/2024-03/headless/startInstallation' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data '{
    "userId":"YOUR_USER_ID",
    "credentialIds":["YOUR_CREDENTIAL_ID"],
    "integrationId":"YOUR_INTEGRATION_ID"
}'

Sample Response

This endpoint creates an installation which can be referenced by its installationId. The fields array returns the relevant fields you'll want to display to your end user along with the associated data type.

{
    "data": [
        {
            "workflowId": "65b7005ae9761102a64ddd3b",
            "app": "netsuite",
            "blockId": "3a8a8e50-f0e5-488b-9b7b-53656e93d392",
            "fields": [
                {
                    "name": "customerEmail",
                    "displayName": "Customer's Email",
                    "type": "string",
                    "required": true
                }
            ]
        }
    ],
    "installationId": "65b701c2f5ba66db3bc53a68"
}

Completing the Installation

Now that you've created the installation and used the POST headless/startInstallation endpoint to return the metadata needed for your end user to map their data, you'll want to actually pass that data back to Alloy Embedded.

To do so, invoke the POST Complete Headless Installation endpoint as seen below. If your integration does not require any input from the user, you may leave the data field empty.

Sample Request

curl --location 'https://embedded.runalloy.com/2024-03/headless/completeInstallation' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--data-raw '{
  "installationId": "YOUR_INSTALLATION_ID",
  "data": [
    {
      "workflowId": "YOUR_WORKFLOW_ID",
      "blockId": "YOUR_BLOCK_ID",
      "fields": [
        { "name": "customerEmail", "value": "[email protected]" }
      ]
    }
  ]
}
'

Sample Response

Assuming you passed in valid information, you will see a success message and associated 200 OK status as seen below.

{
    "message": "Installation completed successfully"
}

You can verify that the integration was installed successfully by navigating to the Alloy Dashboard > Embedded iPaaS > Integrations > YOUR_INTEGRATION > Installations

Wrapping Up

In this article, we took a look at how to use Alloy Embedded's fully headless mode to provide a completely whitelabeled end user experience. Using Headless Mode, your end users will never even know you're using Alloy Embedded to power integrations!