Skip to main content

Authentication

Ovyxa API supports two authentication methods: JWT tokens for user sessions and API keys for programmatic access. Choose the method that best fits your use case.

Authentication Methods

JWT Tokens (User Sessions)

JWT (JSON Web Token) authentication is designed for web applications and dashboard integrations where users log in with their credentials.

Use cases:

  • Building custom dashboards
  • Browser-based integrations
  • User-facing applications
  • Short-lived sessions

How it works:

  1. User logs in with email/password
  2. Server returns a JWT token
  3. Token is included in subsequent API requests
  4. Token expires after 7 days

API Keys (Programmatic Access)

API keys are designed for server-side integrations, scripts, and applications where long-lived credentials are needed.

Use cases:

  • Server-side tracking
  • Automated scripts and cron jobs
  • Mobile applications
  • Third-party integrations
  • Continuous data exports

How it works:

  1. Generate an API key in dashboard settings
  2. Store key securely (environment variables)
  3. Include key in Authorization header
  4. Key remains valid until revoked

JWT Token Authentication

Obtaining a JWT Token

Endpoint: POST /api/v1/auth/login

Request:

{
"email": "user@example.com",
"password": "your-password"
}

Response (200 OK):

{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "user_123",
"email": "user@example.com",
"name": "John Doe"
},
"expires_at": "2025-01-22T14:30:00Z"
}

Example (JavaScript):

async function login(email, password) {
const response = await fetch('https://api.ovyxa.com/api/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, password })
});

if (!response.ok) {
throw new Error('Login failed');
}

const { token, user } = await response.json();

// Store token (localStorage, cookie, etc.)
localStorage.setItem('ovyxa_token', token);

return { token, user };
}

// Usage
const { token } = await login('user@example.com', 'password');

Example (cURL):

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

Using JWT Tokens in Requests

Include the token in the Authorization header with the Bearer scheme:

const response = await fetch('https://api.ovyxa.com/api/v1/stats/overview?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31', {
headers: {
'Authorization': `Bearer ${token}`
}
});

const data = await response.json();

cURL Example:

curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
"https://api.ovyxa.com/api/v1/stats/overview?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31"

Token Expiration and Refresh

JWT tokens expire after 7 days. When a token expires, you'll receive a 401 Unauthorized response.

Handling Expiration:

