HollyHR Developer Docs
  • HollyHR
  • Sign in
  • Manage API keys
  • Start Here
  • Core API
  • AI and MCP
  • API Reference
  • Recipes
  • Resources
Overview5-minute quickstartSandbox and TTFCTypeScript SDKAuthentication
Start Here

Sandbox and TTFC

Use a disposable HollyHR tenant when testing integrations. HollyHR does not use one shared global sandbox credential: API keys are tenant-scoped, and the safer model is a seeded synthetic tenant per reviewer, partner, or trial.

This is the intended product pattern for in-app exploration too: learn inside a made-up company with realistic departments, people, managers, time off, documents, and notifications, then switch to a clean real org before using real company records.

Five-minute smoke

Set an API key with at least organisation:read, people:read, reference:read, and time_off:read:

TerminalCode
export HOLLYHR_API_BASE_URL="https://{workspace}.hollyhr.com/api/v1" export HOLLYHR_API_TOKEN="hhr_live_..." export HOLLYHR_MCP_URL="https://{workspace}.hollyhr.com/api/mcp" export HOLLYHR_MCP_TOKEN="$HOLLYHR_API_TOKEN"

Then run:

TerminalCode
pnpm developer:ttfc:smoke

The smoke checks:

  • GET /me
  • GET /people?limit=1, including a non-empty seeded-data assertion by default
  • GET /metadata
  • MCP protected-resource metadata
  • unauthenticated MCP WWW-Authenticate discovery
  • authenticated GET /api/mcp returning 405 Method Not Allowed
  • MCP SDK initialization, tools/list, and whoami
  • request IDs and rate-limit headers where the live endpoint returns them

The command fails if the full path takes longer than 300 seconds. Override that only when debugging a known network or client issue:

TerminalCode
HOLLYHR_TTFC_MAX_SECONDS=600 pnpm developer:ttfc:smoke

If a hosted smoke fails unexpectedly, check https://status.hollyhr.com before rotating credentials or reseeding the sandbox.

If you are deliberately testing an empty tenant, allow empty people results explicitly:

TerminalCode
HOLLYHR_TTFC_ALLOW_EMPTY=1 pnpm developer:ttfc:smoke

For directory, aggregator, or internal launch evidence, write the smoke result to JSON:

TerminalCode
HOLLYHR_TTFC_OUTPUT_PATH="./ttfc-evidence.json" pnpm developer:ttfc:smoke

For a complete directory-review bundle, pair this smoke output with Reviewer demo guide. The handoff manifest is the non-secret evidence file; the generated .env file is the secret credential bundle.

If the tenant is expected to advertise OAuth, make that expectation explicit so the smoke fails while authorization_servers is still empty:

TerminalCode
HOLLYHR_TTFC_EXPECT_OAUTH=1 \ HOLLYHR_TTFC_EXPECT_AUTHORIZATION_SERVER="https://<authkit-domain>" \ HOLLYHR_TTFC_OUTPUT_PATH="./ttfc-evidence.json" \ pnpm developer:ttfc:smoke

Scenario seed

For local and internal demo environments, HollyHR includes a beta-confidence scenario seed with synthetic UK SME data:

TerminalCode
pnpm seed:scenario:beta

For developer-platform demos, use the higher-level provisioning command. It reuses the scenario seed, returns endpoint evidence, and can mint a reveal-once API key for TTFC:

TerminalCode
HOLLYHR_DATABASE_TARGET_PROOF="postgresql://..." \ pnpm developer:demo:provision -- --create-api-key --output-json=./demo-tenant.json --output-env=./demo-tenant.env

When creating credentials for a production-hosted reviewer tenant, pull Vercel Production env first and derive HOLLYHR_DATABASE_TARGET_PROOF from that env file. Do not assume local .env points at the same Neon endpoint as the deployed app.

When --output-env is present, the JSON output redacts the API token and stores the token only in the mode-0600 env file. Use --reveal-token-in-json only for an interactive reveal-once flow where the JSON file itself is treated as a secret.

For a directory reviewer or sales/demo handoff, mint browser login links into the same secret env file:

TerminalCode
HOLLYHR_DATABASE_TARGET_PROOF="postgresql://..." \ HOLLYHR_ALLOW_DEVELOPER_DEMO_LOGIN_LINKS=1 \ pnpm developer:demo:provision -- \ --create-api-key \ --create-login-links \ --login-personas=hrAdmin,manager,directReport \ --output-json=./demo-tenant.json \ --output-env=./demo-tenant.env

The JSON evidence redacts login URLs by default. The env file contains single-use HOLLYHR_REVIEWER_LOGIN_* links plus the API/MCP token. Treat the env file as a secret, and refresh it before an external review window. The JSON output now includes a reviewer_handoff block with the concrete MCP endpoint, endpoint template, safe starter prompts, login expectations, and TTFC command to copy into the submission pack.

Then run the smoke against the generated env file:

TerminalCode
dotenv -e ./demo-tenant.env -- sh -c 'HOLLYHR_TTFC_OUTPUT_PATH=./ttfc-evidence.json pnpm developer:ttfc:smoke'

To reset the scenario, prove the target database first and explicitly acknowledge the destructive operation:

TerminalCode
pnpm db:target HOLLYHR_DATABASE_TARGET_PROOF="postgresql://..." \ HOLLYHR_ALLOW_DEVELOPER_DEMO_RESET=1 \ pnpm developer:demo:provision -- --reset --create-api-key --output-env=./demo-tenant.env

Never run the reset against a real customer tenant. The seed is intended for local, preview, disposable demo, and reviewer-demo environments.

The reviewer/demo tenant should include at least one person, one manager relationship, departments or teams, one public holiday set, and at least one time-off record so API, SDK, and MCP smoke runs prove real HR workflows rather than only authentication.

Use --include-write-scopes only for a tenant where writes are explicitly part of the demo. The key may include mcp:write, but MCP commit still fails unless the server-side write-mode gate is enabled and the host supports form elicitation.

Demo orgs versus real orgs

Do not seed fake people into a customer's real tenant. The safe onboarding model is a separate demo org with its own orgId, seeded from the same synthetic fixtures as the sandbox. A customer can explore that made-up company, then switch to their real empty org and import real employees. "Start fresh" deletes or abandons the demo org; it never promotes sample rows into production data.

For per-customer demo clones, pass a unique subdomain:

TerminalCode
HOLLYHR_DATABASE_TARGET_PROOF="postgresql://..." \ pnpm developer:demo:provision -- \ --subdomain=demo-acme \ --lifecycle=separate-demo-org \ --create-api-key \ --output-json=./demo-acme.json \ --output-env=./demo-acme.env

Non-default scenario subdomains get clone-specific synthetic email addresses, so multiple demo orgs can coexist without sharing users or reset scope.

Writes

REST writes require idempotency keys and, for conditional updates, ETags. MCP writes also require mcp:write, HOLLYHR_MCP_WRITE_MODE=enabled, and host form elicitation. Keep write tests in disposable tenants until your DPIA/DPO approval and tenant rollout plan are complete.

Last modified on June 23, 2026
5-minute quickstartTypeScript SDK
On this page
  • Five-minute smoke
  • Scenario seed
  • Demo orgs versus real orgs
  • Writes