OurTeamManagement API (0.0.1)

Download OpenAPI specification:

API-first multi-tenant HR service. The same API is used by the bundled dashboard, by master integrators that provision and operate many tenants, and by tenant-side machine integrations.

Authentication

All authenticated requests send a bearer token:

Authorization: Bearer <token>

Three credential types are accepted (each operation lists which subset it allows):

Scheme Token format Used by
masterApiKey mh_live_… (env MASTER_API_KEY) The operator's backend, cross-tenant
tenantApiKey mh_live_… (minted from dashboard) A tenant's own integrations
userSession Auth-service access token (JWT) The OurTeamManagement web app, on behalf of a user

Tenant scoping

Tenant-scoped endpoints resolve the tenant org per caller type:

  • masterApiKeyX-Tenant-Id header (UUID).
  • tenantApiKey → derived from the key; the header is ignored.
  • userSessionX-Org-Id header, validated against the user's memberships.

All data access is enforced by Postgres Row-Level Security — a missing or wrong tenant id never returns another tenant's data.

Audit attribution

Master callers can pass X-Actor: {"id":"u_123","email":"a@b","name":"Ada"} (JSON) to attribute the request to a specific user in the audit log (e.g. the human in the operator's product who triggered the call). User-session callers cannot set X-Actor (the actor is taken from the session to prevent spoofing).

Idempotency

Writes (POST / PATCH / DELETE) require an Idempotency-Key header (any unique string per logical operation, typically a UUID). Replays within 24h return the cached response. Reusing a key with a different request body returns 409 conflict.

Errors

Every error response uses a single envelope:

{ "error": { "code": "not_found", "message": "...", "details": {} } }

Stable codes: bad_request, tenant_required, unauthorized, forbidden, not_found, conflict, internal_error. New codes are additive — clients should switch on code and treat unknown codes as a generic failure.

Pagination

List endpoints use opaque cursors. Pass ?limit= (1–200, default 50) and ?cursor=<value> to page forward. The response is { items: [...], nextCursor: string | null }nextCursor: null means you're at the end. Cursors are stable across writes (deletions skip rather than fail).

Rate limits

Each masterApiKey and tenantApiKey is limited to 600 requests / minute, burst 60/sec. Limits are returned on every response:

  • RateLimit-Limit — total per window
  • RateLimit-Remaining — left in window
  • RateLimit-Reset — seconds until reset

Exceeding the limit returns 429 too_many_requests. Retry with exponential backoff using the Retry-After header.

Versioning

The major version is in the URL (/v1). Within a major version we only make additive changes (new fields, new operations, new error codes). Deprecations are announced at least 90 days in advance via the Deprecation and Sunset response headers (RFC 8594) and called out in apps/api/CHANGELOG.md.

Breaking changes only ever ship under a new major (/v2), and /v1 will run alongside it for at least 12 months.

Webhooks

Register a delivery URL via POST /v1/webhook-endpoints with the events you want — currently employee.created, employee.updated, employee.deleted, and (forthcoming) document.expiring. The signing secret is returned once at creation; use it to verify the Webhook-Signature header on every inbound delivery. The header value is t=<unix-seconds>,v1=<hex-hmac-sha256> of <t>.<raw-body>, the same format Stripe uses; the SDK exposes verifyWebhookSignature() for convenience.

Delivery semantics: each event is enqueued per subscribed endpoint with up to 8 attempts and exponential backoff (~1s → ~17h). The delivery audit log is queryable at /v1/webhook-deliveries, and any non-delivered row can be re-enqueued via /v1/webhook-deliveries/{id}/redeliver. Receivers must respond with any 2xx within 10s; non-2xx triggers a retry.

Quickstart

curl https://api.ourteammanagement.com/v1/employees \
  -H 'Authorization: Bearer $MASTER_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555' \
  -H 'Idempotency-Key: '"$(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{"email":"ada@acme.com","firstName":"Ada","lastName":"Lovelace","country":"us","startDate":"2026-06-01"}'

Employees

Employee records scoped to a tenant org.

List employees

Returns a cursor-paginated list of employees in the current tenant.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
query Parameters
status
string
Enum: "onboarding" "active" "on_leave" "terminated"
Example: status=active
managerId
string <uuid>
country
string
Enum: "us" "de"
cursor
string
limit
integer [ 1 .. 200 ]
Default: 50
Example: limit=50
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/employees?limit=50&status=active' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "nextCursor": null
}

