Skip to main content

Authentication

The API supports two authentication methods: API Keys and JWT tokens.

API Keys

API keys are the recommended method for server-to-server integrations.

Obtaining an API Key

  1. Log in to Sealmetrics dashboard
  2. Go to SettingsAPI Keys
  3. Click Generate New Key
  4. Copy the key immediately (it won't be shown again)

Using API Keys

Include the key in the X-API-Key header:

curl -X GET "https://api.sealmetrics.com/api/v1/sites/YOUR_SITE_ID/stats" \
-H "X-API-Key: sm_your_api_key_here"

API Key Format

All API keys use the sm_ prefix:

sm_abc123def456ghi789...

Keys are 64 characters long and contain only alphanumeric characters after the prefix.

API Key Security

  • Keys are hashed before storage (we cannot retrieve your key)
  • Keys can be revoked at any time from the dashboard
  • Set expiration dates for temporary access
  • Each key is scoped to specific sites

JWT Bearer Tokens

JWT tokens are used for user-authenticated sessions (dashboard, mobile apps).

Obtaining a Token

curl -X POST "https://api.sealmetrics.com/api/v1/auth/token" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your_password"
}'

Response:

{
"access_token": "<access_token>",
"token_type": "bearer",
"expires_in": 900,
"refresh_token": "<refresh_token>"
}

Using JWT Tokens

Include the token in the Authorization header:

curl -X GET "https://api.sealmetrics.com/api/v1/sites/YOUR_SITE_ID/stats" \
-H "Authorization: Bearer <your_access_token>"

Token Refresh

Access tokens expire after 15 minutes. Use the refresh token to obtain a new access token:

curl -X POST "https://api.sealmetrics.com/api/v1/auth/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "<your_refresh_token>"
}'

JWT Claims

The access token contains:

ClaimDescription
subUser ID
emailUser email
account_idsList of accessible site IDs
expExpiration timestamp
iatIssued at timestamp

Authentication Errors

HTTP CodeError CodeDescription
401missing_credentialsNo API key or token provided
401invalid_api_keyAPI key not found or revoked
401invalid_tokenJWT token is malformed
401token_expiredJWT token has expired
403insufficient_scopeValid auth but no access to this resource

Example error response:

{
"error": {
"code": "invalid_api_key",
"message": "The provided API key is invalid or has been revoked"
},
"request_id": "req_abc123"
}

Best Practices

For API Keys

  1. Never commit keys to git - Use environment variables
  2. Rotate keys periodically - Generate new keys and revoke old ones
  3. Use separate keys per environment - Different keys for dev, staging, production
  4. Set minimum required scope - Only grant access to needed sites

For JWT Tokens

  1. Store tokens securely - Use httpOnly cookies or secure storage
  2. Implement token refresh - Don't wait for expiration errors
  3. Handle 401 gracefully - Redirect to login or refresh automatically
  4. Clear tokens on logout - Call the logout endpoint

Code Examples

Python

import requests

API_KEY = "sm_your_api_key_here"
BASE_URL = "https://api.sealmetrics.com/api/v1"

def get_stats(site_id: str, period: str = "7d"):
response = requests.get(
f"{BASE_URL}/sites/{site_id}/stats",
headers={"X-API-Key": API_KEY},
params={"period": period}
)
response.raise_for_status()
return response.json()

JavaScript / Node.js

const API_KEY = 'sm_your_api_key_here';
const BASE_URL = 'https://api.sealmetrics.com/api/v1';

async function getStats(siteId, period = '7d') {
const response = await fetch(
`${BASE_URL}/sites/${siteId}/stats?period=${period}`,
{
headers: { 'X-API-Key': API_KEY }
}
);

if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}

return response.json();
}

PHP

<?php
$apiKey = 'sm_your_api_key_here';
$baseUrl = 'https://api.sealmetrics.com/api/v1';

function getStats($siteId, $period = '7d') {
global $apiKey, $baseUrl;

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "$baseUrl/sites/$siteId/stats?period=$period");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-API-Key: $apiKey"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

return json_decode($response, true);
}