Authentication

Secure your API calls with Bearer token authentication

Overview

AppHighway uses Bearer token authentication for all API endpoints. Each user can create multiple API tokens with custom names, scopes, and rate limits.

Multi-Token Support

Create multiple API tokens for different environments (production, staging, development) or applications.

Token Scopes

Control which APIs each token can access. Useful for limiting permissions for specific use cases.

Rate Limiting

Each token has its own rate limit (default: 60 requests per minute). Customize limits based on your needs.

Optional Expiration

Set expiration dates for tokens to enhance security. Tokens without expiration dates remain valid indefinitely.

Getting Started

Follow these steps to start using AppHighway APIs with authentication:

1. Sign up or Sign in

Create an AppHighway account or sign in to your existing account via the dashboard.

2. Create an API Token

Navigate to the Tokens page in your dashboard and create a new API token. Give it a descriptive name (e.g., 'Production Server', 'Mobile App').

3. Use Your Token

Include your API token in the Authorization header of every API request as a Bearer token.

Creating API Tokens

Step-by-step guide to creating and managing your API tokens

Creating a Token via Dashboard

  1. Navigate to your AppHighway Dashboard
  2. Click on 'Tokens' in the sidebar navigation
  3. Click the 'Create New Token' button
  4. Enter a descriptive name for your token (e.g., 'Production Server', 'Mobile App')
  5. Select the API scopes (permissions) for this token
  6. Set the rate limit (default: 60 requests per minute)
  7. Optionally set an expiration date for enhanced security
  8. Click 'Create Token' and immediately copy the generated token to a secure location

Token Naming Best Practices

Use clear, descriptive names to identify the purpose and environment of each token:

Production ServerDevelopment EnvironmentMobile App - iOSCI/CD PipelineTesting & QA

Token Scopes

Control which APIs your token can access:

All APIs: Full access to all available APIs (use with caution)
Custom Scopes: Select only the specific APIs your application needs (recommended)

Making Authenticated Requests

Include your API token in the Authorization header using the Bearer scheme:

Using cURL

bash
curl -X POST https://apphighway.com/api/v1/structify \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "John Doe is 35 years old and lives in New York",
    "schema": {
      "name": "string",
      "age": "number",
      "city": "string"
    }
  }'

Using Node.js

api-client.js
import fetch from 'node-fetch';

const API_TOKEN = 'your_api_token_here';
const API_URL = 'https://apphighway.com/api/v1';

async function callAPI(endpoint, data) {
  const response = await fetch(`${API_URL}/${endpoint}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
  });

  if (!response.ok) {
    throw new Error(`API call failed: ${response.statusText}`);
  }

  return response.json();
}

// Example: Use Structify API
const result = await callAPI('structify', {
  text: 'John Doe is 35 years old',
  schema: { name: 'string', age: 'number' }
});

console.log(result);

Using Python

api_client.py
import requests

API_TOKEN = 'your_api_token_here'
API_URL = 'https://apphighway.com/api/v1'

def call_api(endpoint, data):
    headers = {
        'Authorization': f'Bearer {API_TOKEN}',
        'Content-Type': 'application/json'
    }

    response = requests.post(
        f'{API_URL}/{endpoint}',
        headers=headers,
        json=data
    )

    response.raise_for_status()
    return response.json()

# Example: Use Structify API
result = call_api('structify', {
    'text': 'John Doe is 35 years old',
    'schema': {'name': 'string', 'age': 'number'}
})

print(result)

Advanced Usage Examples

Production-ready examples with error handling, retry logic, and best practices

TypeScript Client with Error Handling

A robust TypeScript client with type safety and comprehensive error handling for production use

apphighway-client.ts
import axios, { AxiosError } from 'axios';

const API_TOKEN = process.env.APPHIGHWAY_API_TOKEN!;
const API_URL = 'https://apphighway.com/api/v1';

interface APIError {
  error: {
    code: string;
    message: string;
    details: string;
  };
}

class AppHighwayClient {
  private token: string;
  private baseURL: string;

  constructor(token: string, baseURL = API_URL) {
    this.token = token;
    this.baseURL = baseURL;
  }

  async call<T = unknown>(
    endpoint: string,
    data: Record<string, unknown>
  ): Promise<T> {
    try {
      const response = await axios.post<T>(
        `${this.baseURL}/${endpoint}`,
        data,
        {
          headers: {
            'Authorization': `Bearer ${this.token}`,
            'Content-Type': 'application/json',
          },
        }
      );

      return response.data;
    } catch (error) {
      if (axios.isAxiosError(error)) {
        const apiError = error.response?.data as APIError;

        if (apiError?.error?.code === 'INSUFFICIENT_POINTS') {
          throw new Error('Insufficient points. Please purchase more points.');
        }

        if (apiError?.error?.code === 'UNAUTHORIZED') {
          throw new Error('Invalid API token. Please check your credentials.');
        }

        if (error.response?.status === 429) {
          throw new Error('Rate limit exceeded. Please wait before retrying.');
        }
      }

      throw error;
    }
  }
}

// Usage
const client = new AppHighwayClient(API_TOKEN);

const result = await client.call('structify', {
  text: 'John Doe is 35 years old',
  schema: { name: 'string', age: 'number' }
});

Implementing Retry Logic

Handle transient errors and rate limits with exponential backoff retry strategy

api-with-retry.ts
import fetch from 'node-fetch';

const API_TOKEN = process.env.APPHIGHWAY_API_TOKEN;
const API_URL = 'https://apphighway.com/api/v1';

async function callAPIWithRetry(
  endpoint: string,
  data: object,
  maxRetries = 3
) {
  let lastError;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(`${API_URL}/${endpoint}`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${API_TOKEN}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(data),
      });

      // Don't retry on client errors (4xx except 429)
      if (response.status >= 400 && response.status < 500 && response.status !== 429) {
        const error = await response.json();
        throw new Error(`API Error: ${error.error.message}`);
      }

      // Retry on server errors (5xx) or rate limits (429)
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }

      return await response.json();
    } catch (error) {
      lastError = error;

      if (attempt < maxRetries - 1) {
        // Exponential backoff: 1s, 2s, 4s
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Retry attempt ${attempt + 1} after ${delay}ms`);
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
  }

  throw lastError;
}

