Mint a key in settings, then call our models from the OpenAI SDK or from Claude Code and other MCP clients. Usage is billed to your company's credits.
Company admins create keys under Profile → API Keys. The raw key is shown once — copy it into your environment, never into source control.
The endpoint is OpenAI-compatible: only the base URL and the key change.
https://api.aiqlick.com/llm/v1
Base URL: https://api.aiqlick.com/llm/v1
# pip install openai
from openai import OpenAI
client = OpenAI(api_key="sk-...", base_url="https://api.aiqlick.com/llm/v1")
response = client.chat.completions.create(
model="<model-alias>",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)Keep the key out of source control — read it from an environment variable in anything you deploy. Replace the model alias with one your key is scoped to.
Use model aliases (aiqlick/chat-default), never provider ids. A key scoped to a subset can only call that subset.
Point any Streamable-HTTP MCP client at the same origin plus /mcp. The key authenticates and bills exactly like the REST API.
https://api.aiqlick.com/llm/v1/mcp
Base URL: https://api.aiqlick.com/llm/v1/mcp
# The key stays in your shell env, never in the repo export AIQLICK_API_KEY="sk-..." claude mcp add --transport http aiqlick https://api.aiqlick.com/llm/v1/mcp \ --header "Authorization: Bearer $AIQLICK_API_KEY" # Verify inside Claude Code: /mcp should list aiqlick with chat + list_models. # Then ask it to call chat with model "<model-alias>".
Keep the key out of source control — read it from an environment variable in anything you deploy. Replace the model alias with one your key is scoped to.
Probe the handshake, list the tools, then make the first chat call — same key, three curl commands.
Every call lands in API consumption on the same settings page. Rotation mints a sibling and leaves the old key live — deploy the new one, watch the old key go quiet, then revoke it.
Endpoints across inference, parsing, recruitment data, and usage tracking on the same base URL. Bodies are forwarded as received, so provider-specific fields keep working without a client update.
| Method | Path | Notes |
|---|---|---|
| POST | /chat/completions | Chat and text, streaming and non-streaming |
| POST | /completions | Legacy completion shape |
| POST | /embeddings | Text to vectors |
| GET | /models | Only the aliases this key may call |
| GET | /usage | Real-time usage metrics and credit expenditure |
| GET | /jobs | Active company jobs with requirements and metadata |
| POST | /parse/cv | Parse resume/CV into structured candidate profile JSON |
| POST | /parse/jd | Parse job posting into structured job requirements JSON |
Granular permissions control what each key can access. Configure scopes when minting a key in company settings.
| Required scope | Description | Default |
|---|---|---|
| inference:chat | Chat completions, legacy completions, and vector embeddings | Enabled by default |
| inference:parse | Structured CV and job description extraction endpoints | Enabled by default |
| usage:read | Read-only access to key consumption metrics and token spend | Enabled by default |
| jobs:read | Read-only access to company active job postings and requirements | Opt-in only |
When connected via MCP streamable HTTP, the server registers the following tools according to your key's scopes:
| Tool | Required scope | Description |
|---|---|---|
| chat | inference:chat | Generate completions and answers using allowed model aliases |
| list_models | inference:chat | List model aliases authorized for the active key |
| get_usage | usage:read | Fetch real-time usage metrics and credit expenditure for this key |
| list_jobs | jobs:read | List company job openings with requirements and metadata |
| parse_cv | inference:parse | Parse resume or CV text into canonical structured candidate profile JSON |
| parse_jd | inference:parse | Parse job posting text into canonical structured job posting JSON |
Set "stream": true and the response arrives chunk by chunk. The server always merges stream_options.include_usage into streaming requests — without the usage block a call cannot be billed, so a stream that ends without one is recorded as a failure and not charged.
Every failure uses the OpenAI error envelope: {"error": {"message", "type", "code"}}. Match on code, not on words.
| Status | Type | Code | Meaning |
|---|---|---|---|
| 401 | authentication_error | — | Missing, unknown, revoked or expired key. All four look identical on purpose. |
| 402 | insufficient_quota | INSUFFICIENT_CREDITS | Company credit balance is at or below zero. Top up to resume. |
| 403 | permission_error | LLM_MODEL_NOT_ALLOWED | Model is outside this key's allowlist. Mint a key scoped to it, or pick another alias. |
| 403 | permission_error | LLM_SCOPE_DENIED | Key does not have the required scope for this endpoint or tool. |
| 403 | permission_error | PLAN_LIMIT_EXCEEDED | POSTPAID enterprise only: an overdue invoice blocks access. |
| 404 | not_found_error | — | Unknown route. Check the endpoint table above. |
| 429 | rate_limit_error | — | Too many requests. Back off and retry. |
| 503 | api_error | LLM_GATEWAY_UNAVAILABLE | Gateway unreachable. Retry with backoff. |
600 requests per minute per client IP, plus per-key RPM and TPM limits enforced at the gateway. The IP bucket is shared by customers behind the same egress address, which is why the IP limit sits far above any single-tenant rate.
Thin wrappers over the official OpenAI SDK — same calls, with the base URL and model aliases built in. You never need them; the official SDK works directly.
# pip install aiqlick
from aiqlick import AIQLick, Models
client = AIQLick(api_key="sk-...") # or set AIQLICK_API_KEY
reply = client.chat.completions.create(
model=Models.CHAT_DEFAULT,
messages=[{"role": "user", "content": "hello"}],
)
print(reply.choices[0].message.content)# npm install @aiqlick/inference openai
import { AIQLick, Models } from "@aiqlick/inference";
const client = new AIQLick({ apiKey: process.env.AIQLICK_API_KEY });
const reply = await client.chat.completions.create({
model: Models.CHAT_DEFAULT,
messages: [{ role: "user", content: "hello" }],
});
console.log(reply.choices[0]?.message?.content);Call aliases, never provider ids — the mapping can change without you changing code. A key scoped to a subset can only call that subset; list_models (REST: GET /models) shows exactly what your key may use.
| Symptom | Fix |
|---|---|
| Everything returns 401 | The key is missing, wrong, revoked or expired — the server answers all four identically. Re-copy the key from settings; a key that was already shown once is gone, so mint a new one. |
| "Not permitted" for a model | The key is not scoped to that alias. Call list_models to see the allowlist. |
| Calls suddenly stop with 402 | Credits ran out. Usage and top-up live on the same settings page as the keys. |
| A stream carries no usage | The client disconnected early or the usage block went missing. It is recorded as a failed, unbilled call — retry non-streaming to compare. |
Create your free profile, let AI match you to the best jobs, and start applying today — with 9 free AI credits.
No credit card required • Always free • 9 AI credits included
AiQlick helps job seekers find the right opportunities through AI-powered matching, smart CV management, and real-time application tracking.
© 2026 AiQlick. All rights reserved.