Skip to main content

Overview

API keys are the primary authentication mechanism for the InstaView API. Each key is cryptographically secure, scoped to a specific company, and has granular permissions through scopes.

Key Architecture

Security Features

InstaView API keys are built with enterprise-grade security:

HMAC-SHA256 Hashing

Keyed hashing with a strong server-side secret; plaintext keys are never stored.

256-bit Entropy

Cryptographically secure random key generation

Audit Logging

Complete audit trail for all key lifecycle events

Company Isolation

Keys are strictly scoped to prevent cross-company access

Key Components

Every API key contains:
  • Prefix: Identifies key type (sk_ for secret keys)
  • Environment: live for production, test for sandbox
  • Identifier: Unique 32-character string
  • Metadata: Name, scopes, creation date, etc.

Creating API Keys

Via Dashboard

1

Navigate to API Keys

Go to SettingsAPI Keys in your dashboard
2

Create New Key

Click Create API Key
3

Configure Details

{
  "name": "Production Integration",
  "scopes": [
    "read:jobs",
    "write:jobs",
    "read:candidates",
    "write:candidates",
    "read:interviews",
    "write:interviews"
  ],
  "expiresAt": "2025-12-31T23:59:59Z",  // Optional
  "allowedIPs": [                         // Optional
    "192.168.1.0/24",
    "10.0.0.100"
  ]
}
4

Save the Key

Important: Copy your API key immediately - it will only be shown once!

Via API (Admin Only)

// Requires admin JWT authentication
const response = await fetch("https://api.instaview.sk/api-keys", {
  method: "POST",
  headers: {
    Authorization: "Bearer <admin-jwt>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    companyId: "550e8400-e29b-41d4-a716-446655440000",
    name: "Production Integration",
    scopes: ["read:jobs", "write:jobs", "read:candidates", "write:candidates"],
  }),
});

const { data } = await response.json();
console.log("API Key:", data.key); // Save this securely!

Scope Configuration

Choosing the Right Scopes

Apply the principle of least privilege:
{
  "scopes": [
    "read:jobs",
    "read:candidates",
    "read:interviews",
    "read:billing"
  ]
}
Read-only access for dashboards and reporting.

Scope Validation

When making API requests, scopes are validated:
// ✅ Success: Key has write:jobs scope
POST /jobs
Authorization: Bearer sk_live_xxx (scopes: ["write:jobs"])

// ❌ Error: Key lacks write:jobs scope
POST /jobs
Authorization: Bearer sk_live_yyy (scopes: ["read:jobs"])

// Response:
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_PERMISSIONS",
    "message": "This API key does not have the required scope: write:jobs"
  }
}

Key Types

Regular API Keys

Standard keys associated with a single company:
// Automatically scoped to the key's company
GET /jobs
Authorization: Bearer sk_live_company_a_key

// Returns only jobs for Company A
Use Cases:
  • Direct integrations
  • Internal tools
  • Customer-facing applications

ATS Integration Keys

Special keys for multi-tenant ATS platforms:
// Must specify companyId for resource access
GET /jobs?companyId=company-b-uuid
Authorization: Bearer sk_live_ats_integration_key

// Can create new companies
POST /companies
Authorization: Bearer sk_live_ats_integration_key
Use Cases:
  • Greenhouse, Lever, or other ATS integrations
  • Multi-tenant recruitment platforms
  • White-label solutions
ATS keys can only be created by InstaView administrators. Contact support to request ATS integration access.

Advanced Configuration

IP Allowlists

Restrict key usage to specific IP addresses or ranges:
{
  "name": "Production Integration",
  "allowedIPs": [
    "192.168.1.100", // Single IP
    "10.0.0.0/8", // CIDR notation
    "172.16.0.0/12" // Private network range
  ]
}
Requests from non-allowlisted IPs will be rejected:
{
  "success": false,
  "error": {
    "code": "IP_NOT_ALLOWED",
    "message": "Request IP address not in allowlist"
  }
}

Expiration Dates

Set automatic key expiration for temporary access:
{
  "name": "Contractor Access",
  "expiresAt": "2025-03-31T23:59:59Z",
  "scopes": ["read:candidates"]
}
Best Practices:
  • Use expiration for contractor/temporary access
  • Set 90-day expiration for high-privilege keys
  • Receive email notifications 7 days before expiry

Metadata and Tags

Add custom metadata for organization:
{
  "name": "Production Integration",
  "metadata": {
    "tags": ["production", "primary"],
    "environment": "us-east-1",
    "owner": "[email protected]",
    "project": "candidate-sync"
  }
}

