API Reference

Base URL: http://localhost:3005/v1  ·  Production: https://careerlm-api.careerstudiomax.com/v1

Authentication

Pass your API key in the X-Api-Key header on every request.

All requests
curl -H "X-Api-Key: csk_free_v1_..." ...

Key format: csk_(live|test|free)_v1_[48 hex characters]. Keys are shown once at creation — store them immediately. To rotate, use POST /developer/keys/:id/rotate.

Errors

All errors return a consistent JSON envelope:

Error shape
{
  "error": {
    "code":    "missing_cv_text",
    "message": "cv_text is required",
    "docs":    "https://careerstudiomax.com/api/docs#cv-score"
  }
}
CodeHTTPMeaning
invalid_api_key401Key not found or malformed
daily_limit_exceeded429Over daily request limit — resets at midnight UTC
rate_limit_exceeded429Over per-minute RPM limit — check Retry-After header
tier_required403Feature needs a higher plan
content_policy_violation422Request blocked by career ethics guardrails
model_unavailable503Career AI gateway is temporarily unreachable
request_timeout504Model inference timed out (60s limit)

Rate limits

TierRequests/dayRPM
FREE1,00010
PRO10,00060
PLUS100,000200
ENTERPRISEUnlimited1,000

Daily counters reset at 00:00 UTC. RPM limits are per-key sliding windows. The Retry-After header on 429s gives seconds until reset.

Models

NameSpeedQualityTierMax tokens
careerlm-flashFastestGoodFREE+300
careerlm-standardFastBetterPRO+1,500
careerlm-deepSlowerBestPLUS+4,096

Score a CV

POST
/career/cv/score
FREE

Returns a structured ATS score, keyword gap analysis, section breakdown, and improvement suggestions.

Request body

FieldTypeRequiredDescription
cv_textstringrequiredFull CV text
job_descriptionstringoptionalTarget job description (improves keyword match)
target_countrystringoptional, default GBISO 3166-1 alpha-2 country code
target_rolestringoptionalExplicit target role (overrides JD inference)
options.include_suggestionsbooleanoptional, default trueInclude top_suggestions array
JavaScript
const score = await client.cv.score(cvText, jobDescription, { target_country: 'NG' })
// score.ats_score     → 87
// score.grade         → "B+"
// score.keyword_match → { matched: [...], missing: [...], coverage: 73 }
// score.section_scores → { summary: 85, experience: 90, ... }
// score.top_suggestions → ["Add Kubernetes", ...]
Response
{
  "ats_score": 87,
  "grade": "B+",
  "keyword_match": {
    "matched": ["Python", "AWS", "FastAPI"],
    "missing": ["Kubernetes", "Terraform"],
    "coverage": 73
  },
  "section_scores": { "summary": 85, "experience": 90, "skills": 75, "education": 80 },
  "top_suggestions": ["Add Kubernetes to skills section", ...],
  "model": "careerlm-flash",
  "request_id": "req_a1b2c3d4"
}

Benchmark salary

POST
/career/salary/benchmark
PRO

PPP-adjusted salary ranges for 196 countries. Returns skill premiums, negotiation target, and equity range.

Request body

FieldTypeRequiredDescription
rolestringrequiredJob title / career path
countrystringoptional, default GBISO 3166-1 alpha-2
citystringoptionalCity for local adjustment
years_experienceintegeroptionalYears of experience
skillsstring[]optionalSkills to compute premiums for
options.currencystringoptionalISO 4217 currency code (default: local)
Response
{
  "salary_range": { "low": 4200000, "median": 6800000, "high": 11000000 },
  "currency": "NGN",
  "usd_equivalent": { "median": 4500 },
  "skill_premiums": [{ "skill": "dbt", "premium_percent": 12 }],
  "negotiation_target": 7500000,
  "negotiation_script": "Based on market data...",
  "confidence": "high"
}

Generate cover letter

POST
/career/cover-letter/generate
PRO

15 professional writing modes. No banned filler phrases. Structured return includes letter, mode name, and word count.

Cover letter modes

ModeNameBest for
1Achievement-ledStrong career track records
2Insight-ledStrategy and leadership roles
3Problem-solutionPain-point-heavy job specs
4NarrativeStorytelling-friendly brands
5Company-specificDeep research hooks
6Question-ledProvocative openers
7Bold statementHigh-competition roles
8Data-drivenMetrics-heavy CVs
9Cultural fitValues-first organisations
10Career transitionChanging industries/roles
11PromotionInternal promotions
12ReferralWhen referred by someone
13RemoteRemote-first applications
14MultilingualMulti-market roles
15ExecutiveC-suite / Director gravitas

Match job

POST
/career/job/match
PRO

