Authentication
Learn how to authenticate your requests to the SpatialFlow API using API keys or JWT tokens.
Authentication Methods
SpatialFlow's API accepts two credential types. Pick the one that fits your client.
| Method | Best for | Notes |
|---|---|---|
| Email + password (JWT) | Browser sessions and first-time logins from a user-facing app | Issues a short-lived access token plus a refresh token. Detailed below under JWT Tokens. |
| API Keys | Server-to-server integrations, scripts, CI, backend services | Long-lived bearer tokens with scoped permissions. Detailed below under API Keys. |
People signing in to the SpatialFlow app itself have other options: Google, Apple, and SAML single sign-on. Those are configured by the workspace owner (see Roles, audit log and SSO) or, for a self-managed deployment, by whoever runs it (see Enabling SSO Authentication). However someone signs in, the API they call afterward issues the same JWT pair documented under JWT Tokens.
API Keys
API keys are the simplest way to authenticate. They're long-lived credentials that don't expire, and each person can hold up to 5 of them.
Creating an API Key
- Log in to your Dashboard
- Go to Settings > API Keys
- Click Create API Key
- Name it, then set Permissions. A new key starts with none and can't call anything until you grant some; the form says "Leave empty for no API access." For each resource (
admin,audit-logs,devices,geofences,integrations,signals,storage,webhooks,workflows,workspaces) choose Full Access, Read, Write, Create, or Delete, or leave it at None. Turning on Read-only mode restricts the whole key toGET/HEAD/OPTIONSrequests, regardless of the actions you picked for each resource - Copy the key. SpatialFlow shows it only once
Each permission is stored as resource:action, for example geofences:create. A key with geofences:* (Full Access to Geofences) can perform every action on that resource; a key with *:* can call every permission-gated endpoint. No key can use the account endpoints, such as /auth/me or /account/api-keys: they accept only a signed-in session token, so creating or revoking keys stays with a person. The API returns a 403 naming the missing permission when a key tries a call it isn't scoped for.
Reading device data takes devices:read. That covers the device list and details, device, dashboard and location ingest statistics (/locations/stats), geofence events, sessions and session notes, and location tracks. Neither devices:write nor Read-only mode includes it, so a key that sends locations and also reads them back needs devices:write and devices:read.
Device writes that answer with the device need devices:read as well: updating, activating or deactivating a device, and the shift controls (start, pause, resume, end, recover and cancel recovery). Registering a device ID that already exists updates that device and returns it, so it needs devices:read and devices:write on top of devices:create. Registering a new device needs only devices:create, and sending locations, adding notes and deleting a device need only their own permission.
Stored files take the storage permissions: storage:read to list them (/storage/list/{file_type}) or get a download link (/storage/download/{file_id}), storage:write to upload, and storage:delete to delete. Device photo, attachment and capture listings (/devices/photos, a session's photos and attachments, and /devices/captures) take storage:read as well. Capture photos and files attached to a session count as device data on the storage routes too: listing /storage/list/image, or downloading one of those files from /storage/download/{file_id}, needs devices:read on top of storage:read, and other /storage/list/ results leave session attachments out for a key without devices:read.
The dashboard can't edit an existing key's permissions. To add devices:read to one, send PUT /api/v1/account/api-keys/{id} with the key's full permissions list from a signed-in session, or create a new key.
Using API Keys
Include your API key in the X-API-KEY header:
curl https://api.spatialflow.io/api/v1/geofences/ \
-H "X-API-KEY: your-api-key-here"
Never commit API keys to version control or share them publicly. Use environment variables or secret management services.
JWT Tokens
JWT (JSON Web Tokens) are temporary credentials that expire after a set time period.
Getting a JWT Token
curl -X POST https://api.spatialflow.io/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your-password"
}'
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 86400,
"token_type": "Bearer"
}
Using JWT Tokens
curl https://api.spatialflow.io/api/v1/geofences/ \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Refreshing Tokens
Access tokens expire after 24 hours by default (a global platform setting). Use the refresh token to get a new access token:
curl -X POST https://api.spatialflow.io/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "your-refresh-token-here"
}'
Best Practices
Security
- Use environment variables for credentials, not hardcoded strings in source
- Rotate API keys regularly
- Use JWT tokens for user-facing applications
- Implement token refresh logic
- Don't share API keys between environments
Performance
- Cache JWT tokens until expiration
- Reuse connections when making multiple requests
- Implement exponential backoff for failed authentication attempts
Rate Limiting
Authentication endpoints have the following rate limits:
- Login: 60 requests per minute per IP address, 15 requests per minute per email address
- Refresh: 30 requests per minute per token, 100 requests per minute per IP address
For API request rate limits by subscription tier, see Rate Limiting. When limits are exceeded, the API returns a 429 Too Many Requests status code with a Retry-After header indicating when to retry.
Error Handling
Common Authentication Errors
| Status Code | Error | Solution |
|---|---|---|
| 401 | Invalid credentials | Check your API key or token |
| 401 | Token expired | Refresh your JWT token |
| 403 | Insufficient permissions | Check your API key scopes |
| 429 | Rate limit exceeded | Implement exponential backoff |
Example Error Response
{
"detail": "Unauthorized"
}
Next Steps
- Create your first geofence - Start building
- API Reference - Explore all endpoints
- Best Practices - Production-ready patterns