Create employee

Creates a new employee in the current tenant.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
externalId
string [ 1 .. 200 ] characters
email
required
string <email>
firstName
required
string [ 1 .. 200 ] characters
lastName
required
string [ 1 .. 200 ] characters
preferredName
string <= 200 characters
jobTitle
string <= 200 characters
department
string <= 200 characters
managerId
string <uuid>
country
required
string
Enum: "us" "de"
startDate
required
string^\d{4}-\d{2}-\d{2}$
endDate
string^\d{4}-\d{2}-\d{2}$
status
string
Default: "onboarding"
Enum: "onboarding" "active" "on_leave" "terminated"

Responses

Request samples

Content type
application/json
{
  • "email": "ada@acme.com",
  • "firstName": "Ada",
  • "lastName": "Lovelace",
  • "country": "us",
  • "startDate": "2026-06-01",
  • "jobTitle": "Staff Engineer",
  • "department": "Engineering"
}

Response samples

Content type
application/json
{
  • "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "externalId": "emp_4271",
  • "email": "ada@acme.com",
  • "firstName": "Ada",
  • "lastName": "Lovelace",
  • "preferredName": null,
  • "jobTitle": "Staff Engineer",
  • "department": "Engineering",
  • "managerId": null,
  • "country": "us",
  • "startDate": "2026-06-01",
  • "endDate": null,
  • "status": "onboarding",
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Get employee

Returns a single employee by id, scoped to the current tenant.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/employees/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "externalId": "emp_4271",
  • "email": "ada@acme.com",
  • "firstName": "Ada",
  • "lastName": "Lovelace",
  • "preferredName": null,
  • "jobTitle": "Staff Engineer",
  • "department": "Engineering",
  • "managerId": null,
  • "country": "us",
  • "startDate": "2026-06-01",
  • "endDate": null,
  • "status": "onboarding",
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Update employee

Partially updates an employee. Only provided fields are changed.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
externalId
string [ 1 .. 200 ] characters
email
string <email>
firstName
string [ 1 .. 200 ] characters
lastName
string [ 1 .. 200 ] characters
preferredName
string <= 200 characters
jobTitle
string <= 200 characters
department
string <= 200 characters
managerId
string <uuid>
country
string
Enum: "us" "de"
startDate
string^\d{4}-\d{2}-\d{2}$
endDate
string^\d{4}-\d{2}-\d{2}$
status
string
Default: "onboarding"
Enum: "onboarding" "active" "on_leave" "terminated"

Responses

Request samples

Content type
application/json
{
  • "jobTitle": "Principal Engineer",
  • "status": "active"
}

Response samples

Content type
application/json
{
  • "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "externalId": "emp_4271",
  • "email": "ada@acme.com",
  • "firstName": "Ada",
  • "lastName": "Lovelace",
  • "preferredName": null,
  • "jobTitle": "Principal Engineer",
  • "department": "Engineering",
  • "managerId": null,
  • "country": "us",
  • "startDate": "2026-06-01",
  • "endDate": null,
  • "status": "active",
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Delete employee (GDPR Art. 17)

Soft-deletes an employee and anonymizes PII in place. A scheduled job performs hard erasure after retention deadlines pass.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Responses

Request samples

curl -X DELETE 'https://api.ourteammanagement.com/v1/employees/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555' \
  -H 'Idempotency-Key: '"$(uuidgen)"

Response samples

Content type
application/json
{
  • "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  • "deletedAt": "2026-05-04T12:00:00.000Z"
}

Export employee data (GDPR Art. 15)

Returns the full employee record. A follow-up will also bundle contracts and documents into a zip.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/employees/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/export' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "employee": {
    },
  • "exportedAt": "2026-05-04T12:00:00.000Z"
}

Orgs

Tenant orgs. Root master, partner, and end-user creation; root master + partner read (partners see only their own orgs).

