Skip to main content
API keys provide long-lived authentication for server-to-server integration with Open Wearables. They’re designed for backend services, scripts, and automated workflows.

Overview

API keys are simple credentials that authenticate your server with the Open Wearables API. Unlike JWT tokens, they don’t expire automatically and remain valid until explicitly deleted or rotated.

Key Format

All API keys follow this format:
sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
  • Prefix: sk- (secret key)
  • Length: 32 hexadecimal characters
  • Generation: Cryptographically secure random generation
Security Notice: API keys are only displayed once during creation. Store them securely immediately - you cannot retrieve them later.

Using API Keys

Include your API key in the X-Open-Wearables-API-Key header for all API requests:
curl https://api.openwearables.com/api/v1/users \
  -H "X-Open-Wearables-API-Key: sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

API Endpoints

All API key management endpoints require JWT authentication (developer portal access).

Create API Key

name
string
default:"Default"
Human-readable name to identify this API key. Useful for tracking which services use which keys.
API keys are associated with the authenticated developer who creates them.
Request Example:
curl -X POST https://api.openwearables.com/api/v1/api-keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Production Server"}'
Response (201 Created):
{
  "id": "sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "name": "Production Server",
  "created_by": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2026-03-07T10:30:00Z"
}
id
string
required
The API key value. This is the only time you’ll see the full key - store it securely.
name
string
required
The name you assigned to this key.
created_by
string (uuid)
UUID of the developer who created this key.
created_at
string (datetime)
required
ISO 8601 timestamp when the key was created.

List API Keys

For security, the full key value is never returned in list operations - only the key ID and metadata.
Request Example:
curl https://api.openwearables.com/api/v1/api-keys \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
Response (200 OK):
[
  {
    "id": "sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
    "name": "Production Server",
    "created_by": "550e8400-e29b-41d4-a716-446655440000",
    "created_at": "2026-03-07T10:30:00Z"
  },
  {
    "id": "sk-x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4",
    "name": "Staging Environment",
    "created_by": "550e8400-e29b-41d4-a716-446655440000",
    "created_at": "2026-03-01T14:20:00Z"
  }
]

Update API Key

key_id
string
required
The full API key ID (e.g., sk-a1b2c3d4...)
name
string
New name for the API key.
Request Example:
curl -X PATCH https://api.openwearables.com/api/v1/api-keys/sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Production Server v2"}'
Response (200 OK):
{
  "id": "sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "name": "Production Server v2",
  "created_by": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2026-03-07T10:30:00Z"
}

Rotate API Key

key_id
string
required
The API key ID to rotate.
Important: The old key is immediately invalidated. Any services using it will lose access until updated with the new key.
Request Example:
curl -X POST https://api.openwearables.com/api/v1/api-keys/sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6/rotate \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
Response (201 Created):
{
  "id": "sk-z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4",
  "name": "Production Server",
  "created_by": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2026-03-07T11:45:00Z"
}

Delete API Key

key_id
string
required
The API key ID to delete.
This action is irreversible. Any services using this key will immediately lose access.
Request Example:
curl -X DELETE https://api.openwearables.com/api/v1/api-keys/sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
Response (200 OK):
{
  "id": "sk-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "name": "Production Server",
  "created_by": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2026-03-07T10:30:00Z"
}

Best Practices

Name your API keys based on their purpose or environment:
  • ✅ “Production Server - AWS Lambda”
  • ✅ “Staging Environment”
  • ✅ “Data Pipeline - Hourly Sync”
  • ❌ “Key 1”
  • ❌ “Test”
Create different API keys for each environment:
  • Development
  • Staging
  • Production
This allows you to rotate or revoke keys without affecting other environments.
Implement a key rotation schedule:
  • High-security: Every 30 days
  • Standard: Every 90 days
  • Minimum: Every 6 months
Use the rotate endpoint for zero-downtime rotation:
  1. Call /rotate to get new key
  2. Deploy new key to your services
  3. Verify services are using new key
  4. Old key is automatically deleted
Never expose API keys in:
  • Client-side JavaScript
  • Mobile app source code
  • Git repositories
  • Logs or error messages
  • URLs or query parameters
