Skip to main content
A project link maps one of your platform’s projects to an OpenTrain job. Links are the routing layer of the integration: lifecycle events are job-keyed, so you only receive contract.started / contract.ended for jobs you have linked, and GET /contracts only surfaces contracts on linked jobs.
Link the job before the customer starts hiring. Events are emitted at hire/end time for jobs with an active link — there is no replay for contracts that started before the link existed (though you can still read them via GET /contracts once the link is in place).
Requires project-links:write. The customer supplies (or your integration settings store) the OpenTrain jobId; you supply your own project’s identity:
curl -sS -X POST https://app.opentrain.ai/api/partner/v1/project-links \
  -H "Authorization: Bearer $OT_PARTNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "externalProjectId": "42",
    "externalProjectName": "Traffic signs batch 3",
    "externalProjectUrl": "https://your-platform.example.com/projects/42",
    "jobId": "<OPENTRAIN_JOB_ID>",
    "provisioningMode": "PARTNER_WEBHOOK"
  }'
The rules:
  • externalProjectId is required (max 200 characters) and unique per install — creating a second link with the same ID returns 409.
  • jobId must be a job owned by the installing employer — anything else returns 404. (jobId is optional at creation; a link without a job receives no contract events until it points at one.)
  • provisioningMode defaults to PARTNER_WEBHOOK — you provision workspace members from webhook events. MANAGED_ADAPTER selects the OpenTrain managed-credential path instead.
  • A successful create emits a project_link.created event.
Full parameter and response detail: Create Project Link.
# All links on this install, newest first (project-links:read)
curl -sS https://app.opentrain.ai/api/partner/v1/project-links \
  -H "Authorization: Bearer $OT_PARTNER_TOKEN"

# One link
curl -sS https://app.opentrain.ai/api/partner/v1/project-links/<LINK_ID> \
  -H "Authorization: Bearer $OT_PARTNER_TOKEN"
Each link looks like:
{
  "id": "<LINK_ID>",
  "jobId": "<OPENTRAIN_JOB_ID>",
  "externalProjectId": "42",
  "externalProjectName": "Traffic signs batch 3",
  "externalProjectUrl": "https://your-platform.example.com/projects/42",
  "provisioningMode": "PARTNER_WEBHOOK",
  "createdAt": "2026-06-12T10:00:00.000Z"
}
curl -sS -X DELETE https://app.opentrain.ai/api/partner/v1/project-links/<LINK_ID> \
  -H "Authorization: Bearer $OT_PARTNER_TOKEN"
Deletion is permanent — the link row is hard-deleted. The response and the emitted project_link.removed event both carry a final snapshot of the link, which is the last time you will see its data. After deletion, contract events for that job stop (unless another link on your install references the same job).

Re-Linking

There is no update operation on links. To point one of your projects at a different OpenTrain job — or fix a wrong externalProjectId — delete the old link and create a new one. Expect a project_link.removed followed by a project_link.created event.