// Usage
const result = await callAPIWithRetry('structify', {
  text: 'John Doe is 35 years old',
  schema: { name: 'string', age: 'number' }
});

Go Implementation

Production-ready Go client with proper error handling and HTTP best practices

main.go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

const apiURL = "https://apphighway.com/api/v1"

type APIClient struct {
    Token      string
    HTTPClient *http.Client
}

type APIError struct {
    Error struct {
        Code    string `json:"code"`
        Message string `json:"message"`
        Details string `json:"details"`
    } `json:"error"`
}

func NewClient(token string) *APIClient {
    return &APIClient{
        Token:      token,
        HTTPClient: &http.Client{},
    }
}

func (c *APIClient) Call(endpoint string, data interface{}) ([]byte, error) {
    jsonData, err := json.Marshal(data)
    if err != nil {
        return nil, fmt.Errorf("failed to marshal data: %w", err)
    }

    req, err := http.NewRequest(
        "POST",
        fmt.Sprintf("%s/%s", apiURL, endpoint),
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        return nil, fmt.Errorf("failed to create request: %w", err)
    }

    req.Header.Set("Authorization", "Bearer "+c.Token)
    req.Header.Set("Content-Type", "application/json")

    resp, err := c.HTTPClient.Do(req)
    if err != nil {
        return nil, fmt.Errorf("request failed: %w", err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        return nil, fmt.Errorf("failed to read response: %w", err)
    }

    if resp.StatusCode != http.StatusOK {
        var apiErr APIError
        if err := json.Unmarshal(body, &apiErr); err == nil {
            return nil, fmt.Errorf("API error: %s", apiErr.Error.Message)
        }
        return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
    }

    return body, nil
}

func main() {
    client := NewClient(os.Getenv("APPHIGHWAY_API_TOKEN"))

    data := map[string]interface{}{
        "text": "John Doe is 35 years old",
        "schema": map[string]string{
            "name": "string",
            "age":  "number",
        },
    }

    result, err := client.Call("structify", data)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    fmt.Printf("Result: %s\n", result)
}

Token Management

Best practices for managing your API tokens:

Descriptive Names

Use clear, descriptive names for your tokens to identify their purpose and environment. Examples:

Production ServerDevelopment EnvironmentMobile AppCI/CD Pipeline

Token Rotation

Regularly rotate your API tokens for enhanced security. Create a new token, update your applications, and delete the old token.

Immediate Revocation

If a token is compromised, immediately revoke it from your dashboard to prevent unauthorized access.

Error Handling

Common authentication-related errors and how to handle them:

401

Unauthorized

Your API token is invalid, expired, or missing. Verify that you're sending the correct token in the Authorization header.

json
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired API token",
    "details": "The provided token is not valid or has expired"
  }
}
402

