Skip to content

Request an integration

Tell us which system you want to connect. We review every request weekly and publish a step-by-step guide or build the connection.

OTYS integration

Sync OTYS candidates, relations and placements into TimeTracking with external-ID upserts, batches and the OTYS web services.

Last updated: · Markdown version

1. Summary

Status: Recipe (no native connector).

Direction: OTYS to TimeTracking for master data. Optional: approved hours back.

2. Mechanism

  • OTYS side. OTYS JSON-RPC web services (OWS) for candidates, relations (companies), vacancies and procedures/placements. Poll on modification date.
  • TimeTracking side. PUT /{clients|people|placements}/by-external/otys/{uid} or the batch endpoints with externalSource: "otys".
  • Hours back (optional). GET /days?status=approved&updated_since=….

Assumption — verify with your OTYS consultant: service and field names (for example Otys.Services.CandidateService, RelationService, procedure status "placed") vary by module and licence.

3. Prerequisites

  • OTYS web services API key with read rights on candidates, relations and procedures.
  • TimeTracking API key with scope write (admin if the job also manages webhooks).

4. Entity mapping

OTYS object.field TimeTracking field Notes
Candidate uid person external ref (/people/by-external/otys/{uid})
Candidate payroll number employeeNumber
First name / last name incl. prefix firstName / lastName Prefix in lastName.
Email, mobile, language email, phone, locale
Relation uid client external ref
Relation name name
Procedure/placement uid placement external ref; ref
Candidate uid / relation uid personExternalRef / clientExternalRef
Vacancy title roleTitle
Start / end startsOn / endsOn
Procedure closed DELETE /placements/{id} (deactivate)

External-ID strategy. source = otys, ref = OTYS uid. Idempotent upserts, full replace semantics, created: true|false in responses.

5. Step-by-step setup

export TT=https://app.timetracking.tech/api/v1
export KEY=tt_live_...
curl -s -X PUT "$TT/clients/by-external/otys/5521" -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
  -d '{"name":"Bakkerij Ruijters","externalRef":"5521"}'
curl -s -X PUT "$TT/people/by-external/otys/c-88412" -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
  -d '{"employeeNumber":"1004","firstName":"Sanne","lastName":"Janssen"}'
curl -s -X PUT "$TT/placements/by-external/otys/77810" -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
  -d '{"personExternalRef":"c-88412","clientExternalRef":"5521","ref":"OT-77810","roleTitle":"Productiemedewerker","startsOn":"2026-10-01"}'

For bulk loads use POST /clients/batch, /people/batch, /placements/batch (≤500 rows). Structure the job like the Bullhorn sync script.

6. Sync schedule and triggering events

Trigger Action
Poll OTYS every 15 min Upsert changed records.
Nightly Re-upsert all active records.
timesheet.approved or schedule (optional) GET /days?updated_since=… and write back.

7. Corrections, conflicts and locked periods

TimeTracking owns hours, conflicts and locks. Corrections bump the day version and return it to submitted. Exported/locked days return 423. Ending a placement before existing hours returns 409.

8. Testing checklist

  • Re-runs return created: false and create no duplicates.
  • Name prefix lands in lastName.
  • Closed procedure deactivates the placement.

9. Troubleshooting

Error Fix
401 New key from a current admin.
403 read-only Use a write key.
422 "Person and client must exist …" Upsert person and client first.
409 Placement shortened before hours.
429 Wait Retry-After.

10. Limits and known gaps

No client-contact API. Native OTYS app: Planned.

11. Build it with Claude

Build an OTYS → TimeTracking placement sync (TypeScript). Ask me for the OTYS web-service names and a sample
candidate, relation and placement response first. TimeTracking: https://app.timetracking.tech/api/v1, Bearer
$TT_API_KEY. Use PUT /clients|/people|/placements/by-external/otys/{uid} (full replace; placements use personExternalRef/clientExternalRef), POST /…/batch for bulk,
DELETE /placements/{id} to deactivate, Idempotency-Key on writes, 429 handling, dry-run mode, mocked-HTTP tests.