Files
shopify-ai-backup/EXTERNAL_ADMIN_API.md
2026-02-20 18:40:54 +00:00

16 KiB

External Admin API Documentation

Overview

The External Admin API provides programmatic access to all admin functionality via a RESTful API. This enables automation, integrations with external tools, and custom admin dashboards.

Table of Contents

  1. Authentication
  2. Configuration
  3. API Endpoints
  4. Request/Response Format
  5. Rate Limiting
  6. Error Handling
  7. Examples
  8. Security Best Practices

Authentication

The External Admin API supports two authentication methods:

Option 1: API Key (Direct)

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

Authorization: Bearer sk_live_your_api_key_here

Key Format:

  • Production keys: sk_live_ prefix
  • Test keys: sk_test_ prefix

For better performance, exchange your API key for a short-lived JWT token:

  1. Obtain JWT Token:

    POST /api/external/auth/validate
    Authorization: Bearer sk_live_your_api_key_here
    
  2. Response:

    {
      "success": true,
      "data": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "tokenType": "Bearer",
        "expiresIn": 3600,
        "expiresAt": "2026-02-20T11:00:00.000Z"
      },
      "meta": {
        "timestamp": "2026-02-20T10:00:00.000Z",
        "requestId": "req_abc123"
      }
    }
    
  3. Use JWT Token:

    GET /api/external/users
    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    

Token Validation

Validate your current authentication:

GET /api/external/auth/me
Authorization: Bearer <your_token>

Configuration

Environment Variables

Add these to your .env file or Docker environment:

Variable Description Default Required
ADMIN_API_KEY Your secret API key - Yes (to enable API)
ADMIN_API_JWT_TTL JWT token lifetime in seconds 3600 (1 hour) No
ADMIN_API_RATE_LIMIT Requests per hour per key 1000 No
JWT_SECRET Secret for JWT signing - Yes

Docker Compose Setup

# docker-compose.yml
services:
  shopify-ai-builder:
    environment:
      - ADMIN_API_KEY=${ADMIN_API_KEY:-}
      - ADMIN_API_JWT_TTL=${ADMIN_API_JWT_TTL:-3600}
      - ADMIN_API_RATE_LIMIT=${ADMIN_API_RATE_LIMIT:-1000}
      - JWT_SECRET=${JWT_SECRET:-}

Generating a Secure API Key

# Generate a 32-byte hex key
openssl rand -hex 32

# Example output: a1b2c3d4e5f6... (64 hex characters)

# Set in .env:
ADMIN_API_KEY=sk_live_a1b2c3d4e5f6...

API Endpoints

Base URL

All external API endpoints are prefixed with /api/external.

Authentication

Method Endpoint Description
POST /auth/validate Exchange API key for JWT token
GET /auth/me Get current authentication info

User Management

Method Endpoint Description
GET /users List all users (paginated)
GET /users/:id Get user by ID
PATCH /users/:id/plan Update user's subscription plan
PATCH /users/:id/tokens Adjust user's token allocation
DELETE /users/:id Delete a user
GET /users/:id/sessions List user's active sessions
DELETE /users/:id/sessions/:sessionId Revoke a user session

Model Management

Method Endpoint Description
GET /models List all configured models
POST /models Create a new model configuration
GET /models/:id Get model by ID
PATCH /models/:id Update model configuration
DELETE /models/:id Delete a model
POST /models/reorder Reorder model display priority

Affiliate Management

Method Endpoint Description
GET /affiliates List all affiliates (paginated)
GET /affiliates/:id Get affiliate by ID
DELETE /affiliates/:id Delete an affiliate

Withdrawal Management

Method Endpoint Description
GET /withdrawals List withdrawal requests (paginated)
PUT /withdrawals Update withdrawal status

Analytics & Monitoring

Method Endpoint Description
GET /analytics/overview Get dashboard overview stats
GET /analytics/tracking Get visitor tracking stats
GET /analytics/resources Get resource monitoring data
GET /analytics/usage Get token usage statistics

Content Management

Method Endpoint Description
GET /blogs List all blogs (paginated)
POST /blogs Create a new blog post
GET /blogs/:id Get blog by ID
PATCH /blogs/:id Update blog post
DELETE /blogs/:id Delete a blog post
GET /feature-requests List feature requests (paginated)
PATCH /feature-requests/:id Update feature request status
GET /contact-messages List contact messages (paginated)
DELETE /contact-messages/:id Delete a contact message

System Operations

Method Endpoint Description
GET /system/health Health check (no auth required)
GET /system/tests Run system tests
POST /system/tests Run specific system tests
POST /system/cache/clear Clear server cache
GET /system/audit-log Query audit log (paginated)

Request/Response Format

Standard Response

{
  "success": true,
  "data": {
    // Response data here
  },
  "meta": {
    "timestamp": "2026-02-20T10:00:00.000Z",
    "requestId": "req_abc123"
  }
}

