Skip to content

Authentication API

16 endpoints, generated from packages/core/openapi/v1.snapshot.json (OpenAPI 3.1.0, contract version 1.0). Conventions for lists, errors, money and authentication are on the API conventions page.

GET/api/v1/auth/demo/personas

Demo personas (demo mode only)

Access
Public (no sign-in)

Responses

200 Success. object

  • itemsarray of objectrequired
    • membershipIdstring (uuid)required
    • displayNamestringrequired
    • emailstringrequired
    • rolesarray of stringrequired
  • 404 not_found

POST/api/v1/auth/demo/sign-in

Sign in as a demo persona (demo mode only)

Access
Public (no sign-in)

Request body

application/json, object, required

  • membershipIdstring (uuid)required

Responses

204 No content.

  • 400 validation_failed
  • 404 not_found

POST/api/v1/auth/invitations/accept

Accept an invitation with a password

Sets the password (or confirms the existing one for people already on Crow HR), activates the membership and signs in.

Access
Public (no sign-in)

Request body

application/json, object, required

  • tokenstringrequired

    min length 20 · max length 200

  • passwordstringrequired

    min length 1 · max length 1024

  • displayNamestring

    min length 1 · max length 120

  • codestring

    max length 20

Responses

200 Success. object

  • orgSlugstring | nullrequired
  • 400 validation_failed
  • 401 invalid_credentials, invalid_mfa_code
  • 403 password_sign_in_disabled
  • 409 conflict

POST/api/v1/auth/invitations/inspect

Look up an invitation link

Access
Public (no sign-in)

Request body

application/json, object, required

  • tokenstringrequired

    min length 20 · max length 200

Responses

200 Success. object

  • statusenumrequired

    one of "valid", "expired", "used", "revoked", "unknown"

  • organisationobject or nullrequired
    • namestringrequired
    • slugstring | nullrequired
  • emailstring | nullrequired
  • displayNamestring | nullrequired
  • existingAccountbooleanrequired
  • mfaRequiredbooleanrequired
  • passwordAllowedbooleanrequired
  • providersarray of objectrequired
    • idstring (uuid)required
    • kindstringrequired
    • displayNamestringrequired
  • 400 validation_failed

GET/api/v1/auth/methods

Sign-in methods an organisation has enabled

Public. Without `org`, resolves the only organisation of a single-organisation install.

Access
Public (no sign-in)

Parameters

NameInTypeRequired
orgquerystringno

Responses

200 Success. object

  • orgSlugRequiredbooleanrequired
  • organisationobject or nullrequired
    • namestringrequired
    • slugstring | nullrequired
  • passwordobjectrequired
    • enabledbooleanrequired
  • providersarray of objectrequired
    • idstring (uuid)required
    • kindenumrequired

      one of "google", "entra", "singpass", "oidc"

    • displayNamestringrequired
    • allowedDomainsarray of stringrequired
  • demoModebooleanrequired
  • singpassLogoUrlstring | nullrequired
  • 400 validation_failed
  • 404 not_found

POST/api/v1/auth/mfa/verify

Complete a sign-in with a TOTP or recovery code

Completes a password sign-in (token from `/auth/sign-in`) or an SSO sign-in that needs Crow HR's TOTP (token in the `crowhr_mfa` cookie set by the SSO callback; omit `mfaToken`). Wrong codes count toward the account's MFA lock; requests are also limited per network.

Access
Public (no sign-in)

Request body

application/json, object, required

  • mfaTokenstring

    min length 1 · max length 200

  • codestringrequired

    min length 6 · max length 20

Responses

200 Success. object

  • mfaRequiredbooleanrequired
  • mfaTokenstring
  • mfaExpiresAtstring (date-time)
  • redirectTostring
  • 400 validation_failed
  • 401 invalid_mfa_code
  • 429 rate_limited

GET/api/v1/auth/oidc/{providerId}/callback

Identity provider callback

The only cookie-authenticated GET with side effects; protected by `state`. Validates the ID token (signature, issuer, audience, expiry, nonce) and the provider restrictions, links or matches the identity, then signs in.

Access
Public (no sign-in)

Parameters

NameInTypeRequired
providerIdpathstring (uuid)yes
statequerystringno

Responses

302 Redirect into the app, or back to the sign-in page with an error.

  • 400 validation_failed
  • 403 forbidden, reauth_required
  • 404 not_found

GET/api/v1/auth/oidc/{providerId}/jwks.json

