Integrations Framework
💡 Context
In Factorial, we have developed the first version of our integrations framework, allowing Factorial to sync data (employee compensation, expenses…) into external systems (payroll software, ERPs).
This functionality is exposed through our public API, so that external partners and clients can integrate external software more easily and consistently.
✨ Introduction
This framework enables external developers to sync data from Factorial to the different external softwares in an easy and transparent way for the user, providing the best experience to the user. A summary of the flow of how the framework would be:
- Client defines all the data (compensations, expenses) in Factorial
- Client clicks on ‘Sync to [external_software_name]
- Partner receives a webhook notification
- Partner fetches data to sync from Factorial
- Partner syncs it to the external software
- Partner reports the sync result back to Factorial so the client can have visibility of the result of the sync
🔧 Setup integration for the first time
To get started, the partner needs to specify 2 things to Factorial team:
Data Fields
From Factorial, we can send a set of fields when syncing each item to the external software. The partner must specify 2 things: which data they want to receive and which fields are mandatory for their integration:
Compensations
Fields | Format | Do they want to have this data in our response? (Yes/No) | Is it mandatory to sync to the payroll software (Yes/No) |
---|---|---|---|
| Integer | ||
| String | ||
| Integer | ||
| Integer | ||
| Integer
| ||
| String: one of | ||
| yyyy-mm-dd |
Expenses
Fields | Format | Do they want to have this data in our response? (Yes/No) | Is it mandatory to sync to the ERP software (Yes/No) |
---|---|---|---|
expense_id (in Factorial) | Integer | ||
tbd |
Webhook URL
- URLs where Factorial will send the webhook must be provided. One for production and another for the test environment
- This URL will be used for all companies using the integration.
Integration UUI
- Factorial will provide the Partner with an
integration_uuid
That represents your integration across Factorial environments and is the shared integration identifier between both systems. You will need it in the following steps.
🔧 Setup integration for a new client
When a new client starts using the integration for the first time, some configuration may be required on the partner's side.
1. Set up data mappings
Compensations
- The partner can list the Payroll Concepts for a company by calling the following endpoint: Read Compensation Concepts
GET {baseUrl}/api/{version}/resources/compensations/concepts
-
It is important that the partner filters by
- categories:
- earnings_fixed_salary
- earnings_variable
- earnings_benefits_in_kind
- earnings_others
- deductions
- with_active_status: true
- categories:
-
Once the partner has the list of Payroll Concepts, they can ask the client to map them with the payroll concepts codes of their payroll software account.
Expenses
TBD
2. Notify Factorial about the new installation & set up
Once the setup is finished on the partner's side and the integration is ready to be used, it must be enabled in Factorial for that specific client (company) by calling the following endpoint:
Create an Installation FactorialCreates an Installation
POST {baseUrl}/api/{version}/resources/marketplace/installations
{
"integration_uuid": string, // your integration identifier
"company_id": integer
}
🔄 Async Integration Flow
1. Receive Webhook Notification
When a sync is triggered by the user in Factorial, Partners’ webhook will receive a POST
request with the following payload:
{
"sync_run_id": integer,
"integration_uuid": string, // your integration identifier
"company_id": integer,
"capability": string // the type of synchronization (compensation, expenses)
}
Important
- Partners’ endpoint must respond with HTTP
200 OK
to confirm receipt.- The partner should process the sync asynchronously.
- Partner should not return errors in this response — errors must be handled and reported separately in Step 4.
- If a webhook notification fails, Factorial will send an email to the partner and retry the notification up to 5 times within 15 minutes. If all retries fail, the user will be notified that the sync was unsuccessful.
2. Fetch Sync Data
To retrieve the data items to sync, call the following endpoint:
GET {baseUrl}/api/{version}/resources/integrations/syncable_items?sync_run_id={n}
using the sync_run_id
value received in the webhook payload.
The response will contain a paginated list of data entries to sync. We encourage you to use the cursor pagination, which is more performant than the offset pagination.
Example with Compensation data
{
"data": [
{
"syncable_sync_run_id": 1,
"sync_payload": {
"employee_id": 8,
"payroll_concept_id": 16,
"amount": 50,
"unit": "units",
"effective_on": "2025-08-31",
"employee_company_identifier": "23537657",
"legal_entity_id": 5
}
},
{
"syncable_sync_run_id": 2,
"sync_payload": {
"employee_id": 6,
"payroll_concept_id": 20,
"amount": 5198, # Amount in cents (5198 -> 51.98)
"unit": "money",
"effective_on": "2025-08-31",
"employee_company_identifier": "23456787",
"legal_entity_id": 3
}
},
{...}
],
"meta": {
"has_next_page": true,
"has_previous_page": false,
"start_cursor": "MQ==",
"end_cursor": "MTAw",
"total": 869,
"limit": 100
}
}

3. Process Sync Data
When processing the data, the partner is responsible for:
- Performing the delta:
- The client may trigger the sync multiple times for the same period and company, potentially with different filters. These are not concurrent, but your system must ensure idempotency or manage updates accordingly.
- Pushing data to the external system:
- Create or update items (compensations, expenses) in the external payroll provider based on the sync data.
Please clarify with Factorial how updates should be managed:
Should we overwrite previous values defined directly in the external system, or should a merge be done? (This depends on which system is the source of truth.)
4. Report Sync Status
Once sync items are processed, the Partner needs to report the final status of each syncable_sync_run
received in the step 2 back to Factorial by calling:
PUT {baseUrl}/api/{version}/resources/integrations/syncable_sync_runs/{id}
{
"status": "success"| "failed" | "invalid",
"error_messages": {
"sycn_api_error": string,
"sync_validation_error": string
...
}
}
- Use
success
when the item was synced correctly to the external software. - Use
failed
if something went wrong and the item was not synced. - Use
invalid
if the data is structurally incorrect or missing required fields.- Example: Factorial sends you a compensation with a
payroll_concept_id
that you don’t have mapped with any code of the payroll software
- Example: Factorial sends you a compensation with a
One hour after the user starts the sync process, any items without a reported status will be marked as 'failed,' and the sync_run will be updated to its corresponding final state.

Updated about 14 hours ago