Authentication
How to authenticate requests to the LaserData Cloud API using API keys and scoped roles.
Set variables to auto-fill all examples and run requests in-browser.
All LaserData Cloud API requests are authenticated using API keys passed in the ld-api-key request header. There are no sessions, cookies, or OAuth flows for API access.
Request Header
curl https://api.laserdata.cloud/tenants/{tenant_id}/api_keys \
-H "ld-api-key: YOUR_API_KEY"The key is validated on every request. If the key is missing, expired, or invalid, the API returns 401 Unauthorized. If the key is valid but lacks the required permission, the API returns 403 Forbidden.
Key Format
API keys are long-entropy random secrets. They cannot be recovered after creation; only the hash is stored server-side. Copy the secret immediately after creating it.
Scopes and Permissions
Every API key is tied to a role, which defines its permissions. Roles grant access at two levels:
| Scope | Description |
|---|---|
| Tenant | Cross-organization permissions, for example member:read, api_key:manage |
| Division | Resource permissions scoped to specific environments, for example deployment:manage, deployment:config:read |
The full permission model is documented in Roles & Permissions.
When creating an API key you can either assign an existing role or define inline permissions (a dedicated role is created automatically).
Rate Limiting
Each API key has a per-key rate limiter. Exceeding the limit returns 429 Too Many Requests. The response includes Retry-After indicating when the limit resets.
IP Allowlisting
API keys support optional IP allowlisting. When an allowlist is configured, requests from IPs not in the list receive 403 Forbidden regardless of the key's validity.
Allowlists can be updated on existing keys without recreating them. See Update API Key Security.
Expiry
All API keys have a mandatory expiration date (maximum 365 days). Expired keys return 401 Unauthorized. Create a replacement key before expiry and rotate it in your CI/CD environment.
Error Reference
| Status | Cause |
|---|---|
400 Bad Request | Validation failed. Response includes field_issues[] with per-field details |
401 Unauthorized | Key missing, malformed, expired, or revoked |
403 Forbidden | Key valid but missing the required permission, or request from a blocked IP |
404 Not Found | Resource does not exist or is not visible to this key |
429 Too Many Requests | Per-key rate limit exceeded; check Retry-After |
500 Internal Server Error | Unexpected server failure |
Error Envelope
Every non-2xx response uses a single envelope:
{
"code": "invalid_email",
"reason": "Invalid email address",
"field": "email",
"field_issues": [
{
"code": "invalid_email",
"reason": "malformed address",
"path": "email"
}
]
}| Field | Description |
|---|---|
code | Stable machine-readable error code (e.g. invalid_email, tenant_not_found, insufficient_permissions) |
reason | Human-readable explanation |
field | Single field name when the error is bound to one field. Legacy, still emitted for back-compat |
field_issues | Array of per-field issues for validation errors. Each entry has code, reason, and an optional dotted path. Empty or omitted on non-validation errors |
Validation errors return 400 with one or more entries in field_issues so clients can surface per-field UI feedback.
Security Best Practices
- Store keys in secrets managers (AWS Secrets Manager, HashiCorp Vault, GitHub Secrets), never in source code or logs
- Use the minimum required permissions: prefer
deployment:readover a full admin role for read-only automation - Set short expiration windows for CI keys (30-90 days)
- Enable IP allowlisting for long-lived keys used from fixed infrastructure
- Rotate keys using zero-downtime overlap: create the new key, update all consumers, then delete the old key
- All API key operations are logged in the audit trail