Skip to main content

Credential Ownership

A credential belongs to the person it was issued to, and that person may be an applicant during recruitment and a worker after they're hired. Ownership is what carries the credential — and its verification history — across that boundary without re-verifying it.

Most integrations never touch these endpoints: creating a credential with owners set, as the Workers & Credentials tutorial does, is enough. You need this page when ownership has to change after the fact — the applicant-to-worker hire flow above all.

owners is immutable on PATCH/PUT — attempting it returns 400. Change ownership through the dedicated endpoints instead. Each owner reference is a type plus exactly one of id or externalId. A credential holds at most one worker and one applicant slot at a time.

# Link an additional owner to one credential
curl -sS -X POST "$OHO_BASE/credentials/$CRED/link" \
-H "Authorization: Bearer $OHO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "to": { "type": "applicant", "id": "app_Qz7yT2mB" } }'

# Transfer an owner — the canonical applicant -> worker hire flow
curl -sS -X POST "$OHO_BASE/credentials/$CRED/transfer" \
-H "Authorization: Bearer $OHO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "from": { "type": "applicant", "id": "app_Qz7yT2mB" }, "to": { "type": "worker", "id": "'"$WKR"'" } }'

# Unlink an owner (refuses if it would leave the credential with no owners)
curl -sS -X POST "$OHO_BASE/credentials/$CRED/unlink" \
-H "Authorization: Bearer $OHO_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "ownerType": "applicant" }'

References: Link · Transfer · Unlink.

Conflicts

Linking a slot that already holds a different id returns 409 with code ALREADY_LINKED — use transfer to replace it. Transferring a credential not currently owned by from returns 409 with code OWNER_MISMATCH.

Bulk ownership

POST /credentials/link and POST /credentials/transfer (no {id} in the path) operate on many credentials at once. Omit credentialIds to process every credential currently linked to from; the response reports a per-item status. Best-effort batch, capped at 500.

curl -sS -X POST "$OHO_BASE/credentials/transfer" \
-H "Authorization: Bearer $OHO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"from": { "type": "applicant", "externalId": "ATS-55021" },
"to": { "type": "worker", "externalId": "WD-100482", "sourceSystem": "workday" }
}'
{
"data": [
{ "credentialId": "cred_8x2Kf9aQ4mN7pLrT", "status": "transferred" },
{
"credentialId": "cred_bad1",
"status": "skipped",
"error": {
"code": "OWNER_MISMATCH",
"message": "not owned by applicant ..."
}
}
],
"meta": { "total": 2, "succeeded": 1, "failed": 1, "requestId": "..." }
}