List orgs (root master + partner)

Lists tenant orgs. Root master sees every org on the deployment. Partner callers see only the orgs they themselves provisioned (RLS-isolated from every other partner).

Authorizations:
masterApiKeypartnerApiKey
query Parameters
cursor
string
limit
integer [ 1 .. 200 ]
Default: 50
Example: limit=50
header Parameters
x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/orgs?limit=50' \
  -H 'Authorization: Bearer $MYHR_API_KEY'

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "nextCursor": null
}

Create org

Provisions a new tenant org. Root master and partner callers provision on behalf of a tenant (partner-created orgs are tagged with the partner id). End-user callers create their own org and become owner.

Authorizations:
masterApiKeypartnerApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
name
required
string [ 1 .. 200 ] characters
region
string
Default: "eu"
Enum: "eu" "us"

Responses

Request samples

Content type
application/json
{
  • "name": "Acme Inc",
  • "region": "eu"
}

Response samples

Content type
application/json
{
  • "id": "11111111-2222-3333-4444-555555555555",
  • "name": "Acme Inc",
  • "region": "eu",
  • "status": "active",
  • "partnerId": null,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Get org (root master + partner)

Returns a single tenant org by id. Root master sees every org; partners see only the orgs they themselves provisioned (404 otherwise).

Authorizations:
masterApiKeypartnerApiKey
path Parameters
id
required
string <uuid>
Example: 11111111-2222-3333-4444-555555555555
header Parameters
x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/orgs/11111111-2222-3333-4444-555555555555' \
  -H 'Authorization: Bearer $MYHR_API_KEY'

Response samples

Content type
application/json
{
  • "id": "11111111-2222-3333-4444-555555555555",
  • "name": "Acme Inc",
  • "region": "eu",
  • "status": "active",
  • "partnerId": null,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Update org (root master + partner)

Partially updates a tenant org. Root master can update any org; partners can update only orgs they themselves provisioned.

Authorizations:
masterApiKeypartnerApiKey
path Parameters
id
required
string <uuid>
Example: 11111111-2222-3333-4444-555555555555
header Parameters
idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Request Body schema: application/json
required
name
string [ 1 .. 200 ] characters
region
string
Default: "eu"
Enum: "eu" "us"
status
string
Enum: "active" "suspended" "deleted"

Responses

Request samples

Content type
application/json
{
  • "name": "Acme Holdings GmbH"
}

Response samples

Content type
application/json
{
  • "id": "11111111-2222-3333-4444-555555555555",
  • "name": "Acme Holdings GmbH",
  • "region": "eu",
  • "status": "active",
  • "partnerId": null,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Members

Per-org memberships and roles.

List org members

Returns all active members of the resolved org with their role and identity.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/members' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "items": [
    ]
}

Invitations

Invite-by-email flow for adding members.

Invite someone to the org

Creates an invitation record and returns the acceptance URL plus the plaintext token. Owner/admin only for user callers; master + tenant_key callers bypass the role check.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
email
required
string <email>
role
required
string
Enum: "owner" "admin" "manager" "member"

Responses

Request samples

Content type
application/json
{
  • "email": "newhire@acme.com",
  • "role": "admin"
}

Response samples

Content type
application/json
{}

List pending invitations

Returns invitations for the resolved org that haven't been accepted or revoked.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/invitations' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "items": [
    ]
}

Accept an invitation

Exchanges an invitation token for a membership. The caller's email must match the email on the invitation.

Authorizations:
userSession
header Parameters
idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
token
required
string non-empty

Responses

Request samples

Content type
application/json
{
  • "token": "inv_4f3c1aa9e2b14d8e9c0f7d6b5e2a1c8d"
}

Response samples

Content type
application/json
{
  • "id": "cccccccc-dddd-eeee-ffff-aaaaaaaaaaaa",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "userId": "u_01HXYZUSER00000000000000",
  • "role": "admin",
  • "createdAt": "2026-05-04T12:00:00.000Z"
}

ApiKeys

Tenant-scoped API keys minted from the dashboard.

Mint a tenant-scoped API key

