Build a Payroll App with Salsa Express

Quickly launch payroll with prebuilt, embeddable UI elements and easy to use APIs.

Salsa Express is the fastest and easiest way to provide payroll services to your customers. With a combination of embeddable UI elements and simple to use APIs, you can launch payroll within days. In this tutorial, you'll build a sample application using Salsa Express, and learn how to:

  • Embed UI elements in an application
  • Set up an Employer and Workers
  • Send compensation data from the application to Salsa

When finished, you'll be able to run payroll and view existing payroll runs, including payment records for each worker.

Employer dashboard embedded in sample app

Employer dashboard embedded in sample app

📘

In a rush?

If you'd like to skip ahead, and run the completed app, the code is available on GitHub.


Step 1: Get an API Token

Before you continue, you need an API token. If you don't have one, get in touch with us.

After signing up, you receive two API keys. One for production and one for your sandbox environment. In this tutorial, you need your Sandbox API Token. To learn more, see Authorization.


Step 2: Download the sample app and create a UI element

UI Elements are added to an application with our browser library, Salsa.js. Elements are rendered in an iframe and customizable for your use case. In this section, you'll download the sample app, create an element, and render it in your app.

Run the sample app

Follow these steps to download and run the sample app:

  1. Clone the sample app repository: git clone https://github.com/salsa-payroll/Example-Frontend-App-Integration.git.
  2. Runnpm install.
  3. Run npm start.
  4. From a browser, navigate to https://localhost:3000/.

You should now see a basic web app with a tab for Payroll. This is where we will embed the Salsa Payroll Run UI.

Sample app starting point

Sample app starting point

Import and initialize Salsa.js

Using your favorite code editor, open App.js, and add the following code:

import { useScript } from './hooks/useScript';

useScript('https://js.salsa.dev/v0');
const [salsa, setSalsa] = useState();
 if(window.Salsa && !salsa) {
    setSalsa(window.Salsa('my-public-client-key', {env: 'sandbox'}));
 }

This does a few things. Salsa.js is loaded from a CDN URL with useScript, then initialized. And since you are running this in the sandbox, the environment is explicitly set to sandbox.

Then, pass salsa into the Router component:

<Router salsa={salsa}/>

Create and mount an element

Open components/Payroll.js, and create a new element instance:

const salsaElement = salsa.elements.create('demo');

Next, create a container for your UI element:

<div id='salsa-container' /> 

Mount your element in the container:

salsa.elements.mount(salsaElement, '#salsa-container');

You should now see the Salsa demo element embedded in your application, and it should look like this:

Demo element embedded successfully

Demo element embedded successfully

Cleanup

When the view that contains the element unmounts, call the destroy function, passing in the element reference to clean it up.

salsa.elements.destroy(salsaElement);

Step 3: Setup an Employer and Workers

Now that you have an element embedded in your application, the next step is to set up Employers and Workers with Salsa's APIs.

The following steps are provided as cURL requests. However, if you prefer, these requests are also available as a Postman collection.

Create an Employer

Create an Employer entity by providing basic information, such as businessName and country. This entity represents a business that is employing and paying Workers.

curl --location --request POST 'https://api.sandbox.salsa.dev/api/rest/v1/employers' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ${YOUR_API_TOKEN}' \
--data-raw '{
  "businessName": "Shack 22",
  "country": "USA"
}'

Example response

{
    "data": {
        "id": "er_b9743f80-0b6c-44f4-b22f-8e3348b1408f",
        "externalId": null,
        "businessName": "Shack 22",
        "country": "USA"
    }
}

Save the Employer's ID (id), you will need it to complete the next steps.

Onboard the Employer

Use the mock-onboard endpoint to generate sample details, and simulate the onboarding of an Employer. Use the id from the previous step, as the employerId.

curl --location --request POST 'https://api.sandbox.salsa.dev/api/rest/v1/employers/${employerId}/mock-onboard' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ${YOUR_API_TOKEN}'

Example response

{
    "data": {
        "employer": "er_b9743f80-0b6c-44f4-b22f-8e3348b1408f",
        "readiness": {
            "workerPayment": {
                "status": "READY"
            }
        }
    }
}

See Employers API Reference for more details about onboarding employers.

Create Workers

Use the employerId from the previous step to create a Worker entity. This entity represents one employee of the business.

curl --location --request POST 'https://api.sandbox.salsa.dev/api/rest/v1/employers/${employerId}/workers' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ${YOUR_API_TOKEN}' \
--data-raw '{
  "firstName": "Olivia",
  "lastName": "Johnson",
  "category": "EMPLOYEE"
}'

Example response

{
    "data": {
        "id": "wr_d4779475-da76-45c9-86e1-6f1f75d9ac1e",
        "displayName": "Olivia Johnson",
        "firstName": "Olivia",
        "lastName": "Johnson",
        "category": "EMPLOYEE"
    }
}

Save this worker's ID (id), you will need it to complete the next steps.

Onboard Workers

Use the following mock-onboard endpoint to generate sample details and mock the onboarding of a Worker.

curl --location --request POST 'https://api.sandbox.salsa.dev/api/rest/v1/employers/${employerId}/workers/mock-onboard' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ${YOUR_API_TOKEN}' \
--data-raw '{
  "workerIds": [
    "${workerId}"
  ]
}'

Example response

{
    "data": [
        {
            "worker": "wr_d4779475-da76-45c9-86e1-6f1f75d9ac1e",
            "readiness": {
                "workerPayment": {
                    "status": "READY"
                }
            }
        }
    ]
}