Key Lifecycle Management

Monitoring Usage

Track key usage in the dashboard:
  • Last Used: Timestamp of most recent request
  • Request Count: Total API calls made
  • Error Rate: Failed requests percentage
  • Top Endpoints: Most frequently accessed endpoints

Rotating Keys

Regular rotation improves security:
1

Create New Key

Generate a replacement key with the same scopes
2

Update Applications

Deploy the new key to all applications
3

Monitor Old Key

Verify traffic has moved to the new key
4

Revoke Old Key

Once traffic has fully migrated, revoke the old key
Recommended Rotation Schedule:
  • High-privilege keys: Every 90 days
  • Read-only keys: Every 180 days
  • Compromised keys: Immediately

Suspending Keys

Temporarily disable a key without deletion:
// Via dashboard or API
PATCH /api-keys/{keyId}
{
  "suspended": true,
  "suspensionReason": "Temporary maintenance"
}
Use Cases:
  • Investigating suspicious activity
  • Temporary service maintenance
  • Debugging integration issues

Revoking Keys

Permanently revoke a compromised key:
Revocation is permanent! Revoked keys cannot be restored. Create a new key if needed.
DELETE /api-keys/{keyId}
{
  "revocationReason": "Key compromised in security incident"
}
All subsequent requests with the revoked key will fail:
{
  "success": false,
  "error": {
    "code": "API_KEY_REVOKED",
    "message": "This API key has been revoked"
  }
}

Security Best Practices

Don’t do this:
const apiKey = 'sk_live_1234567890abcdef'; // Hardcoded!
Do this instead:
const apiKey = process.env.INSTAVIEW_API_KEY;
  • Production: sk_live_xxx - Staging: sk_test_xxx - Development: sk_test_yyy Never use production keys in non-production environments.
// Graceful key rotation
const primaryKey = process.env.INSTAVIEW_PRIMARY_KEY;
const fallbackKey = process.env.INSTAVIEW_FALLBACK_KEY;

async function makeRequest(url, options) {
  try {
    return await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        'Authorization': `Bearer ${primaryKey}`
      }
    });
  } catch (error) {
    if (error.status === 401) {
      // Primary key failed, try fallback
      return await fetch(url, {
        ...options,
        headers: {
        ...options.headers,
        'Authorization': `Bearer ${fallbackKey}`
        }
      });
    }
    throw error;
  }
}
Set up alerts for: - Unusual request volumes - Requests from unexpected IPs - High error rates - After-hours usage (if unexpected)
When your application runs from fixed infrastructure:
{
  "allowedIPs": [
    "52.1.2.3",      // Production server 1
    "52.1.2.4",      // Production server 2
    "10.0.0.0/16"    // VPC network
  ]
}
Note: All API requests must use the Authorization: Bearer header with your API key.

Audit Logs

All API key events are logged for security and compliance:

Logged Events

  • Key Creation: Who created it, when, and with what scopes
  • Authentication: Every successful and failed authentication
  • Scope Changes: Modifications to key permissions
  • Suspension/Revocation: Status changes with reasons
  • Configuration Changes: IP allowlist, expiration date updates

Accessing Audit Logs

// Via dashboard: Security → Audit Logs

// Filter by key ID
GET /api-keys/{keyId}/audit-logs

// Filter by event type
GET /api-keys/{keyId}/audit-logs?eventType=authentication_failed

// Date range
GET /api-keys/{keyId}/audit-logs?from=2024-01-01&to=2024-01-31

Example Audit Log Entry

{
  "id": "log_1234567890",
  "eventType": "authentication_success",
  "apiKeyId": "key_xxx",
  "timestamp": "2024-01-15T10:30:00Z",
  "ipAddress": "192.168.1.100",
  "userAgent": "MyApp/1.0",
  "endpoint": "/jobs",
  "metadata": {
    "companyId": "550e8400-e29b-41d4-a716-446655440000",
    "scopes": ["read:jobs", "write:jobs"]
  }
}

Troubleshooting

Possible Causes:
  • Invalid API key format
  • Revoked or expired key
  • Suspended key
  • Key not properly set in headers
Solutions:
  • Verify key format: sk_live_xxx or sk_test_xxx
  • Check key status in dashboard
  • Ensure header is Authorization: Bearer sk_xxx
Possible Causes: - Insufficient scopes - IP not in allowlist - Attempting cross-company access Solutions: - Check required scope in error message - Verify your IP is allowlisted - Confirm you’re accessing resources in your company
Possible Causes:
  • Exceeded rate limit
  • Too many requests in short time
Solutions:

Next Steps