Work & Workforce Engineering · API

Learning Content Suggestions API

Upload a professional document, give a target role, or both. The API works out where the person falls short of the role, then recommends targeted courses - each with its source, level, and relevance score - to close every gap. Results come back in the language you choose.

Documentation Pricing
POST /v1/learning-content/suggest
Auth Bearer token Content-Type multipart/form-data Status Stable · v1 Max file size 10 MB

When to use this API

Use this API to turn a skill gap into an actionable learning plan - a ranked set of courses for each skill the person is missing.

Send a document, a target role, or both. The API identifies the gap skills against the role, then returns learnings - an object keyed by gap skill, each mapping to recommended courses. It also returns the matched skills, additional skills, and soft skills for the full picture. With just a role (no document), the role's expected skills are treated as gaps and courses are recommended for them.

Results are returned in English by default. Pass an optional language field (e.g. French, Spanish, German, Hindi) to receive them in that language.

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 header
Authorization: Bearer ok_xxxxxxxxxxxxxxxxxxxxxxxx
Heads-up. API keys are tied to the user account that generated them. Credit deductions are applied to that user's balance. A key that is revoked or expired returns 401 unauthorized.

Parameters

Form fields

NameTypeRequiredDescription
file file conditional A single resume or document. Accepted formats: .pdf, .doc, .docx. Up to 10 MB. Either file or role (or both) must be provided.
role string conditional Target role to identify gaps against, e.g. Software Engineer. Sent with just a role (no file), the role's expected skills are treated as gaps. Either file or role (or both) must be provided.
language string optional Output language for the results. Defaults to English. Examples: French, Spanish, German, Italian, Portuguese, Hindi, Arabic.
At least one of file or role is required. Sending neither returns 400.

Request

# Document + role
curl -X POST https://platform.openknowra.ai/api/bff/v1/learning-content/suggest \
  -H "Authorization: Bearer $OPENKNOWRA_API_KEY" \
  -F "file=@/path/to/resume.pdf" \
  -F "role=Software Engineer" \
  -F "language=English"

# Role only (no document)
curl -X POST https://platform.openknowra.ai/api/bff/v1/learning-content/suggest \
  -H "Authorization: Bearer $OPENKNOWRA_API_KEY" \
  -F "role=Software Engineer" \
  -F "language=English"
import os
import requests

API_KEY = os.environ["OPENKNOWRA_API_KEY"]
API_URL = "https://platform.openknowra.ai/api/bff/v1/learning-content/suggest"

with open("./resume.pdf", "rb") as f:
    res = requests.post(
        API_URL,
        headers={"Authorization": f"Bearer {API_KEY}"},
        files={"file": f},
        data={"role": "Software Engineer", "language": "English"},
    )
res.raise_for_status()
data = res.json()
for skill, courses in data["learnings"].items():
    print(skill, "->", [c["courseTitle"] for c in courses])
import fs from "fs";

const API_KEY = process.env.OPENKNOWRA_API_KEY!;
const API_URL = "https://platform.openknowra.ai/api/bff/v1/learning-content/suggest";

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("./resume.pdf")]), "resume.pdf");
form.append("role", "Software Engineer");
form.append("language", "English");

const res = await fetch(API_URL, { method: "POST", headers: { Authorization: `Bearer ${API_KEY}` }, body: form });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
console.log((await res.json()).learnings);

Response

200 OK - learnings is an object keyed by gap skill, each mapping to an array of recommended courses. The skill lists (matchedSkills, additionalSkills, gapSkills, softSkills, gappedSoftSkills) are arrays of { skill, level } (level 1-4). role is echoed only when one was provided.

application/json
{
  "success": true,
  "role": "Software Engineer",
  "matchedSkills": [
    { "skill": "java", "level": 4 },
    { "skill": "sql", "level": 2 }
  ],
  "additionalSkills": [
    { "skill": "redis", "level": 3 }
  ],
  "gapSkills": [
    { "skill": "Docker", "level": 3 },
    { "skill": "Kubernetes", "level": 3 }
  ],
  "softSkills": [
    { "skill": "communication", "level": 4 }
  ],
  "gappedSoftSkills": [
    { "skill": "leadership", "level": 4 }
  ],
  "learnings": {
    "Docker": [
      {
        "courseTitle": "Docker Fundamentals",
        "courseUrl": "https://youtube.com/watch?v=docker-fundamentals",
        "courseSource": "YouTube",
        "level": "Beginner",
        "score": 0.55,
        "isPremium": false
      },
      {
        "courseTitle": "Docker Deep Dive",
        "courseUrl": "https://udemy.com/course/docker-deep-dive",
        "courseSource": "Udemy",
        "level": "Intermediate",
        "score": 0.48,
        "isPremium": true
      }
    ],
    "Kubernetes": [
      {
        "courseTitle": "Kubernetes for Developers",
        "courseUrl": "https://coursera.org/learn/kubernetes-for-developers",
        "courseSource": "Coursera",
        "level": "Intermediate",
        "score": 0.51,
        "isPremium": true
      }
    ]
  },
  "creditsUsed": 45,
  "newBalance": 955
}

Course object fields

FieldTypeDescription
courseTitlestringTitle of the recommended course.
courseUrlstringLink to the course.
courseSourcestringProvider, e.g. Udemy, Coursera, YouTube.
levelstringCourse difficulty: Beginner, Intermediate, Advanced, or Expert.
scorenumberRelevance score (0-1) for closing the gap skill.
isPremiumbooleantrue if paid, false if free.

Errors

StatusCodeMeaning
400invalid_inputNeither a document nor a target role was provided.
401unauthorizedMissing, invalid, expired, or revoked API key.
402insufficient_creditsAccount balance too low. Response includes required and balance.
413file_too_largeThe file exceeds the 10 MB per-file size limit.
502upstream_errorThe analysis engine returned an error. Safe to retry after a short delay.
503service_unavailableThe analysis service is briefly unavailable or not configured. Safe to retry.
402 - insufficient_credits
{
  "error": {
    "code":     "insufficient_credits",
    "required": 25,
    "balance":  10
  }
}