Use secure storage:
  • Environment variables
  • Secret management services (AWS Secrets Manager, HashiCorp Vault)
  • Encrypted configuration files
Track which keys are actively used:
  • Set up logging for API key authentication
  • Delete unused keys immediately
  • Alert on unusual activity patterns
  • Review key list monthly
If an API key is compromised:
  1. Delete the key immediately via /api/v1/api-keys/{key_id}
  2. Create a new key with a different name
  3. Update all affected services
  4. Review logs for unauthorized access
  5. Consider rotating other keys as a precaution

Error Responses

Status CodeErrorDescription
401UnauthorizedInvalid or missing API key
403ForbiddenValid key but insufficient permissions
404Not FoundAPI key does not exist
422Validation ErrorInvalid request body (e.g., missing name)
429Rate LimitedToo many requests - slow down
Example Error Response:
{
  "detail": "Invalid or missing API key"
}

Complete Integration Example

Here’s a complete example of managing API keys in a Python application:
api_key_manager.py
import os
import requests
from typing import Optional

class OpenWearablesClient:
    """Client for Open Wearables API with key management."""
    
    def __init__(self, jwt_token: Optional[str] = None, api_key: Optional[str] = None):
        self.base_url = "https://api.openwearables.com/api/v1"
        self.jwt_token = jwt_token
        self.api_key = api_key or os.getenv("OPEN_WEARABLES_API_KEY")
    
    def _get_headers(self, use_jwt: bool = False) -> dict:
        """Get authentication headers."""
        if use_jwt and self.jwt_token:
            return {"Authorization": f"Bearer {self.jwt_token}"}
        elif self.api_key:
            return {"X-Open-Wearables-API-Key": self.api_key}
        else:
            raise ValueError("No authentication credentials provided")
    
    # API Key Management (requires JWT)
    
    def create_api_key(self, name: str) -> dict:
        """Create a new API key."""
        response = requests.post(
            f"{self.base_url}/api-keys",
            headers={**self._get_headers(use_jwt=True), "Content-Type": "application/json"},
            json={"name": name}
        )
        response.raise_for_status()
        return response.json()
    
    def list_api_keys(self) -> list[dict]:
        """List all API keys."""
        response = requests.get(
            f"{self.base_url}/api-keys",
            headers=self._get_headers(use_jwt=True)
        )
        response.raise_for_status()
        return response.json()
    
    def rotate_api_key(self, key_id: str) -> dict:
        """Rotate an API key."""
        response = requests.post(
            f"{self.base_url}/api-keys/{key_id}/rotate",
            headers=self._get_headers(use_jwt=True)
        )
        response.raise_for_status()
        return response.json()
    
    def delete_api_key(self, key_id: str) -> dict:
        """Delete an API key."""
        response = requests.delete(
            f"{self.base_url}/api-keys/{key_id}",
            headers=self._get_headers(use_jwt=True)
        )
        response.raise_for_status()
        return response.json()
    
    # Data Access (uses API key)
    
    def get_users(self) -> list[dict]:
        """Get all users using API key authentication."""
        response = requests.get(
            f"{self.base_url}/users",
            headers=self._get_headers()
        )
        response.raise_for_status()
        return response.json()

# Usage example
if __name__ == "__main__":
    # Initialize with JWT token for key management
    jwt_token = "your-jwt-token-here"
    client = OpenWearablesClient(jwt_token=jwt_token)
    
    # Create a new API key
    new_key = client.create_api_key("Production Server")
    print(f"Created API key: {new_key['id']}")
    
    # Save the key securely (e.g., to environment or secret manager)
    api_key = new_key['id']
    
    # Use the API key for data access
    data_client = OpenWearablesClient(api_key=api_key)
    users = data_client.get_users()
    print(f"Found {len(users)} users")
    
    # Rotate key periodically
    rotated_key = client.rotate_api_key(api_key)
    print(f"Rotated to new key: {rotated_key['id']}")

JWT Token Authentication

Learn about session-based authentication for the developer portal

Authentication Overview

Compare authentication methods and choose the right one

Build docs developers (and LLMs) love