Version: 1.0 · Base URL: https://api.jobin.ailaile.cn
All requests (except public endpoints) require an API Key via one of two headers:
Authorization: Bearer jl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-API-Key: jl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
API Key format: Starts with jl_live_ followed by 64 hex chars (72 chars total). Plaintext is shown only once at creation.
Public endpoints (no key required):
POST /auth/register · POST /auth/login · POST /billing/webhook · GET /health
| Plan | Monthly Requests | Per Minute | Data Sources | AI Features | Price |
|---|---|---|---|---|---|
| Free | 1,000 | 10 | 1 | — | $0 |
| Starter | 50,000 | 60 | 3 | — | $49/mo |
| Pro | 500,000 | 300 | 5 | ✓ lite + flagship | $149/mo |
| Scale | 3,000,000 | 1,000 | 6 | ✓ all | $299/mo |
Rate limit headers returned on every authenticated response:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-Plan: pro
Public endpoint protection: /auth/register is limited to 5 req/IP/min; /auth/login to 10 req/IP/min.
Use X-AI-Provider and X-AI-Model headers to select a model per request. Use GET /jobs/providers for live availability status.
Currently available: Qwen (Alibaba) · Coming Soon: Anthropic · OpenAI · Google · DeepSeek
| Provider | Alias | Model ID | Tier | Min Plan | Status |
|---|---|---|---|---|---|
anthropic | haiku | claude-haiku-4-5 | lite | Starter | 🔜 Coming Soon |
anthropic | sonnet | claude-sonnet-4-6 | flagship | Pro | 🔜 Coming Soon |
openai | gpt-4o-mini | gpt-4o-mini | lite | Starter | 🔜 Coming Soon |
openai | gpt-4o | gpt-4o | flagship | Pro | 🔜 Coming Soon |
google | flash | gemini-2.0-flash | lite | Free | 🔜 Coming Soon |
google | pro | gemini-1.5-pro | flagship | Pro | 🔜 Coming Soon |
qwen | turbo | qwen-turbo | lite | Free | ✅ Available |
qwen | plus | qwen-plus | flagship | Pro | ✅ Available |
deepseek | chat | deepseek-chat | lite | Starter | 🔜 Coming Soon |
deepseek | reasoner | deepseek-reasoner | flagship | Pro | 🔜 Coming Soon |
X-AI-Provider: qwen
X-AI-Model: turbo
| Source | Coverage | Specialty | Plan |
|---|---|---|---|
| Adzuna | Global | Widest coverage, strong salary data | Free+ |
| Remotive | Global | Remote-first jobs | Starter+ |
| Findwork | UK + US | Dev/tech roles, skills pre-tagged | Starter+ |
| Reed | UK | Best UK structured salary data | Pro+ |
| Arbeitnow | EU / Germany | Visa-sponsored tag | Pro+ |
| The Muse | US / Global | Company culture-focused roles | Scale |
Smart routing: country=gb → prioritizes Reed; country=us → prioritizes The Muse; EU countries (de at ch nl pl cz) → prioritizes Arbeitnow; remote=true → prioritizes Remotive and Findwork.
Results from multiple sources are deduplicated by fingerprint (title + company + city) and merged to fill missing fields.
REGISTRATION
─────────────────────────────────────────────────────────────
Client ──POST /auth/register──► API
├─ Create user account
└─ Generate API Key (hash stored)
◄── jl_live_... returned (plaintext shown once only)
KEY RECOVERY (if key is lost)
─────────────────────────────────────────────────────────────
Client ──POST /auth/login──► Returns session token
──POST /auth/keys/rotate──► Revoke all keys → new jl_live_...
KEY MANAGEMENT (ongoing)
─────────────────────────────────────────────────────────────
GET /auth/me Plan · usage · key list
POST /auth/keys Create additional key
POST /auth/keys/rotate Revoke all → one new key [distributed lock]
DEL /auth/keys/:prefix Revoke specific key
Every authenticated request to a /jobs/* endpoint passes through this pipeline:
Incoming request
│
▼
┌─────────────────────────────────────────────────┐
│ Auth Middleware │──── 401 (invalid key)
│ Validate API Key → inject user + plan context │
└─────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Quota Middleware │──── 403 (endpoint access)
│ Endpoint access · monthly quota · rate limit │──── 429 (quota / rate)
└─────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ KV Cache Check │
│ Key = query + plan (+ model for AI endpoints) │──── HIT → return immediately
└─────────────────────────────────────────────────┘
│ MISS
▼
┌─────────────────────────────────────────────────┐
│ Source Router │
│ Select sources by plan (1–6) · parallel fetch │
│ Context routing (country / remote flag) │
└─────────────────────────────────────────────────┘
│ concurrent fetch
├──► Adzuna
├──► Reed / Remotive / Findwork
└──► Arbeitnow / The Muse
│
▼
┌─────────────────────────────────────────────────┐
│ Dedup + Merge │
│ Fingerprint by title+company+city │
│ Complement missing fields across sources │
└─────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ AI Enhance (Pro+ with enhance=true) │
│ Skill extraction · seniority · remote detect │
│ 15s timeout → graceful degrade on failure │
└─────────────────────────────────────────────────┘
│
▼
Write KV cache + Log usage → Return response
NEW SUBSCRIPTION
─────────────────────────────────────────────────────────────
Client ──POST /billing/checkout──►
{ plan, success_url, cancel_url }
│
▼
Returns Stripe Checkout URL
│
User completes payment on Stripe
│
Redirect → success_url
│
(background) Stripe fires webhook ──►
WEBHOOK EVENTS (automatic, Stripe → /billing/webhook)
─────────────────────────────────────────────────────────────
checkout.session.completed → Activate plan (matched by userId)
subscription.updated → Apply change + notify user email
subscription.deleted → Revert to Free + notify user email
invoice.payment_failed → Mark past_due, retain plan (grace period)
Stripe retries; only downgrades on deletion
After plan update → client polls GET /auth/me until plan field changes
SELF-SERVICE
─────────────────────────────────────────────────────────────
POST /billing/portal ──► Stripe Customer Portal URL
User can: upgrade · downgrade · cancel · view invoices
Any change triggers webhook → automatic plan sync
| Code | Meaning |
|---|---|
400 | Bad Request — missing or invalid parameters |
401 | Unauthorized — API Key missing, invalid, or revoked |
403 | Forbidden — plan cannot access this endpoint or model tier. Response includes upgrade URL |
409 | Conflict — email already registered, or already on this plan |
429 | Too Many Requests — monthly quota or per-minute rate limit exceeded |
503 | Service Unavailable — AI provider timed out (15s limit), retry later |
500 | Internal Server Error |
429 response:
{
"error": "Monthly request limit exceeded",
"limit": 50000,
"used": 50001,
"resets": "2025-05-01T00:00:00.000Z",
"upgrade": "https://api.jobin.ailaile.cn/pricing"
}
Public · 5 req/IP/min
| Field | Type | Required | Description |
|---|---|---|---|
email | string | ✓ | Account email |
password | string | ✓ | Minimum 8 characters |
curl -X POST https://api.jobin.ailaile.cn/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"dev@example.com","password":"mypassword"}'
201 Response:
{
"message": "Registration successful",
"api_key": "jl_live_a1b2c3d4...",
"prefix": "jl_live_a1b2****",
"plan": "free",
"notice": "Save your API key now — it will not be shown again."
}
Public · 10 req/IP/min
Use if you've lost your API Key. Login → get session token → call POST /auth/keys/rotate.
| Field | Type | Required | Description |
|---|---|---|---|
email | string | ✓ | Account email |
password | string | ✓ | Account password |
200 Response:
{
"access_token": "eyJhbGci...",
"refresh_token": "abc123...",
"expires_in": 3600
}
Requires API Key · Free+
200 Response:
{
"plan": "pro",
"monthly_used": 12480,
"monthly_limit": 500000,
"endpoints": [
"/jobs/search",
"/jobs/salary",
"/jobs/trends",
"/jobs/insight"
],
"api_keys": [
{
"name": "Default Key",
"key_prefix": "jl_live_a1b2****",
"last_used_at": "2025-04-12T08:32:00Z"
}
]
}
Requires API Key · Free+
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | Key label, defaults to "Default Key" |
201 Response:
{
"key": "jl_live_...",
"prefix": "jl_live_ab12****",
"notice": "Save this key securely. It will not be shown again."
}
Requires API Key · Free+
Revoke all active keys and generate one new key. Irreversible. Protected by a distributed lock — concurrent rotation requests return 429.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | — | New key label, defaults to "Rotated Key" |
Requires API Key · Free+
Revoke a specific key by its prefix (e.g. jl_live_ab12****). Get the prefix from GET /auth/me.
200 Response: { "message": "Key revoked" }
Requires API Key · Free+
Multi-source job aggregation with optional AI skill extraction.
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | ✓ | Search keyword, e.g. python developer |
location | string | — | City or region |
country | string | — | Country code, default gb. Supports: gb us au ca de fr |
remote | boolean | — | Prioritize remote-friendly sources |
enhance | boolean | — | AI skill extraction — Pro+ only. Gracefully degrades to unenhanced on timeout |
AI Headers (when enhance=true):
| Header | Description |
|---|---|
X-AI-Provider | qwen (others coming soon) |
X-AI-Model | Model alias or full ID, e.g. turbo |
Results cached 15 min per query + plan. Cache hits return
X-Cache: HIT.
curl "https://api.jobin.ailaile.cn/jobs/search?q=python+developer&country=gb&enhance=true" \
-H "Authorization: Bearer jl_live_..." \
-H "X-AI-Provider: qwen" \
-H "X-AI-Model: turbo"
200 Response:
{
"meta": {
"total": 42,
"enhanced": true,
"aiProvider": "qwen",
"aiModel": "qwen-turbo",
"sources": [
{ "name": "adzuna", "count": 22 },
{ "name": "reed", "count": 12 }
]
},
"jobs": [
{
"id": "adzuna:12345678",
"source": "adzuna",
"title": "Senior Python Developer",
"company": "Tech Ltd",
"location": { "city": "London", "country": "GB", "region": "" },
"salary": {
"min": 80000,
"max": 100000,
"currency": "GBP",
"period": "year"
},
"skills": ["Python", "FastAPI", "Docker"],
"seniority": "senior",
"remote": false,
"url": "https://...",
"postedAt": "2025-04-10T09:00:00Z",
"fetchedAt": "2025-04-12T08:00:00Z"
}
]
}
Requires API Key · Starter+
Salary P25/P50/P75 percentiles with histogram.
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | ✓ | Job title keyword |
location | string | — | City or region |
country | string | — | Country code, default gb |
Cached 6 hours per query + plan.
200 Response:
{
"query": "data scientist",
"currency": "GBP",
"sampleSize": 87,
"p25": 55000,
"median": 72000,
"p75": 90000,
"min": 35000,
"max": 140000,
"histogram": { "40000": 8, "50000": 15, "60000": 22 }
}
Requires API Key · Pro+ ·
X-AI-Provider+X-AI-Modelrequired
AI-powered skill trend analysis.
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | ✓ | Role or industry keyword |
location | string | — | City or region |
country | string | — | Default gb |
Cached 6 hours per query + model.
200 Response:
{
"query": "machine learning",
"sampleSize": 63,
"aiProvider": "qwen",
"aiModel": "qwen-turbo",
"topSkills": [{ "skill": "Python", "count": 52, "ratio": 0.83 }],
"remoteRatio": 0.41,
"seniority": { "junior": 8, "mid": 22, "senior": 27, "lead": 6 }
}
Requires API Key · Pro+ ·
X-AI-Provider+X-AI-Modelrequired
AI-generated market intelligence report. Same query + same model = cached 6 hours at no extra AI cost.
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | ✓ | Role or industry keyword |
location | string | — | City or region |
country | string | — | Default gb |
200 Response:
{
"query": "frontend developer",
"location": "london",
"insight": {
"summary": "London's frontend market remains competitive...",
"topSkills": [{ "skill": "React", "trend": "rising" }],
"salaryRange": { "p25": 55000, "median": 72000, "p75": 88000 },
"remoteRatio": 0.38,
"keyFindings": ["Next.js up 34% YoY"],
"dataQuality": "high",
"sampleSize": 62,
"aiProvider": "qwen",
"aiModel": "qwen-turbo"
}
}
Requires API Key · Free+
Returns AI providers and models available for the current plan with live availability status.
200 Response:
{
"plan": "pro",
"defaultProvider": "qwen",
"available": [
{
"provider": "qwen",
"status": "available",
"models": [
{ "alias": "turbo", "tier": "lite" },
{ "alias": "plus", "tier": "flagship" }
]
},
{ "provider": "anthropic", "status": "coming_soon", "models": [] }
]
}
Requires API Key · Free+
Creates a Stripe Checkout URL. After payment, poll GET /auth/me until plan changes.
| Field | Type | Required | Description |
|---|---|---|---|
plan | string | ✓ | starter · pro · scale |
success_url | string | ✓ | Redirect after payment. Supports {CHECKOUT_SESSION_ID}. Must be https:// or http://localhost |
cancel_url | string | ✓ | Redirect if cancelled. Same URL requirements |
curl -X POST https://api.jobin.ailaile.cn/billing/checkout \
-H "Authorization: Bearer jl_live_..." \
-H "Content-Type: application/json" \
-d '{ "plan": "pro", "success_url": "https://yourapp.com/success?session_id={CHECKOUT_SESSION_ID}", "cancel_url": "https://yourapp.com/cancel" }'
200 Response: { "url": "https://checkout.stripe.com/c/pay/cs_live_..." }
409 Response: { "error": "Already on this plan or higher.", "portal": "https://api.jobin.ailaile.cn/billing/portal" }
Requires API Key · Starter+
Returns a Stripe Customer Portal URL for self-service subscription management.
200 Response: { "url": "https://billing.stripe.com/p/session/..." }
Stripe only — Do not call directly
| Event | Action |
|---|---|
checkout.session.completed | Activate paid plan |
customer.subscription.updated | Apply change + notify email |
customer.subscription.deleted | Revert to Free + notify email |
invoice.payment_failed | Mark past_due, retain plan (grace period) |
Public
{ "status": "ok", "ts": "2025-04-12T09:00:00.000Z" }
| Method | Path | Auth | Min Plan |
|---|---|---|---|
| POST | /auth/register | — | — |
| POST | /auth/login | — | — |
| GET | /auth/me | API Key | Free |
| POST | /auth/keys | API Key | Free |
| POST | /auth/keys/rotate | API Key | Free |
| DELETE | /auth/keys/:prefix | API Key | Free |
| GET | /jobs/search | API Key | Free |
| GET | /jobs/salary | API Key | Starter |
| GET | /jobs/trends | API Key | Pro |
| GET | /jobs/insight | API Key | Pro |
| GET | /jobs/providers | API Key | Free |
| POST | /billing/checkout | API Key | Free |
| POST | /billing/portal | API Key | Starter |
| POST | /billing/webhook | Stripe | — |
| GET | /health | — | — |