Skip to content

API Reference

Raw HTTP endpoints for implementing Keycrate authentication.

Quick Start

We recommend using a pre-built SDK for the best developer experience:

  • Python - pip install keycrate
  • JavaScript - npm install keycrate
  • Go - go get github.com/keycrate/keycrate-sdk/sdks/go
  • C# - dotnet add package Keycrate
  • Rust - cargo add keycrate

Not using one of these languages? Continue below to implement the HTTP API directly.


Base URL

https://api.keycrate.dev

Authentication Endpoint

POST /auth

Authenticate a user using either a license key or a username/password combination. Validates blacklist, application, team, subscription, HWID, and license status. Returns sanitized license data.

Request Parameters

ParameterTypeRequiredDescription
app_idstring (UUID)YesApplication ID in UUID format
licensestringOne of twoLicense key for authentication
usernamestringOne of twoUsername for password authentication
passwordstringOne of twoPassword (bcrypt hashed in DB)
hwidstringNoHardware ID of the device

Authentication Methods

You must provide either license OR both username and password. At least one authentication method is required.

Example Requests

License Key:

json
{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "license": "XXXX-XXXX-XXXX-XXXX"
}

License Key + HWID:

json
{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "license": "XXXX-XXXX-XXXX-XXXX",
    "hwid": "44454C4C-5900-1038-8059-B5C04F46334A"
}

Username/Password:

json
{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "username": "user@example.com",
    "password": "secure_password"
}

Username/Password + HWID:

json
{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "username": "user@example.com",
    "password": "secure_password",
    "hwid": "44454C4C-5900-1038-8059-B5C04F46334A"
}

Responses

✅ 200 OK - Authentication Successful

User credentials validated and license is active.

json
{
    "success": true,
    "message": "LICENSE_VERIFIED_USED_AND_LOCKED_KEY",
    "data": {
        "key": "XXXX-XXXX-XXXX-XXXX",
        "created_at": "2024-01-15T10:30:00.000Z",
        "expires_at": "2025-01-15T10:30:00.000Z",
        "initial_duration": "31536000",
        "first_used_at": "2024-01-15T10:45:00.000Z",
        "hwid_lock": true,
        "last_hwid_reset_at": null,
        "hwid_reset_cooldown": 86400,
        "hwid_reset_allowed": true,
        "username": "user@example.com",
        "last_login": "2024-01-20T14:22:00.000Z",
        "subscription_level": 2,
        "subscription_name": "Professional"
    }
}

Success Message Codes:

License State Indicators
  • LICENSE_VERIFIED_UNUSED_AND_UNLOCKED_KEY - First activation, no HWID lock
  • LICENSE_VERIFIED_UNUSED_AND_LOCKED_KEY - First activation, with HWID lock
  • LICENSE_VERIFIED_USED_AND_UNLOCKED_KEY - Subsequent use, no HWID lock
  • LICENSE_VERIFIED_USED_AND_LOCKED_KEY - Subsequent use, with HWID lock

Response Data Fields:

FieldTypeDescription
keystringUnique license key identifier
created_atdatetimeWhen the license was created
expires_atdatetimeWhen the license expires
initial_durationstringDuration in seconds
first_used_atdatetime | nullFirst activation timestamp
hwid_lockbooleanWhether HWID locking is enabled
last_hwid_reset_atdatetime | nullLast HWID reset timestamp
hwid_reset_cooldownnumberSeconds until next HWID reset allowed
hwid_reset_allowedbooleanWhether HWID reset is available now
usernamestring | nullAssociated username
last_logindatetimeLast authentication timestamp
subscription_levelintegerSubscription tier level
subscription_namestringSubscription plan name

⚠️ 400 Bad Request

Invalid request - Invalid JSON, missing required fields, or wrong format.

Common Issues

  • Invalid JSON - Malformed JSON in request body
  • Missing app_id - Application ID is required for all requests
  • Invalid UUID - App ID must be a valid UUID format
  • No Auth Method - Missing both license and username/password :::

Error Messages:

- Invalid JSON in request body
- App ID is required
- Invalid App ID format (must be a valid UUID)
- No valid authentication method provided (missing license key or username/password)

🚫 403 Forbidden

Authentication failed - Invalid credentials, expired, blacklisted, or validation failed.

Authentication Failures:

Invalid Credentials or State

CodeDescription
LICENSE_NOT_FOUNDLicense key does not exist
INVALID_USERNAME_OR_PASSWORDWrong username or password
LICENSE_NOT_ACTIVELicense status is not 'active'
LICENSE_EXPIREDLicense has passed expiration date

HWID Validation:

Hardware ID Issues

CodeDescription
HWID_NOT_PROVIDEDLicense requires HWID but none provided
HWID_MISMATCHProvided HWID doesn't match stored HWID
DEVICE_ALREADY_REGISTERED_WITH_OTHER_LICENSEHWID is bound to different license

Application & Team Validation:

Configuration Issues

CodeDescription
INVALID_APP_IDApplication ID is invalid or missing
APPLICATION_NOT_FOUNDApplication does not exist
APPLICATION_NOT_ACTIVEApplication status is not 'active'
TEAM_ERRORTeam not found or plan expired

Subscription Validation:

Subscription Issues

CodeDescription
SUBSCRIPTION_ERRORSubscription not found
SUBSCRIPTION_NOT_ACTIVESubscription status is not 'active'

Blacklist Blocks:

Geographic & Security Blocks

CodeDescription
COUNTRY_BLACKLISTEDRequest country is blacklisted
ASN_BLACKLISTEDRequest ASN is blacklisted
IP_BLACKLISTEDRequest IP address is blacklisted
HWID_BLACKLISTEDHardware ID is blacklisted

