DEVELOPER DOCUMENTATION
Consent and Installs
Learn how customers connect OpenTrain to your platform with consent links, scopes, PII consent, one-time tokens, reconnects, and revocation.
An install is one customer’s grant of access to your platform app: which scopes they approved, whether they consented to Work Email sharing, and the tokens minted under that grant. Every Platform API token (ot_ptk_…) belongs to exactly one install.
The Consent Deep Link
Section titled “The Consent Deep Link”Send your customer (an OpenTrain employer — specifically the organization owner) to:
https://app.opentrain.ai/integrations/{partnerSlug}/connect?external_project_id=<id>&redirect_uri=<url>&state=<opaque>| Query parameter | Required | Purpose |
|---|---|---|
external_project_id | No | Your project identifier. Echoed back on the return redirect so you know which of your projects initiated the connection. |
redirect_uri | No | Where to send the customer after consent. Must be http(s) and match a redirect URI registered for your app: same origin, and its path must start with the registered base path (so dynamic sub-paths under a registered base work). |
state | No | Opaque value echoed back unchanged on the return redirect — use it to correlate the flow on your side. |
On the consent screen the customer sees your app’s name, the scopes you requested, and — if you requested participants:email — a separate, explicit PII consent checkbox for Work Email sharing. They can approve or decline.
The One-Time Token
Section titled “The One-Time Token”When the customer approves, OpenTrain mints an install-scoped ot_ptk_… token and displays it once, on the consent screen only. The customer copies it into your platform’s integration settings.
Scopes
Section titled “Scopes”Your app requests a subset of these seven scopes when you register it; the customer sees each one described on the consent screen:
| Scope | Grants |
|---|---|
project-links:read | Read links between your projects and OpenTrain jobs |
project-links:write | Create and remove project links (implies project-links:read) |
contracts:read | Read contracts (status, dates, budget) on linked jobs |
participants:read | Read hired participants on linked contracts: OpenTrain user ID, display name, profile URL, country |
participants:email | Read the participant’s @opentrain.work Work Email. Requires the explicit PII consent checkbox at install time; personal email addresses are never shared |
usage:write | Report cumulative per-day work usage (time, tasks, labels) for contracts on linked jobs |
webhooks:manage | Create, list, update, and delete webhook endpoints |
participants:email is double-gated: the scope must be granted and the install must have piiConsent: true. If the customer granted the scope but left the consent box unchecked, requests that would return Work Email are refused with 403 at request time — and webhook payloads simply omit the workEmail field.
Inspecting Your Install
Section titled “Inspecting Your Install”GET /installs/current returns the install your token belongs to — useful as a connectivity check and to confirm which scopes and consent you actually have:
curl -sS https://app.opentrain.ai/api/partner/v1/installs/current \ -H "Authorization: Bearer $OT_PARTNER_TOKEN"{ "install": { "id": "<INSTALL_ID>", "status": "ACTIVE", "scopes": [ "project-links:read", "project-links:write", "contracts:read", "participants:read", "participants:email", "webhooks:manage" ], "piiConsent": true, "organizationId": "<ORG_ID>", "createdAt": "2026-06-12T10:00:00.000Z", "partnerApp": { "id": "<APP_ID>", "slug": "your-app", "name": "Your App" }, "token": { "id": "<TOKEN_ID>", "name": "Your App connection", "scopes": ["..."] } }}What Every Request Requires
Section titled “What Every Request Requires”Beyond the right scope, every Platform API request checks four things. Any of them failing yields 401 or 403:
- A live token — not revoked or expired
- An
ACTIVEinstall - An
ACTIVEplatform app - The annotation-platform feature enabled for the granting employer’s account
Reconnecting
Section titled “Reconnecting”If a customer runs the consent flow again for an app they already installed, OpenTrain revokes all previous tokens for that install before minting the fresh one. A scope reduction on reconnect therefore cannot be bypassed by holding on to an older, broader token. Treat any 401 as a signal to ask the customer to reconnect.
Revocation
Section titled “Revocation”Customers can disconnect your app at any time from their OpenTrain integrations page. Disconnecting immediately:
- Flips the install to
REVOKED - Revokes every access token — your next request returns
401 - Emits an
install.revokedevent to webhook deliveries already queued - Stops all new event fan-out for that install
Handle install.revoked by ceasing work for that customer and marking the connection as disconnected in your UI.