See Workers API Reference for more details about Workers.


Step 4: Send compensation data to Salsa

Paying Workers is one of the most important tasks when overseeing payroll for a business. In this section, you will learn how to send compensation data from your platform to Salsa, allowing you to pay workers.

Get compensation policies

Compensation policies have been pre-configured in your Salsa account. You use these policies to give workers their compensation, making sure their pay data matches the right pay items. To retrieve your organization's compensation policies, make this request.

curl --location --request GET 'https://api.sandbox.salsa.dev/api/rest/v1/organization-compensation-policies' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ${YOUR_API_TOKEN}'

Example response

{
    "data": [
        {
            "id": "prtnrcomppol_569103c1-b418-4d3f-902a-5ff3327540bc",
            "referenceId": "ref:comp:parisfintech:salarycomp",
            "description": "Salary Comp",
            "calculationMethod": "FIXED_AMOUNT"
        },
        {
            "id": "prtnrcomppol_900157da-cfcd-4083-934b-cb3caa430ee2",
            "referenceId": "ref:comp:parisfintech:hourlycomp",
            "description": "Hourly Comp",
            "calculationMethod": "HOURLY_BASED_AMOUNT"
        }
    ]
}

Save the referenceId, you will need it to complete the next step.

Create compensations for Workers

Now you can create worker compensations (the earnings workers are paid). These are picked up and processed by the payroll engine to create the total Worker payment.

Use the referenceId returned in the previous step to define the Worker Compensation linked to a specific Compensation Policy.

curl --location --request POST 'https://api.sandbox.salsa.dev/api/rest/v1/paystream' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer ${YOUR_API_TOKEN}' \
--data-raw '{
    "data": [
        {
            "type": "PaystreamCompensationItemInput",
            "compensationReferenceId": "${YOUR_FIXED_AMOUNT_COMPENSATION_REFERENCE_ID}",
            "workerId": "${YOUR_WORKER_ID}",
            "startDate": "2023-01-01",
            "endDate": "2023-01-07",
            "amount": "1500"
        },
        {
            "type": "PaystreamCompensationItemInput",
            "compensationReferenceId": "${YOUR_HOURLY_COMPENSATION_REFERENCE_ID}",
            "workerId": "${YOUR_WORKER_ID}",
            "startDate": "2023-01-01",
            "endDate": "2023-01-07",
            "rate": "17.50",
            "hours": "25"
        }
    ]
}'

Example response

{
    "data": [
      {
			      "paystreamItemId": "paystream_4378cf42-f5b5-42da-a66a-c05be76e2131",
            "partnerId": "prtnr_46fcab5e-afc5-4931-a130-350fa2b8a991",
            "createdAt": "2023-02-04T09:04:06.542243",
            "updatedAt": "2023-02-04T09:04:06.555242",
            "status": "IN_PROGRESS",
            "itemInput": {
                "type": "PaystreamCompensationItemInput",
                "compensationReferenceId": "ref:comp:parisfintech:salarycomp",
                "workerId": "wr_d4779475-da76-45c9-86e1-6f1f75d9ac1e",
                "startDate": "2023-01-01",
                "endDate": "2023-01-07",
                "amount": "1500",
                "rate": null,
                "hours": null,
                "frequency": null
            }
      },
      {
            "paystreamItemId": "paystream_32ae0de1-1fbf-4e11-a601-ddb074ea5d81",
            "partnerId": "prtnr_46fcab5e-afc5-4931-a130-350fa2b8a991",
            "createdAt": "2023-02-04T09:04:06.542532",
            "updatedAt": "2023-02-04T09:04:06.555257",
            "status": "IN_PROGRESS",
            "itemInput": {
                "type": "PaystreamCompensationItemInput",
                "compensationReferenceId": "ref:comp:parisfintech:hourlycomp",
                "workerId": "wr_d4779475-da76-45c9-86e1-6f1f75d9ac1e",
                "startDate": "2023-01-01",
                "endDate": "2023-01-07",
                "amount": null,
                "rate": "17.50",
                "hours": "25",
                "frequency": null
            }
        }            
    ],
}

See Compensation policies for more details about worker compensations and compensation policies.


Step 5: Embed the Employer Dashboard element

Create a User Token

To access the Employer, Workers, and Payroll data that you just created, you need to create a User Token with permissions to the data.

Create a User Token with the EMPLOYER_ADMIN:

curl --location 'https://api.sandbox.salsa.dev/api/rest/v1/auth/token' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ${YOUR_API_TOKEN}' \
--data '{
    "role": "EMPLOYER_ADMIN",
    "employerIds": [
        "${SALSA_EMPLOYER_ID}"
    ]
}'

Example response

{
  "data": {
    "token": "${USER_TOKEN}",
    "expiration": "2022-01-01T00:00:00.000+00:00"
  }
}

Load the Employer Dashboard element

Now that you've configured the resources for running payroll, you can embed the Employer Dashboard into your sample app. Open App.js and replace the demo component that you created earlier with the employer-dashboard component. This component requires both the employerId and userToken from previous steps.

const salsaElement = salsa.elements.create('employer-dashboard', {userToken: ${USER_TOKEN}, employerId: ${SALSA_EMPLOYER_ID});

You should see the employer dashboard element embedded in your application, and it should look like this:

Final result, embedded employer dashboard

Final result: embedded employer dashboard