Service API Authentication
Issue an app key and secret, scope it to the right permissions, and protect it with a rate limit and IP allowlist.
This guide begins with Creating an app, continues through Permissions (scopes), Rotating and revoking, Rate limit and IP allowlist, and finishes with Authentication error codes.
Creating an app
Only tenant admins (owner, admin, manager, super_admin) can create apps.
- Open Dashboard → Security & Apps → Applications.
- Click New App, give it a descriptive name (e.g. "Booking Bot Production").
- Pick the permissions the integration needs (least-privilege; see the next section).
- Hit Create app. The plaintext app key and app secret are displayed once.
Each request must carry both headers:
X-Links-App-Key: lk_app_...
X-Links-App-Secret: lk_sec_...
Permissions (scopes)
Apps are scoped per-permission. Pick only what the integration needs.
| Scope | Allows |
|---|---|
spaces:read | List active spaces with working hours and location metadata. |
spaces.availability:read | GET available time slots for a space and date. |
spaces.reservations:request | POST a reservation request that lands as pending until a tenant admin approves. |
Missing scope returns 403 SCOPE_MISSING. You can edit the scope set later from Applications → Manage → Permissions without rotating the secret.
Rotating and revoking
Rotation issues a fresh app key and secret while keeping the previous one alive for a grace window so you can deploy without downtime.
- Applications → [your app] → Rotate. Default grace is 60 minutes.
- Copy the new key and secret. Roll them into your secret store.
- Wait until your fleet picks the new credentials up, or click revoke now on the previous secret to end the grace early.
To kill an app entirely, use Revoke. All secrets are marked revoked immediately and any incoming request returns 401 SERVICE_AUTH_REVOKED.
Rate limit and IP allowlist
Each app has a per-minute rate limit (default 60 req/min). Once exceeded the API returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{ "error": { "code": "SERVICE_RATE_LIMITED" } }
Edit the rate limit from Applications → Manage → Settings.
The same Settings tab exposes an IP allowlist (one IP or CIDR per line). When set, only matching client IPs are accepted. Off-list requests return 403 SERVICE_IP_NOT_ALLOWED.
Authentication error codes
Authentication failures come back with a stable error.code so you can branch on them:
| HTTP | error.code | Meaning |
|---|---|---|
| 401 | SERVICE_CREDENTIALS_REQUIRED | One of the headers is missing. |
| 401 | SERVICE_AUTH_INVALID | App key not found. |
| 401 | SERVICE_AUTH_SECRET_MISMATCH | App key valid, secret is wrong. |
| 401 | SERVICE_AUTH_REVOKED | App or secret has been revoked. |
| 401 | SERVICE_AUTH_EXPIRED | Secret is past its grace window. |
| 403 | SCOPE_MISSING | App is authenticated but lacks the scope for this endpoint. |
| 403 | SERVICE_IP_NOT_ALLOWED | Client IP not in the app's allowlist. |
| 429 | SERVICE_RATE_LIMITED | Per-minute rate limit reached, see Retry-After. |