Payment Required (Insufficient Points)

Your account doesn't have enough points to make this API call. Purchase more points to continue.

json
{
  "error": {
    "code": "INSUFFICIENT_POINTS",
    "message": "Insufficient points. Required: 3, Available: 1",
    "details": "Please purchase more points to continue using the API"
  }
}
429

Too Many Requests

You've exceeded the rate limit for your token. Wait before making additional requests or upgrade your rate limit.

Token Security Best Practices

Critical security guidelines for protecting your API tokens and preventing unauthorized access

Secure Token Storage

Never expose tokens in your codebase or version control

Use Environment Variables

Store tokens in environment variables (.env files) and never commit them to git. Add .env to your .gitignore file.

Use Secrets Management Systems

For production environments, use dedicated secrets management solutions like AWS Secrets Manager, HashiCorp Vault, or Azure Key Vault.

Never Hardcode Tokens

Avoid hardcoding tokens directly in source code, configuration files, or client-side applications.

Never Expose in Client-Side Code

API tokens should only be used in server-side code. Never include them in frontend JavaScript, mobile apps, or any client-facing code.

Token Rotation

Regularly rotate tokens to minimize security risks

Rotate Every 90 Days

Implement a regular rotation schedule (every 90 days recommended) to limit the exposure window if a token is compromised.

Zero-Downtime Rotation Process

Create a new token, update your applications to use both tokens temporarily, then remove the old token once all systems are migrated.

Automate Rotation

Use automation tools and CI/CD pipelines to streamline the token rotation process and reduce manual errors.

Access Control & Scoping

Implement the principle of least privilege

Use Minimal Scopes

Only grant access to the specific APIs your application needs. Avoid using tokens with full access unless absolutely necessary.

Separate Tokens per Environment

Use different tokens for production, staging, and development environments. Never reuse production tokens in lower environments.

One Token per Application

Create separate tokens for each application or service. This makes it easier to track usage and revoke access when needed.

Monitoring & Detection

Detect and respond to suspicious activity

Monitor Token Usage

Regularly review token usage in your dashboard. Look for unexpected spikes, unusual API calls, or access from unfamiliar locations.

Set Up Alerts

Configure alerts for unusual activity patterns, such as rate limit violations, failed authentication attempts, or API calls from unexpected IPs.

Implement Comprehensive Logging

Log all API requests with timestamps, endpoints called, and response codes. This helps with debugging and security audits.

Incident Response

Act quickly if a token is compromised

Revoke Compromised Tokens Immediately

If you suspect a token has been exposed or compromised, revoke it immediately from your dashboard to prevent unauthorized access.

Assess the Impact

Review API usage logs to determine what actions were taken with the compromised token and assess any potential data exposure.

Create a New Token

After revoking a compromised token, create a new token with appropriate scopes and update your applications.

Review Points Usage

Check your points balance and usage history. Unauthorized API calls may have consumed points. Contact support if you notice fraudulent usage.

Secure Transport

Protect tokens during transmission

Always Use HTTPS

Only make API calls over HTTPS to encrypt tokens in transit. Never send tokens over unencrypted HTTP connections.

Verify TLS Certificates

Ensure your HTTP client verifies SSL/TLS certificates to prevent man-in-the-middle attacks.

Avoid Logging Tokens

Never log full API tokens in application logs, error messages, or debugging output. If logging is necessary, redact or mask the token value.

Compliance & Governance

Maintain compliance with security standards

Document Token Usage

Maintain an inventory of all active tokens, their purposes, owners, and expiration dates.

Regular Access Reviews

Periodically review all active tokens and revoke those that are no longer needed or belong to former team members.

Set Expiration Dates

For temporary use cases or short-term projects, set token expiration dates to automatically limit their lifetime.

Best Practices

Follow these security best practices when using AppHighway APIs:

  • Store API tokens in environment variables, never hardcode them in your source code
  • Use different tokens for different environments (production, staging, development)
  • Set appropriate scopes to limit token permissions to only the APIs you need
  • Implement token rotation every 90 days for enhanced security
  • Monitor token usage in your dashboard to detect suspicious activity
  • Set expiration dates for tokens that are only needed temporarily
Authentication - AppHighway API Documentation