Skip to main content

API Overview

Welcome to the Heimdall API documentation. This API provides a comprehensive set of endpoints for managing GPS tracking data, system settings, and real-time communication.

Base URL​

Production: https://api.elcto.com
Development: http://localhost:3000

All API endpoints are available under the /v1 prefix.

API Version​

Current version: v1

All API endpoints are prefixed with /v1 (except health check and root endpoints).

Available APIs​

Heimdall provides three main API interfaces:

REST API​

Traditional RESTful API with full CRUD operations, pagination, and HATEOAS links.

  • Endpoints: /v1/*
  • Authentication: Bearer token
  • Format: JSON
  • Documentation: Interactive Swagger UI (development builds only)

GraphQL API​

Flexible query language for efficient data fetching and mutations.

  • Endpoint: /v1/gql (optionally authenticated — auth is checked per-resolver)
  • GraphiQL IDE: /v1/graphiql (interactive interface, no auth)
  • Schema: /v1/schema (SDL format, no auth)
  • Authentication: Pass a Bearer token to /v1/gql; individual resolvers enforce auth/permissions, so unauthenticated requests can still reach public resolvers
  • Features: Introspection, batching, type-safe queries

WebSocket API​

Real-time bidirectional communication for live GPS updates and notifications.

  • Endpoint: ws://api.elcto.com/v1/ws
  • Protocol: WebSocket
  • Features: Channel subscriptions, heartbeat monitoring, automatic reconnection

Architecture​

The API is built from 19 modular heimdall-* crates under crates/. The platform/api/ binary is a thin Actix-web server that wires these crates together:

  • heimdall-rest -- REST handlers, routes, middleware, OAuth endpoints
  • heimdall-graphql -- GraphQL types, resolvers, and schema
  • heimdall-websocket -- WebSocket server and channel pub/sub
  • heimdall-auth -- JWT, RBAC, TOTP, crypto
  • heimdall-db -- Database models and queries
  • heimdall-cache -- Redis client (sessions, permissions, rate limiting)

Services are injected via web::Data<T> (no monolithic AppState). See Architecture Overview and Crate Reference for details.

Key Features​

  • RESTful Design - Clean, predictable resource-based URLs
  • HATEOAS Links - Self-documenting API with hypermedia links
  • Authentication - Secure token-based authentication
  • Rate Limiting - Protection against abuse
  • Pagination - Efficient handling of large datasets
  • Real-time Updates - WebSocket support for live data
  • GraphQL - Flexible querying with exact data needs
  • CORS Support - Environment-aware cross-origin requests
  • Comprehensive Errors - Detailed error messages with codes

Quick Start​

1. Get an API Token​

Contact your administrator to obtain an API token.

2. Make Your First Request​

curl -H "Authorization: Bearer YOUR_TOKEN" \
https://api.elcto.com/v1/gps/current

3. Explore the API​

Visit our Interactive Swagger UI to explore all available endpoints and try them out. Swagger UI is served only in development builds (when is_development is true) and is not exposed in production.

API Endpoints​

CategoryEndpointsDescription
HealthGET /health, GET /v1/healthSystem health check
InfoGET /v1API version info
AuthPOST /v1/auth/*Authentication & validation
GPS/v1/gps/*GPS data management
Vessels/v1/vessels/*AIS vessel directory & detail
Settings/v1/settings/*System configuration
Stats/v1/stats/*Platform statistics
API Keys/v1/api-keys/*API key management
Roles/v1/roles/*Role management
Permissions/v1/permissions/*Permission management
Users/v1/users/*User management
Sessions/v1/users/me/sessions/*Active session management
2FA/v1/users/me/2fa/*Two-factor authentication
Activity Log/v1/users/me/audit/*User activity & audit events
Audit Reports/v1/admin/audit/reports/*Admin audit report management
User Bans/v1/users/{id}/ban, /v1/users/{id}/bansUser ban management & history
Data ExportGET /v1/user/exportGDPR data export
OAuth Clients/v1/oauth/clients/*OAuth app management
Platforms/v1/platforms/*Authentication platforms
WebSocketWS /v1/wsReal-time communication
GraphQLPOST /v1/gql, GET /v1/graphiqlGraphQL queries/mutations

Response Format​

All REST API responses follow a consistent format with HATEOAS links:

{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"latitude": 51.5074,
"longitude": -0.1278
},
"_links": {
"self": "https://api.elcto.com/v1/gps/550e8400-e29b-41d4-a716-446655440000"
}
}

Rate Limiting​

Every request (REST, GraphQL, WS handshake) is rate-limited by an auth-context-aware, fixed-window Redis counter, keyed per identity. The limit depends on the caller's tier:

TierWhoDefault limit
UnlimitedSystem API key (is_system = true)∞ — never counted
API keyNon-system API key1200 req / 60s
UserLogged-in user (session/JWT)600 req / 60s
AnonymousNo auth context (keyed by IP)120 req / 60s

Limits are configurable via [rate_limiting] — see Configuration.

Rate-limited responses (excluded: system keys, exempt paths, fail-open) include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. Exceeding the limit returns 429 Too Many Requests with a Retry-After header (seconds until the window resets).

Exempt paths (never limited): /health, /v1/health, /v1/ws, /v1/openapi.json, /v1/schema, /v1/swagger-ui/*. OAuth endpoints (/v1/oauth/*) are limited like any other route.

Anonymous SSR bypass: server-side requests from the Next.js webapps (e.g. unauthenticated SSR page renders) can skip the anonymous-tier limit by sending a matching X-Internal-Token header — a shared secret configured via internal_token / HEIMDALL__RATE_LIMITING__INTERNAL_TOKEN. The bypass only ever applies to the anonymous tier (never API-key or user tiers), and is disabled by default (empty token = fail-safe). Webapps send it server-side via @elcto/api's ApiClientConfig.internalToken, sourced from the server-only HEIMDALL_INTERNAL_TOKEN env var.

If Redis is unreachable, rate limiting fails open — requests are allowed through rather than blocking the API.

Configuration​

GeoIP Location Lookup​

The API supports IP-to-location lookup for audit events using the MaxMind GeoLite2 City database. This enables showing geographic information (city, region, country) in activity logs.

Setup:

  1. Register for a free license key at MaxMind GeoLite2
  2. Download the database using the built-in updater:
# Using just command
just geoip-update

# Or directly
MAXMIND_LICENSE_KEY=your_key cargo run --bin geoip-update

TOML Configuration (config/default.toml):

[geoip]
# Path to the MaxMind GeoLite2 City database file (.mmdb)
database_path = "data/GeoLite2-City.mmdb"
# MaxMind license key for downloading/updating the database
license_key = ""
# MaxMind account ID (numeric) for Privacy Exclusions API
account_id = ""
# Enable automatic database updates on server startup
auto_update = false
# Update interval in days (default: 7, MaxMind updates weekly)
update_interval_days = 7
# Enable Privacy Exclusions API to respect user opt-outs
privacy_exclusions_enabled = false
# How often to refresh privacy exclusions (in hours)
privacy_exclusions_refresh_hours = 24
# Path to cache file for privacy exclusions
privacy_exclusions_cache_path = "data/geoip-privacy-exclusions.json"

Environment Variable Overrides:

VariableDescription
GEOIP_DATABASE_PATHPath to the .mmdb database file
MAXMIND_LICENSE_KEYLicense key for downloads
MAXMIND_ACCOUNT_IDAccount ID for Privacy Exclusions API
GEOIP_AUTO_UPDATEEnable auto-update (true/false)
GEOIP_UPDATE_INTERVAL_DAYSDays between updates
GEOIP_PRIVACY_EXCLUSIONS_ENABLEDEnable Privacy Exclusions API
GEOIP_PRIVACY_EXCLUSIONS_REFRESH_HOURSHours between exclusion refreshes
GEOIP_PRIVACY_EXCLUSIONS_CACHE_PATHPath to exclusions cache file

Just Commands:

CommandDescription
just geoip-updateDownload/update GeoIP database
just geoip-update-forceForce re-download even if recent
just geoip-statusCheck if database exists

Privacy Exclusions API:

The Privacy Exclusions API allows respecting users who have opted out of geolocation tracking via MaxMind's Privacy Exclusions. When enabled:

  • The service fetches excluded IPs/networks from MaxMind on startup
  • Exclusions are cached locally in a JSON file for persistence
  • Cache is refreshed at the configured interval (default: 24 hours)
  • Any lookup for an excluded IP returns no location data

If no GeoIP database is configured, audit events will still be logged but without location data.

Sentry Error Tracking​

The API supports Sentry integration for error tracking and performance monitoring.

TOML Configuration (config/default.toml):

[sentry]
# Enable Sentry error tracking
enabled = true
# Sentry DSN (Data Source Name) - get from Sentry project settings
dsn = "https://your-key@sentry.io/your-project-id"
# Environment name (e.g., "production", "staging", "development")
environment = "production"
# Sample rate for performance tracing (0.0 to 1.0)
traces_sample_rate = 1.0
# Sample rate for error events (0.0 to 1.0)
sample_rate = 1.0
# Enable Sentry SDK debug mode
debug = false
# Attach stack traces to messages
attach_stacktrace = true
# Send default PII (personally identifiable information)
send_default_pii = false
# Maximum number of breadcrumbs to capture
max_breadcrumbs = 100

Environment Variable Overrides:

VariableDescription
SENTRY_DSNSentry DSN (auto-enables if set)
SENTRY_ENVIRONMENTEnvironment name
SENTRY_TRACES_SAMPLE_RATETraces sample rate
SENTRY_SAMPLE_RATEError sample rate
SENTRY_DEBUGEnable debug mode

Setting SENTRY_DSN automatically enables Sentry even if enabled = false in the config.

What Gets Captured:

  • Database errors (5xx)
  • Redis errors (5xx)
  • Internal server errors (5xx)
  • Performance traces for all requests (based on traces_sample_rate)
  • Breadcrumbs for INFO, WARN, and ERROR log levels

What Is NOT Captured:

  • Client errors (4xx) - these are logged locally but not sent to Sentry
  • DEBUG and TRACE level logs

Next Steps​