Ionhour Docs

Authentication

API keys, token-based auth, rate limits, and CSRF protection.

Ionhour supports two authentication methods: API keys for programmatic access and OAuth tokens for interactive sessions. Which one you need depends on the endpoint you are calling — see the table below before writing any code.

Which credential goes where

SurfaceBase pathCredential
Integration API/api/v1/*ionh_ API key as a Bearer token
MCPPOST /api/mcpionh_ API key as a Bearer token
Dashboard REST APIall other /api/* routesOAuth session (Keycloak access token)
Public endpointsping, public status, badgesnone

ionh_ API keys authenticate only /api/v1/* and /api/mcp. Every other REST endpoint in this reference belongs to the dashboard API and rejects API keys with a 401. If you are a third-party service provider wiring your product into Ionhour, start with the Integrations section — it covers everything the Integration API can do.

API Keys

API keys are the recommended way to reach Ionhour from scripts, CI/CD pipelines, and third-party integrations — via the Integration API (/api/v1) and MCP. Each key is scoped to a single workspace.

Creating an API Key

  1. Navigate to Settings > API Keys in your workspace.
  2. Click Create API Key.
  3. Enter a name to identify the key's purpose.
  4. Copy the key immediately — it will not be shown again.

API keys follow the format ionh_ followed by 32 hex characters (37 characters total).

Using an API Key

Pass the key in the Authorization header on an Integration API or MCP request. GET /api/v1/whoami is the smoke test — it echoes the key's workspace, permission level, and projected role:

curl -H "Authorization: Bearer ionh_your_api_key_here" \
  https://api.ionhour.com/api/v1/whoami

Keys carry a permission level (READ_ONLY keys are limited to GET requests) and optional resource restrictions. The full model — levels, scoping, rate limits, and error codes — is documented in Integration API authentication.

Key Management

ActionDescription
CreateGenerate a new key. Full key shown once.
ListView all keys in the workspace. Only the prefix is displayed.
RotateGenerate a new key for an existing record. The old key is invalidated.
RevokePermanently delete a key.

Security

  • Keys are stored as SHA-256 hashes — Ionhour never stores the plaintext key.
  • Only the first 12 characters (prefix) are stored for identification.
  • Each key tracks a lastUsedAt timestamp for auditing.
  • Keys can be disabled without deleting them.
Treat API keys like passwords — don't commit them to source control.

OAuth Tokens (Web and Mobile)

Interactive applications (like the Ionhour dashboard) use OAuth 2.0 with Keycloak as the identity provider. This is primarily for building custom UIs — most API integrations should use API keys with the Integration API instead.

The dashboard REST endpoints in this reference authenticate with the Keycloak access token — sent automatically as an HttpOnly cookie in browsers, or passed explicitly as Authorization: Bearer <access token> from non-browser clients. Examples in this section write it as $ACCESS_TOKEN.

Web Flow

Get login URL: GET /api/auth/login-url returns a Keycloak authorization URL.
User authenticates: User is redirected to Keycloak, signs in, and is redirected back with an authorization code.
Exchange code: POST /api/auth/token exchanges the code for access and refresh tokens.
Use tokens: Access token is set as an HttpOnly cookie and sent automatically with requests.
Refresh: POST /api/auth/refresh renews the access token using the refresh token.

Mobile Flow

Mobile apps use PKCE (Proof Key for Code Exchange) for added security:

POST /api/auth/mobile/login-url — returns auth URL with PKCE challenge.
POST /api/auth/mobile/token — exchanges code + verifier for tokens (returned in response body, not cookies).
POST /api/auth/mobile/refresh — refreshes tokens (accepts refresh token in request body).
POST /api/auth/mobile/logout — revokes tokens.

CSRF Protection

State-changing requests (POST, PUT, PATCH, DELETE) from web clients require a CSRF token:

  • A csrf_token cookie is set on login/refresh (JavaScript-accessible).
  • Include the token in the X-CSRF-Token header for all state-changing requests.
  • GET, HEAD, and OPTIONS requests are exempt.

Public Endpoints

These endpoints require no authentication:

EndpointPurpose
GET /api/signals/ping/:tokenSend a heartbeat (GET)
POST /api/signals/ping/:tokenSend a heartbeat with payload (POST)
GET /api/public/status/:slugView a public status page
GET /api/public/status/:slug/feed.rssStatus page RSS feed
GET /api/public/status/:slug/badge.svgStatus badge
GET /api/checks/:id/badgeCheck status badge

Rate Limits

Ionhour enforces rate limits to protect the API from abuse. Limits are per client IP address.

Default Limit

100 requests per 60 seconds for all authenticated endpoints.

Auth Endpoints

EndpointLimit
GET /api/auth/login-url5 per 60s
POST /api/auth/token10 per 60s
POST /api/auth/refresh10 per 60s
POST /api/auth/logout10 per 60s

Public Status Page Endpoints

EndpointLimit
Status page data, uptime, history30 per 60s
Password verification5 per 5 minutes
Subscription5 per 60s
RSS/Atom feeds10 per 60s

Rate Limit Response

When the limit is exceeded, the API returns:

HTTP/1.1 429 Too Many Requests

Wait for the rate limit window to reset before retrying.

Workspace Scoping

All authenticated requests are scoped to a workspace. The workspace is determined by:

  • API keys: The workspace the key was created in.
  • OAuth tokens: The workspace selected by the user in the dashboard.

Data from one workspace is never accessible from another, even for the same user. This is enforced at the API level — you cannot query resources across workspaces in a single request.