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.
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:
- Clone the sample app repository:
git clone https://github.com/salsa-payroll/Example-Frontend-App-Integration.git
. - Run
npm install
. - Run
npm start
. - 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.
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:
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 business name, country, address, and banking details. This entity represents a business that is employing and paying Workers.
curl --request POST \
--url https://api.sandbox.salsa.dev/api/rest/v1/paystream/employers \
--header 'Accept: application/json' \
--header 'authorization: Bearer ${ADD_TOKEN}' \
--header 'content-type: application/json' \
--data '
{
"data": [
{
"type": "PaystreamEmployerUpsertInput",
"businessInfo": {
"country": "USA",
"businessName": "Shack 22",
"employerType": "BUSINESS"
},
"addresses": [
{
"name": "Main Address",
"addressLine1": "701 3rd St",
"addressLine2": "Unit 100",
"city": "San Francisco",
"state": "CA",
"postalCode": "94107",
"countryISO": "USA",
"isWorkLocation": true,
"isDefaultWorkLocation": true
}
],
"bankAccounts": [
{
"displayName": "Default",
"routingNumber": "121000358",
"accountNumber": "123456789",
"setAsEmployerDefaultBankAccount": true,
"accountType": "CHECKING",
"paymentAuthorization": {
"acceptedAt": "2024-01-01T01:00:00Z"
},
"verification": {
"organizationVerifiedAt": "2024-01-01T01:00:00Z"
}
}
]
}
]
}'
Example response
{
"data": [
{
"id": "er_353b22d0-5d4b-4416-832e-f408de9e6d33",
"externalId": null,
"addresses": [
{
"id": "eradr_c64cc3a8-1ab0-4d60-9b54-b095cb41bac2",
"externalId": null
}
],
"bankAccounts": [
{
"id": "erbankacc_911a381f-aaf8-42fb-ae84-2b8839a88b99",
"externalId": null
}
],
"termsOfService": null,
"minimumProjectedStartDate": null
}
]
}
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 --request POST \
--url https://api.sandbox.salsa.dev/api/rest/v1/paystream/workers \
--header 'Accept: application/json' \
--header 'authorization: Bearer ${ADD_TOKEN}' \
--header 'content-type: application/json' \
--data '
{
"data": [
{
"type": "PaystreamWorkerUpsertInput",
"contract": {
"classification": "EMPLOYEE",
"hireDate": "2001-01-10"
},
"displayName": "Ruby Brown",
"employerId": "${EMPLOYER_ID}",
"firstName": "Ruby",
"lastName": "Brown",
"personalInfo": {
"email": " [email protected]",
"birthDate": "1989-01-07"
}
}
]
}
'
Example response
{
"data": [
{
"workerId": "wr_d4779475-da76-45c9-86e1-6f1f75d9ac1e",
"externalId": null,
"workerContract": {
"id": "wrctr_f27d9159-edb7-431a-8264-159c41c71385"
},
"bankAccount": null,
"bankAccounts": null
}
]
}
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:
Updated about 2 months ago