Creates a new tenant-scoped API key. The plaintext value is returned once and never again — store it immediately.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
name
required
string [ 1 .. 200 ] characters

Responses

Request samples

Content type
application/json
{
  • "name": "Production server (read+write)"
}

Response samples

Content type
application/json
{
  • "id": "bbbbbbbb-cccc-dddd-eeee-ffffffffffff",
  • "name": "Production server (read+write)",
  • "prefix": "mh_live_4f3c1aa9e2b1",
  • "scope": "tenant",
  • "lastUsedAt": null,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "key": "mh_live_4f3c1aa9e2b14d8e9c0f7d6b5e2a1c8d"
}

List API keys for this org

Returns metadata for every tenant-scoped key minted for this org. Plaintext keys are never returned.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/api-keys' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "items": [
    ]
}

Me

The currently authenticated end user.

Get the authenticated user

Returns the currently authenticated end user. User callers only.

Authorizations:
userSession

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/me' \
  -H 'Authorization: Bearer $MYHR_API_KEY'

Response samples

Content type
application/json
{
  • "id": "u_01HXYZUSER00000000000000",
  • "email": "ada@acme.com",
  • "name": "Ada Lovelace",
  • "isSuperAdmin": false,
  • "createdAt": "2026-05-04T12:00:00.000Z"
}

List orgs the user belongs to

Returns one row per org the caller has a membership in, denormalised with the org and the caller's role.

Authorizations:
userSession

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/me/orgs' \
  -H 'Authorization: Bearer $MYHR_API_KEY'

Response samples

Content type
application/json
{
  • "items": [
    ]
}

Webhooks

