Skip to main content

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.

MethodBest forNotes
Email + password (JWT)Browser sessions and first-time logins from a user-facing appIssues a short-lived access token plus a refresh token. Detailed below under JWT Tokens.
API KeysServer-to-server integrations, scripts, CI, backend servicesLong-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​

  1. Log in to your Dashboard
  2. Go to Settings > API Keys
  3. Click Create API Key
  4. 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 to GET/HEAD/OPTIONS requests, regardless of the actions you picked for each resource
  5. 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"
Keep Your API Keys Secret

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 CodeErrorSolution
401Invalid credentialsCheck your API key or token
401Token expiredRefresh your JWT token
403Insufficient permissionsCheck your API key scopes
429Rate limit exceededImplement exponential backoff

Example Error Response​

{
"detail": "Unauthorized"
}

Next Steps​