Paginated Response

{
  "success": true,
  "data": [
    // Array of items
  ],
  "meta": {
    "timestamp": "2026-02-20T10:00:00.000Z",
    "requestId": "req_abc123"
  },
  "pagination": {
    "page": 1,
    "perPage": 20,
    "total": 150,
    "totalPages": 8,
    "hasNext": true,
    "hasPrev": false
  }
}

Query Parameters

Parameter Description Default Max
page Page number 1 -
perPage Items per page 20 100
search Search query - -
status Filter by status - -
plan Filter by plan - -

Rate Limiting

All authenticated requests are rate-limited per API key.

Default Limits

  • Requests per hour: 1000 (configurable via ADMIN_API_RATE_LIMIT)
  • Burst: Not applicable (smooth rate limiting)

Rate Limit Headers

Every response includes rate limit information:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 856
X-RateLimit-Reset: 1708407600

Rate Limit Exceeded Response

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please retry after the reset time.",
    "details": {
      "resetAt": "2026-02-20T11:00:00.000Z"
    }
  },
  "meta": {
    "timestamp": "2026-02-20T10:45:00.000Z",
    "requestId": "req_xyz789"
  }
}

Error Handling

Error Response Format

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {
      // Additional context
    }
  },
  "meta": {
    "timestamp": "2026-02-20T10:00:00.000Z",
    "requestId": "req_abc123"
  }
}

Error Codes

Code HTTP Status Description
MISSING_AUTH_HEADER 401 No Authorization header provided
INVALID_AUTH_SCHEME 401 Invalid authorization scheme (use Bearer)
INVALID_API_KEY 401 API key is invalid
TOKEN_EXPIRED 401 JWT token has expired
INVALID_TOKEN 401 JWT token is malformed or invalid
RATE_LIMIT_EXCEEDED 429 Rate limit exceeded
ENDPOINT_NOT_FOUND 404 Endpoint does not exist
METHOD_NOT_ALLOWED 405 HTTP method not supported
VALIDATION_ERROR 400 Request validation failed
NOT_FOUND 404 Resource not found
INTERNAL_ERROR 500 Internal server error

Examples

cURL Examples

Get JWT Token

curl -X POST https://your-domain.com/api/external/auth/validate \
  -H "Authorization: Bearer sk_live_your_api_key_here"

List Users

curl -X GET "https://your-domain.com/api/external/users?page=1&perPage=10" \
  -H "Authorization: Bearer your_jwt_token_here"

Update User Plan

curl -X PATCH https://your-domain.com/api/external/users/user_123/plan \
  -H "Authorization: Bearer your_jwt_token_here" \
  -H "Content-Type: application/json" \
  -d '{"plan": "professional"}'

Create Model

curl -X POST https://your-domain.com/api/external/models \
  -H "Authorization: Bearer your_jwt_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "gpt-4-turbo",
    "label": "GPT-4 Turbo",
    "tier": "premium",
    "supportsMedia": true
  }'

JavaScript/Node.js Examples

Setup

const API_BASE = 'https://your-domain.com/api/external';
const API_KEY = 'sk_live_your_api_key_here';

let jwtToken = null;
let tokenExpiresAt = null;

