Create An ATS Specific Contract

Integration Toolkit > Create An ATS Specific Contract

This section guides you on how to develop the Oneflow contract creation backend logic within the Oneflow Integration in your ATS system. To develop the backend logic for Oneflow contract creation within your ATS system, you should allow users to generate contracts from objects such as Candidate Profiles, Job Applications, or Offers. Contracts can be created through automated triggers (e.g., when an offer is made) or manually by selecting a specific candidate or application. The contract details, including the participants, will be populated dynamically based on the ATS object data.

After authenticating your application with Oneflow, you can decide which event in the ATS will initiate the integration (e.g., job offer accepted, candidate signed contract), and what specific data need to be transferred from ATS to Oneflow.

Oneflow Contract Stages

Below are the primary Oneflow contract stages, which can be mapped to the corresponding candidate stages in your ATS.

  • Contract Created: The employment contract has been created.
  • Contract Sent: The employment contract has been sent to the candidate.
  • Contract Signed: All parties have signed the employment contract.
  • Contract Declined: The candidate has declined the employment contract.
  • Contract Overdue: The candidate has not signed the contract within the specified time frame.
  • Data Field Update: When a data field in the contract is updated in Oneflow, an event is triggered to ensure these changes are reflected in your ATS. For the contract owners, this process ensures that any updates to contract details (such as job title, salary, or start date) are accurately and promptly communicated to the ATS. This can also reduce data inconsistency between your ATS and the applicant/employee’s contract in Oneflow, thus, boosting your productivity.

Below is a sample stage mapping of Oneflow contract stages to ATS stages. You can refer to this when creating your own stage mapping configuration for your ATS integration.

Stage Mapping

ATS Candidate StageOneflow Contract StageDescrption
OfferedContract Created and Contract SentWhen a candidate is moved to the “Offered” stage, the contract will be created and sent.
HiredContract SignedWhen the candidate signs the contract in Oneflow, update the ATS to move the candidate to the "Hired" stage.
RejectedContract DeclinedIf the candidate/employer declines the contract, notify the ATS to update the status to "Rejected."
Employer action (Offered or Rejected)Contract OverdueIf the contract is overdue, the employer should then decide whether to extend the signing deadline or decline the contract, and take appropriate action.
OfferedData field updateWhen candidate details are changed, the changed data will be reflected in the contract. (Only possible in draft mode).

Data Transfer

The data transfer between Oneflow and the ATS is a critical component of the integration process. This involves syncing candidate details and contract information to ensure that both systems are up-to-date and consistent.

Data transfer occurs in two main directions:

  1. From your ATS to Oneflow, where candidate information is used to create and update contracts,
  2. From Oneflow to the ATS, where contract status changes are reflected in the candidate's profile in your ATS.

This bidirectional data flow ensures seamless communication and accurate record-keeping across both platforms.

Syncing Data from ATS to Oneflow

When the integration process starts in your ATS, and the candidate moves to the "Offered" stage, the following steps can be taken to synchronize data and create the contract in Oneflow

  1. Candidate Moves to Offered Stage
    1. The ATS detects when the candidate transitions to the "Offered" stage.
    2. A trigger is initiated to start the data transfer process from the ATS to Oneflow.
  2. Fetch Latest Candidate Details
    1. Oneflow sends a request to the ATS to fetch the latest candidate details, including name, contact information, job position, email, and any other relevant data.
    2. The ATS responds with the requested candidate details.
  3. Create Contract in Oneflow
    1. Scenario 1: If the ATS provides an iframe, the user can open the Oneflow contract creation interface within the iframe, select the workspace and template, and manually create the contract.
    2. Scenario 2: If the ATS does not provide an iframe, Oneflow will rely on event notifications when the candidate moves to the "Offered" stage. Using these notifications, Oneflow will automatically create the contract using the Public API.
  4. Send the Contract
    1. Once the contract is created and the candidate is added as a participant, Oneflow sends the contract to the candidate for review and signature.
  5. Contract Signed or Declined
    • Contract Signed: When the candidate and the contract owner sign the contract in Oneflow, an update will be sent to the ATS to move the candidate from the "Offered" stage to the "Hired" stage. Additionally, if the ATS allows, the signed contract will be uploaded to the ATS.
    • Contract Declined: If the candidate or contract owner declines the contract in Oneflow, the ATS will update the candidate’s status from the "Offered" stage to the "Rejected" stage. Additionally, if the ATS allows, the declined contract will be uploaded to the ATS.
Flow - Creating ATS Specific Contract

Create a Contract

To create a contract in Oneflow, you will need to specify the Oneflow workspace and template where the contract will be stored. To simplify this process, provide a list of available workspaces and templates for users to choose from.

📘

Note:

Please note that new workspaces and templates can only be created within the Oneflow application.

Refer to Get workspace from Oneflow and Get templates from Oneflow for instructions on retrieving workspaces and templates.

