Authentication

API keys, scopes, quotas, and subscription tiers.

3 min read

API Key Format#

All API requests require a key in the Authorization header:

Authorization: Bearer ck_live_aB3kLm9xPqR7wZ2nYhJ4cD6fG8tV0sE

Keys follow the format ck_live_ + 32 alphanumeric characters. They are SHA-256 hashed before storage — Chamelingo never stores your raw key.

Scopes#

Each API key is granted one or more scopes that control endpoint access:

ScopeEndpoints
tutorChat, conversations, usage
decksFlashcard decks, cards, imports, reviews, export
progressXP, insights, vocabulary analytics, activity
curriculumUnits, lessons, grammar, vocabulary search
exercisesAI exercise generation
pronunciationPronunciation scoring
webhooksWebhook registration and management

By default, keys are created with ["tutor"]. Request only the scopes your integration needs — principle of least privilege.

bash
curl -X POST https://api.chamelingo.com/api/v1/keys \
  -H "Cookie: better-auth.session_token=YOUR_SESSION" \
  -H "Content-Type: application/json" \
  -d '{"name": "Study Bot", "scopes": ["tutor", "decks", "progress"]}'

Key Limits#

  • Maximum 5 active keys per user account
  • Keys can be revoked (soft delete) but not un-revoked
  • The full key is shown only at creation time
  • Revoked keys immediately stop working

Quotas#

API requests consume your Chamelingo subscription quota. Usage is shared between the web app and the API:

TierDaily AI MessagesPrice
Free5$0
Pro500$9.99/month
LifetimeUnlimited$149 once

Check your current usage anytime:

bash
curl https://api.chamelingo.com/api/v1/usage \
  -H "Authorization: Bearer ck_live_YOUR_KEY_HERE"
Warning

When you hit your daily quota, chat requests return 402 Payment Required until the quota resets at midnight UTC.

Errors#

Missing or invalid keys return 401:

JSON
{
  "success": false,
  "error": {
    "title": "Sign in required",
    "message": "Invalid or expired API key.",
    "retryable": false,
    "statusCode": 401,
    "code": "UNAUTHENTICATED"
  }
}

Accessing an endpoint without the required scope returns 403:

JSON
{
  "success": false,
  "error": {
    "title": "Access denied",
    "message": "This API key does not have the \"decks\" scope.",
    "retryable": false,
    "statusCode": 403,
    "code": "FORBIDDEN"
  }
}