Skip to main content
Everything runs on the Tomorro REST API: one counterparty call, one contract call and one signature call per new employee. How you read and write the HRIS depends on your HRIS.

1. Technical prerequisites

1

1.1 - Create Tomorro superadmin account

An existing admin creates a dedicated superadmin account from Settings > Members (e.g. automation@customer.com), not a personal account.
  • The API key is bound to a member, not to the organization. Every write performed through the API is attributed to that member and inherits its permissions.
  • Consequence: this account is the author of every employment contract created by the integration. A named account such as “HRIS automation” keeps the contract timeline readable.
  • Recommended: no personal mailbox behind it, and exclude it from Tomorro notification settings.
2

1.2 - API key

Generate the API key from that superadmin account. It does not expire. It is sent on every REST call in the x-api-key header: Step 1: Get your API key
3

1.3 - Contract type and template in Tomorro

The template carries everything the integration does not send.
  • Contract type (e.g. Employment contract): its default signature tool is Tomorro, so the employee receives the signature email from Tomorro.
  • Smart fields: one per mapped HRIS field (Libraries > Dynamic components > Smart fields > New), placed in the template. Pick the type matching the HRIS: Text for names, Date for the date of birth, Number for the salary, Single-choice selector for the job title and the grade (options = the HRIS values, see 3.3).
  • Signatories on the template: the internal signatory is set on the template (e.g. the HR Director), and the external signatory has a signature zone but no one assigned. The integration fills that empty slot with the employee’s email.
  • One template per job if the contract differs by job: keep a job title → templateId table in the integration.
  • One template per language: the contract takes the language of its template (language in GET /v2/contract-types/{id}/templates, e.g. FR, EN). To generate a contract in English, create the English template and pick it: the table becomes job title + language → templateId.
  • Copy the ids next to your mapping (Non-Technical scoping): the contract type id from GET /v2/contract-types, the template ids from GET /v2/contract-types/{id}/templates, the smart field ids from GET /v2/contract-types/{id}/creation-form (or the last segment of the smart field URL).
4

1.4 - Approval before signature

If an approval workflow runs before signature on this contract type, the contract goes to approval first and is not sent to the employee straight away (Flow 1, step 3). Decide with the business owner: no approval on this contract type, or keep it and let the contract wait for it.
5

1.5 - HRIS: add the Tomorro contract field

Add a text field Tomorro contract to the employee record, empty for every employee. The integration fills it with the contract id (and contractUrl if there is room); users must not edit it. It stops a second contract from being created for the same employee.

2. Flows

Flow 1 - [HRIS → Tomorro → HRIS] New employee in the HRIS

1

Step 0 - Triggered by the HRIS

Out of scope. An employee record is created and validated in the HRIS: HRIS event or webhook if it has one, otherwise poll the employees created since the last run. Skip it if Tomorro contract is already filled, or if a mapped field or the email is empty.
2

Step 1 - Create the employee as a counterparty

Response 201:
  • Keep data.id for step 2.
  • Why a separate call: POST /v2/contracts also accepts counterparty.name, but it then reuses any counterparty with the same name (case and spaces ignored). Two employees named Jane Doe would share one counterparty. Creating it here, then passing its id, gives every employee their own.
3

Step 2 - Create the employment contract

Response 201:
  • templateId is required in practice: without it, the contract has no document and cannot be sent for signature. It also sets the contract language.
  • fields: one entry per smart field, value always a string. Dates as YYYY-MM-DD, numbers without spaces or currency ("48000"), picklists as the exact option label (see 3.3). Leave a field out rather than sending an empty string.
  • Signatories: only send the employee’s email. It fills the empty external signature zone of the template; the internal signatory is already on the template. Do not add more signatories than the template has empty zones: the extra ones get no signature zone and step 3 is refused.
  • Required fields of the contract type’s creation form that are missing: 400 IncompleteCreationForm. Unknown contractTypeId or templateId: 404.
  • Keep data.id and data.contractUrl.
4

Step 3 - Send the contract for signature

