openapi: 3.0.0
info:
title: Factorial API
description: >-
Open Api Specifications available at
[https://github.com/factorialco/oas](https://github.com/factorialco/oasLooking)
Guides and support available at
[https://help.factorialhr.com/integrations](https://help.factorialhr.com/integrations)
# Authentication
The public API provides two methods of authentication, ApiKeys and OAuth2.
The following sections provide information regarding each one and their
intent.
## OAuth2
> OAuth2 is used to identify individual users, not applicatins or platforms.
OAuth2 is available for authenticating to the public API and making requests
via third parties **on behalf of a user**. All actions are authored on
behalf of the user that creates the token. This means the intent is to be
used mainly to do submit actions the actual user is performing on an
alternative interface.
To generate a token you will require opening an authorization dialog that
returns a code, this code can then be exchanged for a token.
### Configuration
In order to create an OAuth application, you must be an admin, head over to
your [personal repository of OAuth
applications](https://api.factorialhr.com/oauth/applications), click on `New
application` and follow the creation process.
The Factorial API enforces the same permissions at the user level than the
Factorial web application. This means that Factorial API users will only be
able to perform the same actions they are allowed to do in the Factorial
platform.
Next step will be to generate the Authorization Code you will need in order
to generate an OAuth2 Token.
### OAuth2 Code Generation
Should be generated via browser by opening the following url. The user
should be already logged in to Factorial beforehand.
`https://api.factorialhr.com/oauth/authorize?client_id=&redirect_uri=&response_type=code&scope=`
YOUR_CLIENT_ID: OAuth2 Application Id
REDIRECT_URI: OAuth2 Redirect URL
#### State Parameter
An optional query parameter called `state` can be added to the code
generation url. Any string can be used and will be sent on the callback url.
> Authorization protocols provide a `state` parameter that allows you to
restore the previous state of your application. The `state` parameter
preserves some state objects set by the client in the Authorization request
and makes it available to the client in the response.
### OAuth2 Token Generation
Once you have the authorization code, you can request their access token to
Factorial.
`curl -X POST 'https://api.factorialhr.com/oauth/token' -d
'client_id=&client_secret=&code=&grant_type=authorization_code&redirect_uri='`
YOUR_CLIENT_ID: OAuth2 Application Id
YOUR_CLIENT_SECRET: OAuth2 Application Secret
AUTHORIZATION_CODE: OAuth2 CODE
REDIRECT_URI: OAuth2 Redirect URL
> You can generate only one OAuth2 token per Code, that means that if you
want to generate a new token for a Code that already have one you should
refresh your token.
Every time a new token is generated a refresh token is generated as well, so
that you can use it on the OAuth2 Refresh Token, and an expire date is also
provided.
### OAuth2 Refresh Token
You can generate a new token under the same Code with a new expire date (you
can do it as many times as you need). A refresh token is also returned here
so that you can use it on the OAuth2 Refresh Token again.
`curl -X POST 'https://api.factorialhr.com/oauth/token' -d
'client_id=&client_secret=&refresh_token=&grant_type=refresh_token'`
YOUR_CLIENT_ID: OAuth2 Application Id
YOUR_CLIENT_SECRET: OAuth2 Application Secret
REFRESH_TOKEN: OAuth2 Refresh Token
### OAuth2 Token Usage
The generated token is the credential for performing authenticated requests
to Factorial. This token should be included in the Authorization header
prefixed with the word Bearer and a separating space.
As an example, if your token is `12345` then the header content should be
`Bearer 12345`.
### Maintaining a persistent connection
To maintain a persistent connection, you should not let the token expire.
You can avoid this by simply refreshing your token before the expiration
date. This will give you another token with a new expiration date, before
that token expires you should refresh it again, and so on...
If you want to do this automatically, you should provide something in your
code that will help you perform the update every time the token expires.
Otherwise, you would have to do the update manually and make sure you
refresh your token before the expiration date to maintain the connection.
## ApiKeys
> API keys are used to identify systems, not the individual users that
access.
ApiKeys have **TOTAL ACCESS** to everything and never expire. Its the
creators responsability to generate them and store them securely.
### Generation
In the `Core>Keys` section of this documentation you can access the apis for
managing this resource.
### Usage
ApiKeys are a single string of symbols that must be added as a custom header
on the request. The header name must be `x-api-key` and the key must be the
value without any prefixes.
### Disclaimer
ApiKey management require full admin permissions as the resource itself
allows for full admin access to the entire platform on behalf of the company
and not of a user, therefore any operations are not linked to any user in
particular.
# Development
## SDKs
Coming soon
## Sandbox
A sandbox/demo environment is available for testing integrations via public
API calls. Developers can request provisioning with full access to a demo
company where to test code before actually interacting with a production
environment.
Contact your account manager or account executive to request this
environment and get OAuth2 credentials for generating tokens.
Note: the domain for sandbox is different than that from production. Sandbox
base domain is `http://api.demo.factorialhr.com`
## Postman
Click the "Run in Postman" button to open the full list of endpoints on your
Postman workspace as a Postman Collection.
Inside the collection lookout for the Collection's Variables, configure your
variables accordingly.
### Delegating Token Generation To Postman
Coming soon
# Changelog
Coming soon
# How to...
## Custom Fields
Custom fields are useful when you want to add some fields that are not the
default ones, to every employee of the company.
For that, you have to create via Factorial App the base custom field in
order to have all the employees with it. That option is available in
customization, inside the company menu
Once you have that, via API, you can [Create a value for a custom
field](https://apidoc.factorialhr.com/#72f3f786-e37d-4e80-ada2-0beedd03b171)
to each employee. You should know the custom field id in order to make that,
you can check it by [getting a collection of custom
fields](https://apidoc.factorialhr.com/#f98dae5a-a8d0-474e-a181-7e9603409b42)
version: 1.0.0
servers:
- url: "https://api.factorialhr.com/api"
- url: "https://api.demo.factorialhr.com/api"
security:
- oauth2: []
- apikey: []
tags:
- name: Core
- name: Core > Employees
description: "Used for managing employees' information. Only\_`admins`\_can see all the employees' information,\_`regular users`\_will get a restricted version of the payload as a response based on the permission set by the admin"
- name: Core > Employees > V1
description: >-
This version contains employees information and also those that are
related to the employee such as contracts. So it is data intensive, hard
to maintain and not very efficient. This is addressed in version
[V2](https://apidoc.factorialhr.com/#575b6e00-1014-42df-809d-85a683aa4d54)
- name: Core > Employees > V2
description: >-
This version contains strictly employees information. Hence it is not data
intensive and easy to work with. We recommend using this version as V1
will be deprecated with time.
- name: Core > Webhooks
description: >-
> ### 📘
>
> "Knock knock on X outside Factorial when Y happens inside Factorial"
> ### 🚧 Usage
>
> Webhooks can be used directly or via intermediary platforms or services.
Using them directly requires technical knowledge.
## Factorial Webhooks
> ### 🚧 URL
>
> The same URL can be used to get notifications for all events or
different ones per event. Notice that if the same url for receiving
notifications is used for all events, then distinguishing an event from
another might be an issue.
When an event happens inside Factorial, a POST request will be triggered
to the associated event URL. If the request fails for any given reason, a
retry will be performed shortly after.
## Payload
Payloads per hook vary. The common factor will always be the id field for
the related resource that triggered the webhook. Implementations should
avoid relying on other fields.
## Webhooks Types
| **Type** | **Information** |
| --- | --- |
| employee_invited | When creating a new employee, optionally you can send
an invitation to create an account in Factorial. If you send an
invitation, this event gets triggered. |
| employee_created | When creating a new employee, after submitting the
form, this event gets triggered. |
| employee_terminated | When terminating an employee, after submitting the
form, this event gets triggered |
| employee_unterminated | When un terminating an employee, after
submitting the form, this event gets triggered |
| attendance_clockin | When the user clocks in and starts the timer, this
event is triggered. |
| attendance_clockout | When the user clocks out and stops the timer, this
event is triggered |
| ats_application_created | When a candidate applies for a posting. |
| ats_application_updated | When a candidates application for a posting
suffers changes. |
| ats_job_posting_created | When a job posting is created. |
| ats_job_posting_updated | When a job posting is updated. |
| ats_job_posting_deleted | When a job posting is deleted. |
| timeoff_leave_created | When a Timeoff Leave is created. |
| timeoff_leave_updated | When a Timeoff Leave suffers any changes. |
| timeoff_leave_approved | When a Timeoff Leave is explicitly approved. |
| document_created | When a document is created. |
- name: Core > Custom Fields
- name: Core > Files
- name: Core > Files > Documents
description: >-
###### **What does it do?**
This endpoints will allow you to create, update retrieve or delete
documents for the company or an employee. You are also going to be able to
request e-signatures from employees
###### **Is it related to other entities?**
Documents are going to be created under you company, but also can be
assign to an employee.
###### **Who can use it?**
Only admins are able to create documents.
- name: Core > Files > Folders
description: >-
###### **What does it do?**
This endpoints will allow you to create, update or retrieve folders
###### **Is it related to other entities?**
Once you create folder you are going to be able to store documents inside
them.
###### **Who can use it?**
Everyone can create folders
- name: Core > Location
- name: Core > Holidays
- name: Core > Legal Entities
- name: Core > Keys
description: "> API keys are used to identify systems, not the individual users that access.\n\nKeys give total access to the Factorial platform and the operations performed with such are not linked/associated to any user in particular. Therefore their management and storage must be done with extreme caution.\n\nUnlike OAuth2 tokens, Keys dont have a TTL and therefore dont require regenerating the key. As long as the key is not deleted, it will keep working indefinitly.\n\nFor security reasons, when creating a key the code that is generated will only be displayed on the response of the creation. Administrators should copy and safely store such Key as it cant be recovered later. Listing keys will only show a hashed version of the key.\n\n### Usage\n\nApiKeys are a single string of symbols that must be added as a custom header on the request. The header name must be\_`x-api-key`\_and the key must be the value without any prefixes.\n\nIf a request is received with both oauth token and apikey, the api key will overrule the oauth as it has broader permissions.\n\n### Disclaimer\n\nApiKey management require full admin permissions as the resource itself allows for full admin access to the entire platform on behalf of the company and not of a user."
paths:
/v2/core/employees:
get:
tags:
- Core::Employees::V2
summary: Get Employees From a Company
operationId: listEmployees
description: >-
Only `admins` can see all the employees' information, `regular users`
will get a restricted version of the payload as a response based on the
permission set by the admin
parameters:
- name: full_text_name
in: query
schema:
type: string
description: Retrieves the list of employees by full names
example: "Bob Stone"
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Employee"
'500':
description: Internal Server Error
post:
tags:
- Core::Employees::V2
summary: Create Employee
operationId: createEmployee
description: Create employee
requestBody:
content:
application/json:
schema:
type: "object"
properties:
email:
type: "string"
example: "[email protected]"
first_name:
type: "string"
last_name:
type: "string"
birthday_on:
type: "string"
example: "yyyy-mm-dd"
role:
type: "string"
example: "basic"
enum: ["basic", "admin"]
terminated_on:
type: "string"
example: "yyyy-mm-dd"
gender:
type: "string"
example: "female"
enum: ["male", "female"]
nationality:
type: "string"
bank_number:
type: "string"
country:
type: "string"
city:
type: "string"
state:
type: "string"
postal_code:
type: "string"
address_line_1:
type: "string"
address_line_2:
type: "string"
identifier:
type: "string"
swift_bic:
type: "string"
example: "1234567890"
company_id:
type: "integer"
example: 5
legal_entity_id:
type: "integer"
example: 5
manager_id:
type: "integer"
example: 5
timeoff_manager_id:
type: "integer"
example: 5
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: "#/components/schemas/Employee"
'500':
description: Internal Server Error
/v2/core/employees/{id}:
get:
tags:
- Core::Employees::V2
summary: Get Employee
operationId: getEmployee
description: >-
Only admins can see all the employees' information, regular users will
get a restricted version of the payload as a response based on the
permission set by the admin
parameters:
- name: id
in: path
schema:
type: string
required: true
description: '(Required) '
example: 5
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/Employee"
'500':
description: Internal Server Error
put:
tags:
- Core::Employees::V2
summary: Update Employee
operationId: updateEmployee
description: Update employee
requestBody:
content:
application/json:
schema:
type: "object"
properties:
email:
type: "string"
example: "[email protected]"
first_name:
type: "string"
last_name:
type: "string"
birthday_on:
type: "string"
example: "yyyy-mm-dd"
role:
type: "string"
example: "basic"
enum: ["basic", "admin"]
terminated_on:
type: "string"
example: "yyyy-mm-dd"
gender:
type: "string"
example: "female"
enum: ["male", "female"]
nationality:
type: "string"
bank_number:
type: "string"
country:
type: "string"
city:
type: "string"
state:
type: "string"
postal_code:
type: "string"
address_line_1:
type: "string"
address_line_2:
type: "string"
identifier:
type: "string"
swift_bic:
type: "string"
example: "1234567890"
manager_id:
type: "integer"
example: 5
timeoff_manager_id:
type: "integer"
example: 5
parameters:
- name: id
in: path
schema:
type: string
required: true
description: '(Required) '
example: <integer>
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/Employee"
'500':
description: Internal Server Error
/v1/me:
get:
tags:
- Core::Me
summary: Get Information About Current User
operationId: getCurrentUser
description: After token grant, get information of the token holder
responses:
'200':
description: OK
components:
securitySchemes:
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: "/oauth/authorize"
tokenUrl: "/oauth/token"
refreshUrl: "/oauth/token"
scopes:
read: Required for all operations
write: Required for write operations
apikey:
type: apiKey
in: header
name: x-api-key
schemas:
Employee:
type: "object"
properties:
email:
type: "string"
example: "[email protected]"
first_name:
type: "string"
last_name:
type: "string"
birthday_on:
type: "string"
example: "yyyy-mm-dd"
role:
type: "string"
example: "basic"
enum: ["basic", "admin"]
terminated_on:
type: "string"
example: "yyyy-mm-dd"
gender:
type: "string"
example: "female"
enum: ["male", "female"]
nationality:
type: "string"
bank_number:
type: "string"
country:
type: "string"
city:
type: "string"
state:
type: "string"
postal_code:
type: "string"
address_line_1:
type: "string"
address_line_2:
type: "string"
identifier:
type: "string"
swift_bic:
type: "string"
example: "1234567890"
company_id:
type: "integer"
example: 5
legal_entity_id:
type: "integer"
example: 5
manager_id:
type: "integer"
example: 5
timeoff_manager_id:
type: "integer"
example: 5