Skip to main content

Credentials

API for managing worker and applicant credentials.

📄️List credentials

Search credentials with optional filters. Owner filter accepts EITHER `ownerType+ownerId` (synthetic ID) OR `ownerType+ownerExternalId` (upstream HRIS/ATS ID, optionally narrowed by `ownerSourceSystem`). Other filters: credentialType, category, jurisdiction, status, eligibility, expiringBefore (ISO 8601 date). Filter by record recency with `updatedAfter` and/or `updatedBefore` (ISO 8601 instant, e.g. 2026-01-01T00:00:00Z, or a bare date 2026-01-01); `updatedAfter` is inclusive, `updatedBefore` is exclusive. Sort by `lastUpdated` (record last-modified time) in addition to other indexed fields, e.g. `sort=lastUpdated:desc`. Soft-deleted credentials are excluded by default; pass `includeDeleted=true` to include them.

📄️Record an externally-obtained verification result

Record a verification outcome produced OUTSIDE GMS (e.g. the NSW WWCC portal runner, which scrapes the OCG employer portal) using the same recording path as an in-JVM verify: it updates the credential's verification fields — deriving the canonical status from eligibility + statusDetail — AND writes a CredentialVerificationEvent (method ONE_OFF) so the outcome appears in the credential's verification history. No registry call is made and no review task is created; the caller supplies the already-mapped eligibility + statusDetail. Use /verify instead for credential types GMS can check itself.

📄️Transfer an owner reference on a single credential

Move the owner reference of one credential addressed by ID in the path. Clears the {@code from} slot and sets the {@code to} slot — when {@code from.type} and {@code to.type} differ this is the canonical applicant→worker re-anchoring; when they're the same type it's a swap (correcting a wrong id). The body's {@code credentialIds} field is ignored on this single-credential variant; use {@code POST /credentials/transfer} for the bulk shape.

📄️Link an additional owner to a single credential

Add an owner reference to one credential addressed by ID in the path. The credential entity is unchanged — we just register a new relationship. Idempotent: linking to the same owner twice is a no-op. Linking when that owner-type slot already holds a different ID returns 409 — use {@code POST /credentials/{id}/transfer} to replace. The body's {@code from} and {@code credentialIds} fields are ignored on this single-credential variant; use {@code POST /credentials/link} for the bulk shape.

📄️Transfer credentials between owners

Move owner references on one or more credentials from `from` to `to`. The credential entities are unchanged — we update the relationship pointers. If `credentialIds` is omitted, transfers ALL credentials currently owned by `from` (the canonical applicant→worker hire-correction flow). If provided, restricted to those IDs. Each item is atomic at the credential level. Best-effort batch — items that don't currently belong to `from` are reported as `skipped` with code OWNER_MISMATCH. Capped at 500 credentials per request.

📄️Link credentials to an additional owner

Add a new owner reference to one or more credentials. The credential entities themselves are unchanged — we just register a new relationship. If `credentialIds` is omitted, links every credential currently associated with `from` (the canonical applicant→worker hire flow). If provided, restricted to those IDs (which must currently be linked to `from`). Idempotent: items already linked to the target are reported as `noop`. A different ID in the target slot is reported as `skipped` with code ALREADY_LINKED — use /transfer to replace. Best-effort batch (failures don't block successes). Capped at 500 credentials per request.

📄️List supported credential types

Read-only catalogue of credential type codes the platform understands. Used by admin tooling and ATS integrators when authoring screening packages. The same list is published, with the aliases each code accepts and the spreadsheet-import equivalents, at https://docs.weareoho.com/api-guides/credential-types. Filter by `category` (SCREENING / GOVERNMENT_ID / LICENSE / CERTIFICATION) to scope the list. Codes are stable — drop a code only via a deprecation cycle. Codes retired from authoring are omitted by default but still accepted on write; pass `includeRetired=true` to list them, which is what the ingestion mapping wizards do so a recipe can keep targeting a retired code.