Response 200:
  • Can be called right after step 2: the document and its signatories are ready when step 2 answers.
  • documentId is optional: without it, the last document of the contract is sent.
  • Always check data.status:
    • sent: done. The contract moves to signing, Tomorro emails the signatories in the signing order of the contract type and template.
    • draft: the signature was not sent. Usually an approval workflow before signature (1.4): the contract waits for it. Alert HR with contractUrl.
  • signatureNote is the message shown to the signatories. isReminderEnabled defaults to true.
Errors on step 3 (400, branch on error.errorId)
5

Step 4 - Write the contract back to the HRIS

Out of scope (depends on the HRIS). Write data.id (and contractUrl) from step 2 into Tomorro contract, straight away: until it is written, a new run would create a second contract for the same employee.
Rate limit: no need to slow the calls down. If Tomorro answers 429, retry with backoff.

Flow 2 (optional) - [Tomorro → HRIS] Contract signed

1

Step 0 - Receive the contractSigned webhook

Create the webhook from the automation account (1.1), trigger contractSigned: Webhooks. Webhooks only fire for contracts that concern the member who created them, and this account is the author of every contract of Flow 1.Verify the Leeway-Signature header (Technical documentation), answer 2xx straight away, then keep data.contract.id, and data.contract.signatureDate for the HRIS.
2

Step 1 - Find the employee

Out of scope (depends on the HRIS). Look up the employee whose Tomorro contract field holds data.contract.id (Flow 1, step 4). No employee: the contract was not created by Flow 1, ignore the event.
3

Step 2 - Get the signed PDF

Response 200:
downloadUrl is valid 30 seconds: download the file straight away (no auth header), and re-call the endpoint for a fresh URL if needed.
4

Step 3 - Upload to the employee record

Out of scope (depends on the HRIS). Upload the PDF to the employee’s documents and write the signature date. With Lucca, for instance, attach the uploaded file to the work contract by its fileId.

3. Technical references

Reference material: conventions, the endpoints, field values and error handling. Read it once, then come back to it while implementing the flows above.

3.1 - API conventions

  • REST only. The whole integration runs on the public REST API.
  • Base URL: https://api.tomorro.com/v2
  • Authentication: x-api-key: <your api key> on every call. A missing or unknown key returns 401.
  • Versioning: optional tomorro-version header, defaults to the latest version.
  • Rate limit: a 429 means too many calls in a short time. Retry with backoff.
  • Sandbox: available on request. It is an empty sandbox, not a copy of your production workspace.
  • Content type: application/json
  • Response envelope: every successful JSON response is wrapped in a data object (errors come as { error, meta }, see 3.4). Read data.id, data.status and so on.
  • Full reference: Tomorro API

3.2 - Endpoints

3.3 - Field values

fields[].value is always a string. Tomorro does not reformat it: send it in the format below.
  • Picklists: a label that matches no option is not refused, it is stored as an unknown value and shows empty in Tomorro. Align the labels on both sides first (job titles, grades), and translate HRIS codes into Tomorro labels in the integration when they differ.
  • Built-in contract fields can be set the same way, by name instead of id: startAt (start date, YYYY-MM-DD), endAt (end date, for a fixed-term contract).
  • null clears a field.

3.4 - Error handling

Every endpoint follows the standard error format of the REST API. Error envelope
  • error.statusCode is a string, not a number.
  • meta.requestId is the value to quote to Tomorro support when reporting a failing call. Log it.

3.5 - Edge cases

  • Link: the Tomorro contract field in the HRIS. Never match on the employee’s name.
  • Employee created twice in the HRIS, or flow re-run: skipped as long as Tomorro contract is filled (Flow 1, step 0).
  • Rehire: a returning employee already has a counterparty. Reuse its id (store it in the HRIS too) instead of creating a second one in step 1.
  • Missing email: no external signatory, the contract cannot go to signature. Skip the employee in step 0 and alert HR.
  • Data changed in the HRIS after the contract was sent: the integration does not update a contract in signature. Cancel it in Tomorro and clear Tomorro contract to generate a new one.
  • Triggers: prefer an HRIS webhook or event on “employee validated”, so Flow 1 runs as soon as the record is ready. Without one, poll the employees created since the last run, e.g. every 15 minutes.