async function getJwtToken() {
  if (jwtToken && tokenExpiresAt && Date.now() < tokenExpiresAt) {
    return jwtToken;
  }

  const response = await fetch(`${API_BASE}/auth/validate`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`
    }
  });

  const data = await response.json();
  if (!data.success) {
    throw new Error(data.error.message);
  }

  jwtToken = data.data.token;
  tokenExpiresAt = new Date(data.data.expiresAt).getTime();
  return jwtToken;
}

async function apiRequest(method, path, body = null) {
  const token = await getJwtToken();
  
  const options = {
    method,
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  };

  if (body) {
    options.body = JSON.stringify(body);
  }

  const response = await fetch(`${API_BASE}${path}`, options);
  return response.json();
}

Usage Examples

// List users
const users = await apiRequest('GET', '/users?page=1&perPage=20');
console.log(users);

// Get specific user
const user = await apiRequest('GET', '/users/user_123');
console.log(user);

// Update user plan
const result = await apiRequest('PATCH', '/users/user_123/plan', {
  plan: 'professional'
});
console.log(result);

// Adjust user tokens
const tokensResult = await apiRequest('PATCH', '/users/user_123/tokens', {
  tokens: 1000000,
  operation: 'set'
});
console.log(tokensResult);

// List models
const models = await apiRequest('GET', '/models');
console.log(models);

// Create model
const newModel = await apiRequest('POST', '/models', {
  name: 'claude-3-opus',
  label: 'Claude 3 Opus',
  tier: 'premium',
  supportsMedia: true
});
console.log(newModel);

// Get analytics
const analytics = await apiRequest('GET', '/analytics/overview');
console.log(analytics);

Python Examples

import requests
from datetime import datetime

API_BASE = 'https://your-domain.com/api/external'
API_KEY = 'sk_live_your_api_key_here'

class ExternalAdminAPI:
    def __init__(self, api_base, api_key):
        self.api_base = api_base
        self.api_key = api_key
        self.jwt_token = None
        self.token_expires_at = None

    def get_jwt_token(self):
        if self.jwt_token and self.token_expires_at:
            if datetime.now() < self.token_expires_at:
                return self.jwt_token

        response = requests.post(
            f'{self.api_base}/auth/validate',
            headers={'Authorization': f'Bearer {self.api_key}'}
        )
        data = response.json()
        
        if not data['success']:
            raise Exception(data['error']['message'])
        
        self.jwt_token = data['data']['token']
        self.token_expires_at = datetime.fromisoformat(
            data['data']['expiresAt'].replace('Z', '+00:00')
        )
        return self.jwt_token

    def request(self, method, path, body=None):
        token = self.get_jwt_token()
        headers = {
            'Authorization': f'Bearer {token}',
            'Content-Type': 'application/json'
        }
        
        response = requests.request(
            method,
            f'{self.api_base}{path}',
            headers=headers,
            json=body
        )
        return response.json()

# Usage
api = ExternalAdminAPI(API_BASE, API_KEY)

# List users
users = api.request('GET', '/users?page=1&perPage=20')
print(users)

# Update user plan
result = api.request('PATCH', '/users/user_123/plan', {'plan': 'professional'})
print(result)

Security Best Practices

API Key Management

  1. Never commit API keys to version control

    • Use environment variables
    • Use secrets management (Docker secrets, Kubernetes secrets, AWS Secrets Manager)
  2. Use different keys for different environments

    • sk_test_ prefix for development/testing
    • sk_live_ prefix for production
  3. Rotate keys periodically

    • Generate new keys at least every 90 days
    • Immediately revoke compromised keys
  4. Limit key exposure

    • Only store keys on secure servers
    • Never expose keys in client-side code
    • Use IP whitelisting if possible (future feature)

JWT Token Security

  1. Short token lifetime

    • Default: 1 hour
    • Configure via ADMIN_API_JWT_TTL
  2. Token storage

    • Store tokens in memory, not persistent storage
    • Clear tokens on application shutdown
  3. Token refresh

    • Implement token refresh before expiration
    • Handle TOKEN_EXPIRED errors gracefully

Network Security

  1. Use HTTPS

    • Never transmit API keys over HTTP
    • Ensure SSL/TLS certificates are valid
  2. IP Restrictions (if applicable)

    • Restrict API access to known IP ranges
    • Use VPN or private networks
  3. Rate Limiting

    • Respect rate limit headers
    • Implement client-side throttling
    • Handle 429 responses with exponential backoff

Audit & Monitoring

  1. Monitor API Usage

    • Review audit logs regularly
    • Set up alerts for unusual activity
  2. Log Retention

    • Maintain audit logs for compliance
    • Use /system/audit-log endpoint to query logs
  3. Anomaly Detection

    • Monitor for unusual request patterns
    • Alert on failed authentication attempts

Troubleshooting

Common Issues

"API_KEY_NOT_CONFIGURED"

Cause: ADMIN_API_KEY environment variable not set.

Solution: Set the environment variable and restart the server:

export ADMIN_API_KEY=sk_live_your_secure_key_here

"INVALID_API_KEY"

Cause: API key doesn't match the configured key.

Solution:

  1. Verify the API key is correct
  2. Check for extra whitespace or encoding issues
  3. Ensure the key prefix is correct (sk_live_ or sk_test_)

"TOKEN_EXPIRED"

Cause: JWT token has exceeded its lifetime.

Solution: Request a new token using the API key:

POST /api/external/auth/validate
Authorization: Bearer sk_live_your_api_key

"RATE_LIMIT_EXCEEDED"

Cause: Too many requests in the current hour.

Solution:

  1. Wait until the reset time (check X-RateLimit-Reset header)
  2. Reduce request frequency
  3. Increase rate limit via ADMIN_API_RATE_LIMIT environment variable

Debugging Tips

  1. Enable verbose logging

    • Check server logs for detailed error messages
    • Look for [ExternalAPI] prefixed log entries
  2. Test with health endpoint

    curl https://your-domain.com/api/external/system/health
    
  3. Verify authentication

    curl -X GET https://your-domain.com/api/external/auth/me \
      -H "Authorization: Bearer your_token"
    

Version History

Version Date Changes
1.0.0 2026-02-20 Initial release

Support

For issues or questions:

  • GitHub Issues: [project-repo]/issues
  • Documentation: This file
  • Server Logs: Check container logs for [ExternalAPI] entries