Skill Proficiency Analysis API
Upload resume or documents to extract, score, and band skills into Expert, Advanced, Proficient, and Beginner proficiency levels - assembled on demand from your uploaded documents.
When to use this API
Use this API when you need to assess the skill depth of a candidate from their resume - without writing your own extraction or scoring pipeline.
The API accepts PDF, Word, and ZIP files, extracts every skill signal it finds, and returns a structured four-band breakdown (L1-L4) ranked by proficiency score. When multiple documents are submitted, skills are automatically aggregated and the highest score per skill is kept.
Authentication
All requests require a user-scoped API key passed as a bearer token.
Generate one in the platform under Settings → API Keys.
Keys are prefixed ok_ and expire after 90 days.
Authorization: Bearer ok_xxxxxxxxxxxxxxxxxxxxxxxx
401 unauthorized.
Parameters
Form fields
| Name | Type | Required | Description |
|---|---|---|---|
| files | file (one or more) | required |
One or more resume or document files. Accepted formats:
.pdf, .doc, .docx, .zip.
ZIP archives are extracted server-side - every supported document inside
is processed individually and results are merged. macOS metadata files
(__MACOSX/, ._*, .DS_Store) are
ignored automatically.
|
File constraints
| Constraint | Limit |
|---|---|
| Max file size | 10 MB per file |
| Max files per request | 20 files |
| Accepted formats | .pdf · .doc · .docx · .zip |
Request
# Single resume
curl -X POST https://platform.openknowra.ai/api/bff/v1/skill-proficiency/assess \
-H "Authorization: Bearer $OPENKNOWRA_API_KEY" \
-F "files=@/path/to/resume.pdf"
# ZIP archive (batch)
curl -X POST https://platform.openknowra.ai/api/bff/v1/skill-proficiency/assess \
-H "Authorization: Bearer $OPENKNOWRA_API_KEY" \
-F "files=@candidates_batch.zip"import os
import requests
API_KEY = os.environ["OPENKNOWRA_API_KEY"]
API_URL = "https://platform.openknowra.ai/api/bff/v1/skill-proficiency/assess"
def analyse_resume(file_path: str) -> dict:
with open(file_path, "rb") as f:
res = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
files={"files": f},
)
if res.status_code == 402:
err = res.json()["error"]
raise ValueError(
f"Insufficient credits: need {err['required']}, have {err['balance']}"
)
res.raise_for_status()
return res.json()
result = analyse_resume("./candidate.pdf")
for band in result["bands"]:
if band["skills"]:
print(f"{band['level']} {band['label']}: {', '.join(band['skills'])}")import fs from "fs";
const API_KEY = process.env.OPENKNOWRA_API_KEY!;
const API_URL = "https://platform.openknowra.ai/api/bff/v1/skill-proficiency/assess";
async function analyseResume(filePath: string) {
const form = new FormData();
const buffer = fs.readFileSync(filePath);
form.append("files", new Blob([buffer]), "resume.pdf");
const res = await fetch(API_URL, {
method: "POST",
headers: { Authorization: `Bearer ${API_KEY}` },
body: form,
});
if (res.status === 402) {
const err = await res.json() as { error: { required: number; balance: number } };
throw new Error(
`Insufficient credits: need ${err.error.required}, have ${err.error.balance}`
);
}
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
const result = await analyseResume("./candidate.pdf");
console.log(JSON.stringify(result.bands, null, 2));Response
200 OK - Returns a structured proficiency breakdown across all skills found in the uploaded documents. All four bands are always present even when empty, so it is safe to iterate without checking for missing keys.
{
"success": true,
"bands": [
{
"level": "L4",
"label": "Expert",
"skills": ["Python", "Machine Learning", "TensorFlow", "Data Modelling"]
},
{
"level": "L3",
"label": "Advanced",
"skills": ["React", "Node.js", "PostgreSQL", "REST API Design"]
},
{
"level": "L2",
"label": "Proficient",
"skills": ["Docker", "Kubernetes", "Redis"]
},
{
"level": "L1",
"label": "Beginner",
"skills": ["Rust", "GraphQL"]
}
],
"creditsUsed": 2.5,
"fileCount": 1,
"lambdaResponse": {}
}
Proficiency bands
| Level | Label | Meaning |
|---|---|---|
| L4 | Expert | Deep mastery. Extensive hands-on evidence, leadership or specialisation across multiple roles or projects. |
| L3 | Advanced | Strong, practised competency. Consistent use across multiple contexts with clear ownership and outcomes. |
| L2 | Proficient | Working knowledge. Skill is applied with clear practical examples but lacks the breadth or depth of higher bands. |
| L1 | Beginner | Foundational exposure. Skill is mentioned but with limited supporting evidence of hands-on application. |
| - | Not returned | Insufficient evidence. Skills scoring below 50 are excluded from the response entirely. |
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | - | No files provided, or no supported files found after ZIP extraction. |
| 401 | unauthorized | Missing, invalid, expired, or revoked API key. |
| 402 | insufficient_credits | Account balance too low. Response includes required (credits needed) and balance (current balance). |
| 413 | - | A file exceeds the 10 MB per-file size limit. |
| 500 | - | Extraction engine error. Safe to retry after a short delay. |
| 503 | skill_proficiency_not_configured | The extraction service is not enabled in this environment. |
{
"error": {
"code": "insufficient_credits",
"required": 25,
"balance": 10
}
}