Webhook endpoint management + delivery audit. Manage where OurTeamManagement delivers events with /v1/webhook-endpoints/*; inspect or replay attempts with /v1/webhook-deliveries/*. The event payloads OurTeamManagement actually POSTs are documented under the Webhooks section.

Fired when an employee is created Webhook

Emitted on every successful POST /v1/employees. The payload is the same shape returned by the create endpoint (minus encrypted-at-rest fields).

Request Body schema: application/json
required
id
required
string <uuid>

Unique event id. Use as the deduplication key.

type
required
string
Value: "employee.created"

Event type. Always present; safe to switch on.

createdAt
required
string <date-time>
orgId
required
string <uuid>

Tenant org the event applies to.

data
required
object

Responses

Request samples

Content type
application/json
{
  • "id": "ev_01HXYZ0000000000000001",
  • "type": "employee.created",
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "data": {
    }
}

Fired when an employee is updated Webhook

Emitted after a successful PATCH /v1/employees/{id} whenever any persisted field changes. Re-emitted only if the post-write state differs.

Request Body schema: application/json
required
id
required
string <uuid>

Unique event id. Use as the deduplication key.

type
required
string
Value: "employee.updated"

Event type. Always present; safe to switch on.

createdAt
required
string <date-time>
orgId
required
string <uuid>

Tenant org the event applies to.

data
required
object

Responses

Request samples

Content type
application/json
{
  • "id": "ev_01HXYZ0000000000000001",
  • "type": "employee.updated",
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "data": {
    }
}

Fired when an employee is deleted (GDPR Art. 17) Webhook

Emitted when an employee is soft-deleted. PII has already been redacted at this point — only id, orgId, and deletedAt are guaranteed.

Request Body schema: application/json
required
id
required
string <uuid>

Unique event id. Use as the deduplication key.

type
required
string
Value: "employee.deleted"

Event type. Always present; safe to switch on.

createdAt
required
string <date-time>
orgId
required
string <uuid>

Tenant org the event applies to.

data
required
object

Responses

Request samples

Content type
application/json
{
  • "id": "ev_01HXYZ0000000000000001",
  • "type": "employee.deleted",
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "data": {
    }
}

Fired ahead of a document's expiry Webhook

Emitted at 30 / 14 / 7 / 1 days before document.expiresAt so the integrator can notify the employee or HR. Each window fires exactly once per document.

Request Body schema: application/json
required
id
required
string <uuid>

Unique event id. Use as the deduplication key.

type
required
string
Value: "document.expiring"

Event type. Always present; safe to switch on.

createdAt
required
string <date-time>
orgId
required
string <uuid>

Tenant org the event applies to.

data
required
object

Responses

Request samples

Content type
application/json
{
  • "id": "ev_01HXYZ0000000000000001",
  • "type": "document.expiring",
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "data": {
    }
}

Register a webhook endpoint

Register a URL to receive event deliveries. The signing secret is returned once at creation; store it immediately — every delivery is signed with it via HMAC-SHA256 in the Webhook-Signature header. Subsequent reads return the endpoint metadata only.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
url
required
string <uri> ^https:\/\/
events
required
Array of strings non-empty
Items Enum: "employee.created" "employee.updated" "employee.deleted" "document.expiring"

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "id": "eeeeeeee-aaaa-bbbb-cccc-dddddddddddd",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "events": [
    ],
  • "isActive": true,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z",
  • "secret": "whsec_4f3c1aa9e2b14d8e9c0f7d6b5e2a1c8d4f3c1aa9e2b14d8e9c0f7d6b5e2a1c8d"
}

List webhook endpoints for this org

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/webhook-endpoints' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "items": [
    ]
}

Get a webhook endpoint

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: eeeeeeee-aaaa-bbbb-cccc-dddddddddddd
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/webhook-endpoints/eeeeeeee-aaaa-bbbb-cccc-dddddddddddd' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "id": "eeeeeeee-aaaa-bbbb-cccc-dddddddddddd",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "events": [
    ],
  • "isActive": true,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Update a webhook endpoint

Update the URL, subscribed events, or active state. The signing secret is not changed — see rotateWebhookEndpointSecret to rotate.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: eeeeeeee-aaaa-bbbb-cccc-dddddddddddd
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Request Body schema: application/json
required
url
string <uri> ^https:\/\/
events
Array of strings non-empty
Items Enum: "employee.created" "employee.updated" "employee.deleted" "document.expiring"
isActive
boolean

Responses

Request samples

Content type
application/json
{
  • "events": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "eeeeeeee-aaaa-bbbb-cccc-dddddddddddd",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "events": [
    ],
  • "isActive": true,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z"
}

Delete a webhook endpoint

Removes the endpoint and cascades pending deliveries. Returns 204 with no body. Existing WebhookDelivery rows remain for audit.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: eeeeeeee-aaaa-bbbb-cccc-dddddddddddd
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Responses

Request samples

curl -X DELETE 'https://api.ourteammanagement.com/v1/webhook-endpoints/eeeeeeee-aaaa-bbbb-cccc-dddddddddddd' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555' \
  -H 'Idempotency-Key: '"$(uuidgen)"

Response samples

Content type
application/json
{
  • "error": {
    }
}

Rotate the signing secret for an endpoint

Mints a fresh signing secret and returns it once. The previous secret stops working immediately — coordinate the cutover with the receiver before calling.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: eeeeeeee-aaaa-bbbb-cccc-dddddddddddd
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Responses

Request samples

curl -X POST 'https://api.ourteammanagement.com/v1/webhook-endpoints/eeeeeeee-aaaa-bbbb-cccc-dddddddddddd/rotate-secret' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555' \
  -H 'Idempotency-Key: '"$(uuidgen)"

Response samples

Content type
application/json
{
  • "id": "eeeeeeee-aaaa-bbbb-cccc-dddddddddddd",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "events": [
    ],
  • "isActive": true,
  • "createdAt": "2026-05-04T12:00:00.000Z",
  • "updatedAt": "2026-05-04T12:00:00.000Z",
  • "secret": "whsec_4f3c1aa9e2b14d8e9c0f7d6b5e2a1c8d4f3c1aa9e2b14d8e9c0f7d6b5e2a1c8d"
}

List webhook deliveries

Returns the recent deliveries for this org, newest first. Useful for diagnostics — every attempt is recorded with the response code, body (truncated to 4 KiB), and any error.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
query Parameters
endpointId
string <uuid>
eventType
string
Enum: "employee.created" "employee.updated" "employee.deleted" "document.expiring"
status
string
Enum: "pending" "in_progress" "delivered" "failed_retrying" "failed_permanent"
Example: status=delivered
cursor
string
limit
integer [ 1 .. 200 ]
Default: 50
Example: limit=50
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/webhook-deliveries?limit=50&status=delivered' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "nextCursor": null
}

Get a webhook delivery

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/webhook-deliveries/ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555'

Response samples

Content type
application/json
{
  • "id": "ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "endpointId": "eeeeeeee-aaaa-bbbb-cccc-dddddddddddd",
  • "eventId": "11112222-3333-4444-5555-666677778888",
  • "eventType": "employee.created",
  • "status": "delivered",
  • "attempts": 1,
  • "maxAttempts": 8,
  • "lastResponseCode": 200,
  • "lastResponseBody": "ok",
  • "lastError": null,
  • "lastAttemptAt": "2026-05-04T12:00:00.000Z",
  • "nextAttemptAt": null,
  • "deliveredAt": "2026-05-04T12:00:00.000Z",
  • "createdAt": "2026-05-04T12:00:00.000Z"
}

Re-enqueue a delivery

Resets the delivery's attempt counter to zero and enqueues a fresh job. The same eventId is used so consumers can deduplicate. Already-delivered rows are not redelivered (returns 409).

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
path Parameters
id
required
string <uuid>
Example: ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb
header Parameters
x-tenant-id
string <uuid>

Tenant org id — required for root master and partner callers, ignored for tenant-key + user callers.

x-org-id
string <uuid>

Tenant org id — required for end-user (auth-service) callers.

x-actor
string

Optional JSON { id?, email?, name? } attributing this request to a specific user (in the integrator's product) for the audit log. Honored for root master and partner callers; ignored for tenant-key and user-session callers.

idempotency-key
required
string [ 1 .. 200 ] characters

Required on all writes (POST/PATCH/DELETE). Replays return the cached response. Reusing a key with a different body returns 409.

Responses

Request samples

curl -X POST 'https://api.ourteammanagement.com/v1/webhook-deliveries/ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb/redeliver' \
  -H 'Authorization: Bearer $MYHR_API_KEY' \
  -H 'X-Tenant-Id: 11111111-2222-3333-4444-555555555555' \
  -H 'Idempotency-Key: '"$(uuidgen)"

Response samples

Content type
application/json
{
  • "id": "ffffffff-eeee-dddd-cccc-bbbbbbbbbbbb",
  • "orgId": "11111111-2222-3333-4444-555555555555",
  • "endpointId": "eeeeeeee-aaaa-bbbb-cccc-dddddddddddd",
  • "eventId": "11112222-3333-4444-5555-666677778888",
  • "eventType": "employee.created",
  • "status": "pending",
  • "attempts": 0,
  • "maxAttempts": 8,
  • "lastResponseCode": 200,
  • "lastResponseBody": "ok",
  • "lastError": null,
  • "lastAttemptAt": "2026-05-04T12:00:00.000Z",
  • "nextAttemptAt": null,
  • "deliveredAt": null,
  • "createdAt": "2026-05-04T12:00:00.000Z"
}

SuperAdmin

Cross-tenant ops for OurTeamManagement staff (is_super_admin users).

List all orgs (super admin)

Cross-tenant org list for OurTeamManagement ops humans (is_super_admin = true). Master + tenant-key callers are rejected — they have their own paths.

Authorizations:
masterApiKeypartnerApiKeytenantApiKeyuserSession
query Parameters
cursor
string
limit
integer [ 1 .. 200 ]
Default: 50
Example: limit=50

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/v1/superadmin/orgs?limit=50' \
  -H 'Authorization: Bearer $MYHR_API_KEY'

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "nextCursor": null
}

Health

Liveness and service metadata.

Liveness + DB readiness probe

Returns ok when the database is reachable.

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/healthz' \
  -H 'Authorization: Bearer $MYHR_API_KEY'

Response samples

Content type
application/json
{
  • "ok": true
}

Service banner

Responses

Request samples

curl -X GET 'https://api.ourteammanagement.com/' \
  -H 'Authorization: Bearer $MYHR_API_KEY'

Response samples

Content type
application/json
{}