async function fetchWithAuth(url, options = {}) {
const token = localStorage.getItem('ovyxa_token');

const response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`
}
});

// Token expired - redirect to login
if (response.status === 401) {
localStorage.removeItem('ovyxa_token');
window.location.href = '/login';
return;
}

return response;
}

Note: Token refresh endpoints are coming in a future update. For now, users must re-login when tokens expire.


API Key Authentication

Generating an API Key

API keys can be generated in your Ovyxa dashboard:

  1. Navigate to SettingsAPI Keys
  2. Click Generate New Key
  3. Give your key a descriptive name (e.g., "Production Server", "Mobile App")
  4. Copy the key immediately (it's only shown once)
  5. Store the key securely

API Key Format:

sk_live_1234567890abcdefghijklmnopqrstuvwxyz

All API keys are prefixed with sk_live_ for production or sk_test_ for test environments.

Using API Keys in Requests

Include the API key in the Authorization header with the Bearer scheme:

JavaScript Example:

const response = await fetch('https://api.ovyxa.com/api/v1/stats/overview?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31', {
headers: {
'Authorization': 'Bearer sk_live_1234567890abcdefghijklmnopqrstuvwxyz'
}
});

const data = await response.json();

cURL Example:

curl -H "Authorization: Bearer sk_live_1234567890abcdefghijklmnopqrstuvwxyz" \
"https://api.ovyxa.com/api/v1/stats/overview?site_id=xxx&date_from=2025-01-01&date_to=2025-01-31"

Python Example:

import requests
import os

API_KEY = os.environ.get('OVYXA_API_KEY')

response = requests.get(
'https://api.ovyxa.com/api/v1/stats/overview',
headers={'Authorization': f'Bearer {API_KEY}'},
params={
'site_id': 'xxx',
'date_from': '2025-01-01',
'date_to': '2025-01-31'
}
)

data = response.json()
print(data)

Managing API Keys

Best practices:

  1. Never commit keys to version control:

    # .env file (add to .gitignore)
    OVYXA_API_KEY=sk_live_1234567890abcdefghijklmnopqrstuvwxyz
  2. Use environment variables:

    // Node.js
    const API_KEY = process.env.OVYXA_API_KEY;

    // Python
    import os
    API_KEY = os.environ.get('OVYXA_API_KEY')
  3. Rotate keys regularly: Generate new keys periodically and revoke old ones

  4. One key per integration: Create separate keys for different applications/environments

  5. Revoke compromised keys immediately: If a key is exposed, revoke it in dashboard settings

Revoking API Keys

To revoke an API key:

  1. Go to SettingsAPI Keys
  2. Find the key you want to revoke
  3. Click Revoke
  4. Confirm the action

Revoked keys are immediately invalidated and will return 401 Unauthorized for all requests.


API Key Scopes (Phase 2)

Future releases will support scoped API keys with granular permissions:

Planned scopes:

  • stats:read - Read analytics data
  • events:write - Send custom events and pageviews
  • goals:manage - Create, update, delete goals
  • sites:manage - Manage site settings
  • admin:full - Full account access

Example usage:

{
"name": "Mobile App Key",
"scopes": ["events:write"],
"expires_at": "2026-01-01T00:00:00Z"
}

Security Best Practices

1. Store Credentials Securely

Never hardcode credentials:

// BAD - Don't do this
const API_KEY = 'sk_live_1234567890abcdefghijklmnopqrstuvwxyz';

// GOOD - Use environment variables
const API_KEY = process.env.OVYXA_API_KEY;

2. Use HTTPS Only

Always use HTTPS for API requests. HTTP requests will be automatically upgraded to HTTPS, but it's best to use HTTPS explicitly:

// GOOD
const API_URL = 'https://api.ovyxa.com/api/v1';

// BAD - Will work but generates redirect
const API_URL = 'http://api.ovyxa.com/api/v1';

3. Implement Rate Limit Handling

async function apiRequestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);

// Rate limited - retry after delay
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}

return response;
}

throw new Error('Max retries exceeded');
}

4. Validate API Responses

async function fetchStats(siteId, dateFrom, dateTo) {
const response = await fetch(
`https://api.ovyxa.com/api/v1/stats/overview?site_id=${siteId}&date_from=${dateFrom}&date_to=${dateTo}`,
{
headers: {
'Authorization': `Bearer ${process.env.OVYXA_API_KEY}`
}
}
);

// Check for errors
if (!response.ok) {
const error = await response.json();
throw new Error(`API Error: ${error.error.message}`);
}

// Validate response structure
const data = await response.json();
if (!data.data || !data.data.metrics) {
throw new Error('Invalid API response structure');
}

return data;
}

5. Monitor for Suspicious Activity

Regularly review API usage in your dashboard:

  • Unexpected spikes in requests
  • Requests from unknown IP addresses
  • Failed authentication attempts
  • Unusual access patterns

If you detect suspicious activity, immediately revoke the compromised API key and generate a new one.


Error Responses

401 Unauthorized (Invalid or missing credentials):

{
"error": {
"code": "unauthorized",
"message": "Invalid or expired authentication token"
}
}

403 Forbidden (Insufficient permissions):

{
"error": {
"code": "forbidden",
"message": "You do not have permission to access this resource"
}
}

429 Too Many Requests (Rate limit exceeded):

{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please try again later."
}
}

Testing Authentication

Test Your API Key

# Simple test to verify your API key works
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.ovyxa.com/api/v1/auth/verify"

# Expected response:
# {"authenticated": true, "key_id": "key_abc123"}

Test Your JWT Token

# Verify JWT token is valid
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
"https://api.ovyxa.com/api/v1/auth/verify"

# Expected response:
# {"authenticated": true, "user_id": "user_123"}

Migration from Other Analytics

If you're migrating from another analytics platform and need to import historical data, you can use API keys with the Events API to backfill data:

import fs from 'fs';

// Load historical events from CSV/JSON export
const historicalEvents = JSON.parse(fs.readFileSync('export.json'));

// Import events using API key
for (const event of historicalEvents) {
await fetch('https://api.ovyxa.com/api/v1/events/custom', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.OVYXA_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
site_id: 'site_abc123',
event_name: event.name,
url: event.url,
props: event.properties
})
});

// Respect rate limits
await new Promise(resolve => setTimeout(resolve, 100));
}

Support

Having trouble with authentication? Contact our support team at support@ovyxa.com or check our API overview.