The LiteHQ REST API accepts three credential shapes: bearer tokens (the default), scoped keys (for narrow integrations), and OAuth callbacks (for third-party apps acting on behalf of an operator). This guide covers all three, plus rotation and revocation.
All endpoints require HTTPS. Plain HTTP is rejected at the edge. All tokens are sent in the Authorization header, never in query strings — we strip them from logs regardless.
Demo tokens only. Every token in this guide is fake. Generate real keys in your dashboard at /settings/api-keys.
Section 1
Bearer tokens
The default · workspace-wide access · 90-day lifetime
Bearer tokens are workspace-scoped — they can read and write anything the issuing user could. They're ideal for server-to-server jobs you control end-to-end (cron jobs, ETL, internal dashboards). They're a bad fit for anything that runs in a browser or on a customer's machine.
Creating a token
- In your operator dashboard, go to Settings → API keys.
- Click + New token. Give it a name (“Nightly export”) and an expiry (default 90 days, max 365).
- Copy the token once— we don't store the plaintext. Lose it and you rotate.
Calling the API
# List bookings for the current week
curl https://api.litehq.com/v1/bookings \
-H 'Authorization: Bearer lhq_demo_71c3b6f4a8e2d9c5b7f1e3a8d6c2b9e5' \
-H 'Content-Type: application/json' \
--data-urlencode 'start_at[gte]=2026-05-22T00:00:00Z' \
--data-urlencode 'start_at[lt]=2026-05-29T00:00:00Z'# Create a booking on behalf of a member
curl https://api.litehq.com/v1/bookings \
-X POST \
-H 'Authorization: Bearer lhq_demo_71c3b6f4a8e2d9c5b7f1e3a8d6c2b9e5' \
-H 'Content-Type: application/json' \
-d '{
"resource_id": "res_boardroom_demo",
"member_id": "mem_demo_anya",
"start_at": "2026-05-23T10:00:00Z",
"duration_minutes": 60
}'lhq_ prefixes and we email the workspace owner if one shows up in a public push.Section 2
Scoped keys
Narrow surface · per-resource permissions · safer for shared tools
A scoped key is a bearer token with a narrower permission set. You define the surface at creation: which resources, which actions (read/write/delete), which IP allowlist. Once set, scopes can't be widened — only narrowed or revoked.
When to use scoped over bearer
- A third-party tool needs read-only access to your bookings (e.g. an analytics dashboard).
- A teammate wants to script something without holding workspace-wide write access.
- A vendor integration needs to write only to its own scope (e.g. door access webhook).
Creating a scoped key
POST /v1/api-keys
{
"name": "Analytics readonly",
"scope": {
"resources": ["bookings", "members", "invoices"],
"actions": ["read"],
"ip_allowlist": ["52.18.0.0/16"]
},
"expires_at": "2026-08-22T00:00:00Z"
}The response includes the plaintext token (shown once) and a key fingerprint you'll see in audit logs.
{
"id": "key_demo_3f8a2c1b9d4e7a6f",
"token": "lhq_scoped_demo_9b7f3c1a4e8d2b6f5a9c3e7d1b8f4a2c",
"fingerprint": "lhq_scoped_…4a2c",
"created_at": "2026-05-22T08:14:00Z",
"expires_at": "2026-08-22T00:00:00Z"
}Section 3
OAuth callback (for integrations)
3-legged · access + refresh tokens · 30-day access lifetime
OAuth is the right shape when a third-party app acts on behalf of an operator without ever seeing their dashboard password. The flow is standard OAuth 2.0 + PKCE — if you can integrate with Stripe or Xero, you can integrate with us.
The 3-leg flow
- Your app redirects the operator to
https://api.litehq.com/oauth/authorizewithclient_id,redirect_uri,scope,state, and a PKCEcode_challenge. - Operator approves. We redirect back with
?code=…&state=…. - Your app POSTs the
code+code_verifierto/oauth/tokenand receivesaccess_token+refresh_token.
curl https://api.litehq.com/oauth/token \
-X POST \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code' \
-d 'code=demo_code_3f8a2c1b9d4e7a6f' \
-d 'code_verifier=demo_verifier_9b7f3c1a4e8d2b6f5a9c3e7d1b8f4a2c' \
-d 'client_id=demo_client_litehq_partner' \
-d 'redirect_uri=https%3A%2F%2Fyour-app.example.com%2Foauth%2Fcallback'Section 4
Token rotation
Zero-downtime · grace-window overlap · monitored via audit log
Every credential type supports zero-downtime rotation. The pattern is: issue the new token, deploy it everywhere, then revoke the old one. We give you a grace window so the old + new tokens both work briefly.
The rotation recipe
- Create a new token via the dashboard or
POST /v1/api-keys/rotate. The new token is active immediately. - Deploy the new token to every consumer. Old + new both work for the next 7 days (configurable from 1 hour to 30 days).
- Verify via audit log that the old token is no longer being hit. Use the
last_used_atfield on each key. - Revoke the old token.
DELETE /v1/api-keys/{key_id}.
# Rotate, keeping the old key alive for 7 days
curl https://api.litehq.com/v1/api-keys/key_demo_3f8a2c1b9d4e7a6f/rotate \
-X POST \
-H 'Authorization: Bearer lhq_demo_71c3b6f4a8e2d9c5b7f1e3a8d6c2b9e5' \
-d 'grace_window_days=7'
# Response includes the new token + the rotation_id you'll need for the
# subsequent DELETE call.Section 5
Revocation
Immediate · idempotent · audit-logged
Revocation is instant. Once a key is revoked, every cached copy of it in our edge layer is invalidated within ~2 seconds. The key cannot be un-revoked — if you revoked by mistake, create a new one.
How to revoke
- UI. Dashboard → Settings → API keys → click the trash icon.
- API.
DELETE /v1/api-keys/{key_id}. - Emergency. If you suspect a leak, hit
POST /v1/api-keys/revoke-all— this is the workspace-wide nuclear option. Everything-everywhere stops working until you re-issue.
changed_by_profile_idof whoever issued the revoke. Useful when debugging “why did my cron break at 03:14 last night.”Reference
Common errors
Five status codes you'll see most
Every error response includes a JSON body with error.code, error.message, and a request_idyou can quote in support. The five codes below cover ~95% of what you'll see in production.
| Code | What | Cause | Fix |
|---|---|---|---|
| Missing or malformed token | No Authorization header, or the header doesn't start with 'Bearer '. | Verify the header. Test with `curl -H 'Authorization: Bearer …'`. | |
| Scope insufficient | Scoped key doesn't include the resource or action you're calling. | Either widen scope (create a new key — you can't widen an existing one) or use a bearer token. | |
| Rate limited | Exceeded 600 req/min per token. Returns Retry-After header. | Back off + retry, or batch via the bulk endpoints (10x cheaper). | |
| Server error | Our problem. Includes an x-request-id header. | Retry with exponential backoff. If persistent, email support@litehq.com with the request id. | |
| Service unavailable (maintenance) | Scheduled maintenance window. Announced 48 hours in advance. | Subscribe to status.litehq.com for the alert; retry after the window. |
- Missing or malformed token
Cause. No Authorization header, or the header doesn't start with 'Bearer '.
Fix. Verify the header. Test with `curl -H 'Authorization: Bearer …'`.
- Scope insufficient
Cause. Scoped key doesn't include the resource or action you're calling.
Fix. Either widen scope (create a new key — you can't widen an existing one) or use a bearer token.
- Rate limited
Cause. Exceeded 600 req/min per token. Returns Retry-After header.
Fix. Back off + retry, or batch via the bulk endpoints (10x cheaper).
- Server error
Cause. Our problem. Includes an x-request-id header.
Fix. Retry with exponential backoff. If persistent, email support@litehq.com with the request id.
- Service unavailable (maintenance)
Cause. Scheduled maintenance window. Announced 48 hours in advance.
Fix. Subscribe to status.litehq.com for the alert; retry after the window.
Next steps