FUNCTION CreateContract
    INPUT: A request body containing:
        - TriggeredBy: The user who triggered the contract creation
        - Auth: Authorization details for OneFlow
        - Contract details
        - SendContract: Flag indicating if the contract should be sent automatically (true/false)
        - ContractSubject: Subject for the contract (if SendContract is true)
        - ContractMessage: Message for the contract (if SendContract is true)
    OUTPUT: The ID of the created contract

    BEGIN
        # Step 1: Extract required data from request body
        Retrieve the email of the user from TriggeredBy
        Retrieve the authorization token from Auth
        SET template_id TO value of 'template_id' in body
        SET workspace_id TO value of 'workspace_id' in body
        SET participants TO value of 'participants' in body
        SET contract_name TO value of 'candidate_name' in body
        SET send_contract TO value of 'SendContract' in body
        SET contract_subject TO value of 'ContractSubject' in body
        SET contract_message TO value of 'ContractMessage' in body
        
        # Step 2: Prepare participant details
	Call AddParticipants to add participants to the contract
				
	# Step 3: Determine if the contract should be sent directly
        IF send_contract IS TRUE THEN
            IF contract_subject IS EMPTY OR contract_message IS EMPTY THEN
                RETURN {'error': 'Contract subject and message cannot be empty'}

        # Step 4: Create the Oneflow contract
        TRY
            # Calls the CreateOneflowContract function to create a contract.
            SET oneflow_contract TO CALL CreateOneflowContract USING template_id, workspace_id, my_party, counterparties, and contract_name
        CATCH Exception
            # Handles exceptions encountered during contract creation.
            HANDLE exception
        END TRY

        # Step 5: Return the contract ID
        Return the ID of the created contract
    END

If you want to include additional participants from your company in the contract, you can add them as my_party participants. For example, you might include a line manager, supervisor, or HR manager. However, the candidate will be added as an individual party.

FUNCTION AddParticipants
    INPUT: participants (contains participant details, including candidate and my_party participants)
    OUTPUT: my_party (an object containing participants), parties (a list of party objects)

    BEGIN
        # Step 1: Initialize my_party object
        Initialize an empty object called my_party
        Initialize an empty list called my_party.participants

        # Step 2: Add additional my_party participants (if any)
        IF participants IS NOT EMPTY THEN
            TRY
                FOR EACH participant IN participants DO
                    SET participant_details TO {
                        '_permissions': { 'contract:update': participant_type != 'viewer' },
                        'name': participant.fullname,
                        'title': participant.jobtitle OR '',
                        'email': participant.email,
                        'phone_number': participant.phone_number,
                        'signatory': participant_type == 'signatory',  # Set signatory as boolean
                        'sign_method': participant.preferred_sign_method OR 'standard_esign',  # Default value
                        'delivery_channel': participant.preferred_delivery_channel OR 'email'  # Default value
                    }
                    # Add participant details to the my_party.participants array
                    ADD participant_details TO my_party.participants
            CATCH Exception
                # Handles exceptions encountered during my_party creation
                HANDLE exception
            END TRY
        END IF

        # Step 3: Initialize parties list
        Initialize an empty list called parties

        # Step 4: Add the candidate as an individual counterparty
        TRY
            SET candidate TO {
                '_permissions': { 'contract:update': false },
                'name': candidate.fullname,
                'title': candidate.jobtitle OR '',
                'email': candidate.email,
                'phone_number': candidate.phone_number,
                'signatory': participant_type == 'signatory',  # Set signatory as boolean
                'sign_method': candidate.preferred_sign_method OR 'standard_esign',  # Default value
                'delivery_channel': candidate.preferred_delivery_channel OR 'email'  # Default value
            }
            # Add candidate details to the parties list with type set to IndividualCounterparty
            ADD candidate TO parties WITH type 'IndividualCounterparty'
        CATCH Exception
            # Handles exceptions encountered during parties creation
            HANDLE exception
        END TRY

        # Step 5: Return the my_party object and parties list separately
        RETURN my_party, parties
    END

Function to create Oneflow contract

FUNCTION CreateOneflowContract(template_id, workspace_id, my_party, counterparties, contract_name)
    # Purpose: Create a contract in Oneflow using the provided details.

    # Step 1: Prepare the request body
    CREATE body AS a key-value store WITH:
        "template_id": template_id,
        "workspace_id": workspace_id,
        "contract_name": candidate_name,
        "my_party": my_party
        "parties": counterparties

    # Step 2: Set up the headers for the API request
    DEFINE HEADERS
        SET "x-oneflow-api-token" IN HEADERS TO user.apiToken
        SET "x-oneflow-user-email" IN HEADERS TO user.email
        SET "Content-Type" IN HEADERS TO "application/json"

    # Step 3: Make the API request to create the contract
    SET response TO POST REQUEST TO "{host}/v1/contracts/create" WITH:
        - JSON body
        - SSL verification
        - HEADERS

    # Step 4: Check the response status code
    IF response.StatusCode EQUALS 200 THEN
        SET jsonResponse TO result of parsing response to JSON format
        RETURN jsonResponse
    ELSE
        THROW HttpResponseError
END FUNCTION