Authentication & Security
How to authenticate with the RideScan API securely, including API keys and OAuth2/JWT token flows
At a glance
All requests to https://api.ridescan.cloud must be authenticated over HTTPS. Use either a scoped API key or OAuth2-issued JWT access tokens. In fleets, authenticate robots via a Fleet Manager that dispenses short-lived tokens.
Production tips
- Never hardcode secrets in firmware or repos.
- Prefer short-lived tokens over raw API keys on robots.
- Rotate keys regularly and automate revocation.
- Scope credentials by role/robot where possible.
Supported Authentication Methods
Choose the method that fits your integration and security posture.
API Key (Bearer)
- Fast to start; great for server-to-server and CI
- Scope by role or project; store only in trusted backends
- Robots should avoid long-lived keys; exchange for short-lived tokens
Header: Authorization: Bearer <API_KEY>
OAuth2 / JWT
- Access tokens (short-lived) + refresh tokens (longer-lived)
- Fine-grained scopes and aud/iss claims for validation
- Best fit for fleets and multi-tenant dashboards
Header: Authorization: Bearer <ACCESS_TOKEN>
Quickstart: API Key
Use a scoped API key for quick server-to-server access.
1) Set your key (do not hardcode)
# macOS/Linux
export RIDESCAN_API_KEY="YOUR_API_KEY"
# Windows (Powershell)
$Env:RIDESCAN_API_KEY="YOUR_API_KEY"2) Make a test request
curl -sS \
-H "Authorization: Bearer $RIDESCAN_API_KEY" \
https://api.ridescan.cloud/api/robotsExpect 200 with your robot list. If you get 401, verify the header and that your key is active.
Python example
import os, requests
API_BASE = "https://api.ridescan.cloud"
API_KEY = os.environ.get("RIDESCAN_API_KEY")
headers = {"Authorization": f"Bearer {API_KEY}"}
r = requests.get(f"{API_BASE}/api/robots", headers=headers, timeout=10)
r.raise_for_status()
print(r.json())Node.js example
import axios from "axios";
const API_BASE = "https://api.ridescan.cloud";
const API_KEY = process.env.RIDESCAN_API_KEY;
const client = axios.create({
baseURL: API_BASE,
timeout: 10000,
headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data } = await client.get("/api/robots");
console.log(data);OAuth2 / JWT Token Flow
Use short-lived access tokens with refresh token rotation.
High-level flow
+-----------+ +-------------------+ +------------------+
| Client | auth | Auth Server | tokens | RideScan API |
| (backend) +--------->+ (OAuth2 Provider) +--------->+ (Resource Server)|
+-----------+ +-------------------+ +------------------+
^ |
| | refresh
+-------------------------+ token rotationToken endpoints
/oauth/token– exchange client creds or auth code for an access token (+ optional refresh token)/oauth/refresh– rotate refresh tokens and mint a new access token
Exchange for tokens
curl -sS -X POST https://api.ridescan.cloud/api/oauth/token \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=robots:read missions:write"Call an API with JWT
ACCESS_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -sS -H "Authorization: Bearer $ACCESS_TOKEN" \
https://api.ridescan.cloud/api/missionsAuto-refresh (Python)
import os, time, requests
BASE = "https://api.ridescan.cloud"
CLIENT_ID = os.getenv("RIDESCAN_CLIENT_ID")
CLIENT_SECRET = os.getenv("RIDESCAN_CLIENT_SECRET")
def fetch_token():
r = requests.post(f"{BASE}/oauth/token", data={
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"scope": "robots:read missions:write",
}, timeout=10)
r.raise_for_status()
return r.json() # { access_token, expires_in, token_type, ... }
tok = fetch_token()
exp_at = time.time() + tok["expires_in"] - 30 # refresh a bit early
def auth_headers():
global tok, exp_at
if time.time() >= exp_at:
tok = fetch_token()
exp_at = time.time() + tok["expires_in"] - 30
return {"Authorization": f"Bearer {tok['access_token']}"}
r = requests.get(f"{BASE}/v1/robots", headers=auth_headers(), timeout=10)
print(r.json())Error Handling & Troubleshooting
Common auth responses and how to fix them.
Typical responses
401 Unauthorized
{
"error": "invalid_token",
"message": "Access token missing or expired."
}- 401: refresh token or re-authenticate; check clock skew (±5 min).
Health checks
# Verify token audience and expiry (JWT)
# (Example using jwt-cli or your own verifier)
jwt decode $ACCESS_TOKEN | jq '{aud, exp, iat, scope}'Ensure aud matches ridescan-api and exp is in the future.
FAQ
Quick answers for security reviewers.
Do robots store API keys?
▾
Do robots store API keys?
▾Avoid storing long-lived keys on robots. Use a Fleet Manager to mint short-lived per-robot tokens or proxy requests.
How long do tokens last?
▾
How long do tokens last?
▾Access tokens typically live 15–60 minutes; refresh tokens longer. Configure to your risk tolerance.
How do we rotate keys with zero downtime?
▾
How do we rotate keys with zero downtime?
▾Support overlapping keys (old + new) at the gateway; publish ‘not-before’/‘not-after’ windows and gradually cut over.
What happens if a key leaks?
▾
What happens if a key leaks?
▾Immediately revoke in the admin console/API, rotate associated tokens, review logs, and re-issue scoped credentials.
Note: Endpoint paths are illustrative. Replace with the exact endpoints and scopes configured for your RideScan tenant.