💥 500 Internal Server Error

Server error - An unexpected error occurred processing the request.

Debug Information

Response includes debug_error field only when DEBUG=true environment variable is set.

json
{
    "success": false,
    "message": "Server error occurred",
    "debug_error": "DB_ERROR: connection timeout"
}

Registration Endpoint

POST /register

Register or update credentials for a license key. Associates a username and password with an existing license, allowing authentication via credentials instead of just the license key.

Request Parameters

ParameterTypeRequiredDescription
app_idstring (UUID)YesYour application ID in UUID format
licensestringYesLicense key to register credentials for
usernamestringYesUsername for this license
passwordstringYesPassword (will be bcrypt hashed server-side)

Registration Flow

All fields are required. The password is automatically hashed using bcrypt before storage.

Example Request

json
{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "license": "XXXX-XXXX-XXXX-XXXX",
    "username": "newuser@example.com",
    "password": "securepassword123"
}

Responses

✅ 200 OK - Credentials Updated

Credentials successfully registered and stored.

json
{
    "success": true,
    "message": "License credentials updated successfully"
}

⚠️ 400 Bad Request

Missing required fields or invalid JSON.

Missing Fields

  • "License key is required" - license parameter missing
  • "Username is required" - username parameter missing
  • "Password is required" - password parameter missing
  • "App ID is required" - app_id parameter missing
  • "Invalid JSON in request body" - Malformed JSON :::

💥 500 Internal Server Error

Server error during credential update.

json
{
    "success": false,
    "message": "Server error occurred"
}

Possible Issues

  • "Failed to update license credentials" - Database update failed
  • License key doesn't exist in database
  • Database connection issues
  • Invalid app_id and license combination :::

Debug Information: When DEBUG=true environment variable is set, responses include debug_error and debug_type fields for troubleshooting.


CORS Support

Both endpoints support Cross-Origin Resource Sharing (CORS) for browser-based flows.

CORS Configuration

  • Access-Control-Allow-Origin: *
  • Access-Control-Allow-Methods: POST, OPTIONS
  • Access-Control-Allow-Headers: Content-Type, Authorization
  • Access-Control-Max-Age: 86400

An OPTIONS request to either endpoint will return a 204 response.


HTTP Details

Headers

Content-Type: application/json

Methods

  • POST for both /auth and /register
  • OPTIONS for CORS preflight

Integration Examples

cURL

Authenticate with License:

bash
curl -X POST https://api.keycrate.dev/auth \
  -H "Content-Type: application/json" \
  -d '{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "license": "XXXX-XXXX-XXXX-XXXX"
  }'

Authenticate with Username/Password:

bash
curl -X POST https://api.keycrate.dev/auth \
  -H "Content-Type: application/json" \
  -d '{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "username": "user@example.com",
    "password": "password123"
  }'

Register Credentials:

bash
curl -X POST https://api.keycrate.dev/register \
  -H "Content-Type: application/json" \
  -d '{
    "app_id": "550e8400-e29b-41d4-a716-446655440000",
    "license": "XXXX-XXXX-XXXX-XXXX",
    "username": "newuser@example.com",
    "password": "securepassword"
  }'

JavaScript/Fetch

Authenticate:

javascript
const response = await fetch("https://api.keycrate.dev/auth", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
    },
    body: JSON.stringify({
        app_id: "550e8400-e29b-41d4-a716-446655440000",
        license: "XXXX-XXXX-XXXX-XXXX",
    }),
});

const data = await response.json();
if (data.success) {
    console.log("Licensed:", data.data);
} else {
    console.error("Auth failed:", data.message);
}

Python

Authenticate:

python
import requests

response = requests.post(
    'https://api.keycrate.dev/auth',
    json={
        'app_id': '550e8400-e29b-41d4-a716-446655440000',
        'license': 'XXXX-XXXX-XXXX-XXXX'
    }
)

data = response.json()
if data['success']:
    print(f"License expires at: {data['data']['expires_at']}")
else:
    print(f"Error: {data['message']}")

Validation Flow

Processing Order

  1. JSON Validation - Parse and validate request body
  2. App ID Validation - Check UUID format and existence
  3. Blacklist Checks - Country, ASN, IP, HWID blacklists
  4. Authentication - Verify license key or username/password
  5. License Validation - Check status and active state
  6. Application Validation - Verify app exists and is active
  7. Team Validation - Verify team exists and plan not expired
  8. Subscription Validation - Verify subscription exists and active
  9. HWID Processing - Handle first-time or subsequent activation

License Lifecycle

Creation

First Activation (expires_at set, hwid optionally bound)

Subsequent Uses (last_login updated, hwid validated)

Expiration or Deactivation

First Activation

  • License first_used_at is set to current timestamp
  • expires_at is calculated from initial_duration
  • If HWID locking enabled, device ID is bound
  • Generates one of two success codes (locked/unlocked)

Subsequent Uses

  • License last_login is updated
  • HWID is validated against stored value (if locked)
  • Expiration date is checked
  • Generates one of two success codes (locked/unlocked)

Error Handling Best Practices

Implementation Guidelines

  1. Check the success field (true/false) to determine outcome
  2. Use the message field for display or programmatic matching
  3. Implement retries for 5xx errors with exponential backoff
  4. Handle timeouts as authentication failures
  5. Log failed attempts server-side for security monitoring
  6. Cache successful responses when appropriate (consider expiration)
  7. Never log passwords or full license keys
  8. Validate app_id format before making requests