Multi-dimensional match score across skills, experience, salary, location, and culture signals. Returns apply recommendation.

Skills gap

POST
/career/skills/gap
PRO

Quantified gap analysis with L1-L4 skill levels, learning hours, free resources, and salary ROI per skill acquired.

Interview questions

POST
/career/interview/questions
PRO

Role and company-specific questions with STAR model answers, follow-up probes, and common mistakes to avoid.

Career chat (OpenAI-compatible)

POST
/career/chat/completions
FREE

Drop-in OpenAI replacement. Same request/response shape. Change the base URL and model name — nothing else.

Migration from OpenAI (1 change)
// Before:
const openai = new OpenAI({ apiKey: 'sk-...' })

// After:
const openai = new OpenAI({
  apiKey:  'csk_free_v1_...',
  baseURL: 'http://localhost:3005/v1/career',
  defaultHeaders: { 'X-Api-Key': 'csk_free_v1_...' }
})

Career context (persistent memory)

POST
/career/context
FREE
GET
/career/context/:id
FREE

World-first: persist the candidate's profile across API calls. Save once, pass context_id to every other endpoint for automatic personalisation.

💡 A context_id on /cv/score means the model knows the candidate's target role and country without you repeating them.

Register developer

POST
/developer/register

No auth required. Returns your API key — shown once, store immediately.

Response
{
  "developer_id": "dev_abc123",
  "api_key": "csk_free_v1_...",  // shown once
  "tier": "FREE",
  "daily_limit": 1000,
  "docs": "http://localhost:3006/docs"
}

Usage stats

GET
/developer/usage/:developerId

Returns today's request count, remaining daily quota, RPM limit, and recent 10 calls with masked model names.

CSTM-2 — a separate API, different base URL & auth

⚠️ Everything below is a genuinely different product from the CareerStudioMax Developer Cloud API documented above — different base URL, different authentication header, different key format and rate-limit tiers. It is not reachable via X-Api-Key or the api.careerstudiomax.com host. Treat it as a separate integration.

CSTM-2 is CareerStudioMax's own model API, served directly by the main platform. It's organised into per-capability key families (CareerLM, CareerEmbed, CareerScore, CareerAgent, CareerVoice, CareerVision, CareerWebAPI) — this page currently only documents CareerEmbed, the semantic-embedding family. For the live, authoritative list of every CSTM-2 family and endpoint, see GET /api/cstm2/docs/models or the self-documenting reference at careerstudiomax.com/developer.

Base URL: https://careerstudiomax.com/api/cstm2

Authentication

Pass a CareerEmbed key (cstm_em_*, generated via the key-management UI at careerstudiomax.com/developer) as a Bearer token.

All CSTM-2 requests
curl -H "Authorization: Bearer cstm_em_..." ...

Create embeddings

POST
/v1/careerembed/embed

384-dimensional text embeddings (Xenova/all-MiniLM-L6-v2, served by careercamp-ai).

JavaScript (careerlm/cstm2)
const { CSTM2Client } = require('careerlm/cstm2')
const client = new CSTM2Client('cstm_em_...')
const result = await client.embed('Senior Software Engineer, distributed systems')
// result.data[0].embedding → [0.0123, -0.045, ...]  (384 floats)

Semantic similarity

POST
/v1/careerembed/similarity

Cosine similarity (0–1) between two texts.

FieldTypeRequired
text_astringrequired
text_bstringrequired

Semantic job matching

POST
/v1/careerembed/match-jobs

Ranks real, current listings from CareerStudioMax's live-harvested job feed (Adzuna, Reed, USAJOBS, Greenhouse, Lever, RemoteOK, Remotive, ArbeitNow, TheMuse, WeWorkRemotely, Jooble — never scraped or purchased data) by embedding cosine similarity to a given CV.

FieldTypeRequiredDescription
cv_textstringrequiredFull CV text
country_codestringoptionalISO alpha-2 — falls back to a global pool if omitted or uncovered
limitintegeroptional, default 10Max 25
Response
{
  "matches": [
    { "title": "Senior Backend Engineer", "company": "Stripe", "matchScore": 50, "url": "...", "source": "greenhouse" }
  ],
  "total_candidates_considered": 65,
  "scoped_to_country": true,
  "data_freshness": "Oldest listing considered: 9 day(s) old",
  "model": "careerembed-v1"
}
Python (careerlm.cstm2)
from careerlm.cstm2 import CSTM2Client
client = CSTM2Client(api_key="cstm_em_...")
result = client.match_jobs(cv_text, country_code="US", limit=10)
On this page
Authentication Errors Rate limits Models CV score Salary benchmark Cover letter Job match Skills gap Interview Career chat Context Register Usage CSTM-2 (separate API)