> ## Documentation Index
> Fetch the complete documentation index at: https://opentrain.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Project Links

> Map your platform's projects to OpenTrain jobs so contract events route to the right workspace: create, list, get, and delete project links.

A **project link** maps one of your platform's projects to an OpenTrain job. Links are the routing layer of the integration: [lifecycle events](/docs/developers/annotation-platforms/lifecycle-events) are job-keyed, so you only receive `contract.started` / `contract.ended` for jobs you have linked, and [`GET /contracts`](/docs/developers/annotation-platforms/api-reference/contracts/list) only surfaces contracts on linked jobs.

<Tip>
  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`](/docs/developers/annotation-platforms/api-reference/contracts/list) once the link is in place).
</Tip>

## Creating a Link

Requires `project-links:write`. The customer supplies (or your integration settings store) the OpenTrain `jobId`; you supply your own project's identity:

```bash theme={null}
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](/docs/developers/annotation-platforms/api-reference/project-links/create).

## Reading Links

```bash theme={null}
# 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:

```json theme={null}
{
  "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"
}
```

## Deleting a Link

```bash theme={null}
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.

## Related Reference Pages

* [List Project Links](/docs/developers/annotation-platforms/api-reference/project-links/list)
* [Create Project Link](/docs/developers/annotation-platforms/api-reference/project-links/create)
* [Get Project Link](/docs/developers/annotation-platforms/api-reference/project-links/get)
* [Delete Project Link](/docs/developers/annotation-platforms/api-reference/project-links/delete)