Relying-party public keys for a provider (Singpass)

Access
Public (no sign-in)

Parameters

NameInTypeRequired
providerIdpathstring (uuid)yes

Responses

200 Success. object

  • keysarray of objectrequired
    • ktystringrequired
    • kidstring
  • 400 validation_failed
  • 404 not_found

GET/api/v1/auth/oidc/{providerId}/start

Start single sign-on with a provider

Redirects to the identity provider (authorization code + PKCE S256, state and nonce kept server-side for 10 minutes). `purpose=test` is an owner's test sign-in; `purpose=link` links the provider to the signed-in user. `purpose=demo` (only on a server configured with `DEMO_SINGPASS_PROVIDER_ID` and `DEMO_SINGPASS_RETURN_URL`, only for that Singpass provider) is the in-browser demo's Singpass round trip: nobody is signed in or linked, and the browser returns to the demo with `singpass=ok` or `singpass=failed`.

Access
Public (no sign-in)

Parameters

NameInTypeRequired
providerIdpathstring (uuid)yes
purposequeryenumno
invitationquerystringno
nativequerystring (uuid)no

Responses

302 Redirect to the identity provider.

  • 400 validation_failed
  • 403 disabled_in_demo, forbidden, reauth_required
  • 404 not_found

POST/api/v1/auth/password-reset/complete

Set a new password from a reset link

Single use. Revokes every session and device of the user.

Access
Public (no sign-in)

Request body

application/json, object, required

  • tokenstringrequired

    min length 20 · max length 200

  • passwordstringrequired

    max length 1024

Responses

200 Success. object

  • orgSlugstring | nullrequired
  • 400 validation_failed
  • 409 conflict

POST/api/v1/auth/password-reset/inspect

Check a password reset link before showing the form

Access
Public (no sign-in)

Request body

application/json, object, required

  • tokenstringrequired

    min length 20 · max length 200

Responses

200 Success. object

  • statusenumrequired

    one of "valid", "expired_or_used"

  • orgSlugstring | nullrequired
  • 400 validation_failed

POST/api/v1/auth/password-reset/request

Request a password reset email

Always answers 202, whether or not the email belongs to a member.

Access
Public (no sign-in)

Request body

application/json, object, required

  • orgstringrequired

    min length 1

  • emailstringrequired

    max length 254

Responses

202 Success. object

  • acceptedtruerequired
  • emailConfiguredbooleanrequired
  • 400 validation_failed

POST/api/v1/auth/reauth

Confirm it's you before a sensitive action

Password sessions: password, plus a TOTP or recovery code when MFA is enrolled. SSO sessions re-authenticate by an SSO round-trip instead.

Access
Any signed-in member (own data only)

Request body

application/json, object, required

  • passwordstringrequired

    min length 1 · max length 1024

  • codestring

    max length 20

Responses

200 Success. object

  • authenticatedAtstring (date-time)required
  • 400 validation_failed
  • 401 invalid_credentials, invalid_mfa_code, session_expired, session_revoked, unauthenticated
  • 403 csrf_rejected

POST/api/v1/auth/sign-in

Sign in with email and password

Every failure (unknown email, wrong password, suspended, locked) answers the same 401 invalid_credentials. When MFA is enrolled the response carries a pending-sign-in token instead of a session.

Access
Public (no sign-in)

Request body

application/json, object, required

  • orgstringrequired

    min length 1

  • emailstringrequired

    max length 254

  • passwordstringrequired

    min length 1 · max length 1024

  • nativeRequestIdstring (uuid)

Responses

200 Success. object

  • mfaRequiredbooleanrequired
  • mfaTokenstring
  • mfaExpiresAtstring (date-time)
  • redirectTostring
  • 400 validation_failed
  • 401 invalid_credentials
  • 403 password_sign_in_disabled
  • 429 rate_limited

POST/api/v1/auth/sign-out

Sign out of this browser session

Access
Public (no sign-in)

Responses

204 No content.

POST/api/v1/auth/switch-organisation

Switch the session to another organisation you belong to

Issues a new session token (rotation) scoped to the target organisation.

Access
Any signed-in member (own data only)

Request body

application/json, object, required

  • orgstringrequired

    min length 1 · max length 100

Responses

200 Success. object

  • orgSlugstringrequired
  • 400 validation_failed
  • 401 session_expired, session_revoked, unauthenticated
  • 403 csrf_rejected, mfa_enrolment_required
  • 404 not_found