Upload a document, give a target role, or both. The API works out where the person falls short of the role, then returns ranked courses for each missing skill — each with its source, level and relevance score. The catalogue knows the skill. It does not know who is missing it.
score from 0 to 1 and an isPremium flag, so you can rank on relevance and filter on what your licences already cover.
One multipart request, two fields that matter. At least one of file or role is required — sending neither returns 400 invalid_input. You do not need to run a gap analysis first; this endpoint does that part itself and returns it alongside the courses.
The full path. The API extracts what the person demonstrates, compares it against the role, and returns the gap skills and the courses that close each one.
learningscurl -X POST "$BASE/v1/learning-content/suggest" \ -H "Authorization: Bearer $APIKEY" \ -F "file=@resume.pdf" \ -F "role=Software Engineer" \ -F "language=English"
No document to hand? Send just the role. Every competency that role expects is treated as a gap, and courses come back for all of them — a ready-made curriculum for the role itself.
curl -X POST "$BASE/v1/learning-content/suggest" \ -H "Authorization: Bearer $APIKEY" \ -F "role=Software Engineer" \ -F "language=French"
language to get them in French, Spanish, German, Italian, Portuguese, Hindi or Arabic — the course metadata is translated, not just the skill names.This is the documented response for a resume assessed against Software Engineer. Each row is a key in the learnings object — the hatched band is the level the role expects for that skill. Select any row to see the courses returned for it, with source, level, relevance score and whether it is behind a paywall.
Search a skill name and you get beginner content for an expert and expert content for a beginner. Four fields on every course are what make the difference between a search result and a plan.
How well this course closes that specific gap, not how popular it is. Sort on it and the top item is the one to assign.
The difficulty of the course itself: Beginner, Intermediate, Advanced or Expert. Match it against the level the role expects.
true if paid, false if free. Filter before you assign and no one hits a paywall you have not licensed.
The provider, for example Udemy, Coursera or YouTube. Drop the sources your organisation does not use before the plan reaches anyone.
learnings is an object keyed by gap skill, each key mapping to an array of ranked courses. The same five skill arrays as Skill Gap Identification come back alongside it, so one call covers the diagnosis and the plan.
https://platform.openknowra.ai/api/bffmultipart/form-dataAuthorization: Bearer ok_<your-api-key>ok_ and expire after 90 days. A request without a valid one returns 401 unauthorized.
| Field | Type | Required | Description |
|---|---|---|---|
file | file | conditional | A single resume or document. .pdf, .doc, .docx. Up to 10 MB. |
role | string | conditional | Target role to identify gaps against, e.g. Software Engineer. Sent alone, the role’s expected skills are all treated as gaps and courses are recommended for them. |
language | string | optional | Output language for the results. Defaults to English. Also French, Spanish, German, Italian, Portuguese, Hindi, Arabic. |
file or role is required. Sending neither returns 400 invalid_input.{
"success": true,
"role": "Software Engineer",
"matchedSkills": [ { "skill":"java", "level":4 }, ... ],
"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=...",
"courseSource": "YouTube",
"level": "Beginner",
"score": 0.55,
"isPremium": false },
{ "courseTitle": "Docker Deep Dive",
"courseSource": "Udemy",
"level": "Intermediate",
"score": 0.48,
"isPremium": true }
],
"Kubernetes": [ /* ... */ ]
},
"creditsUsed": 45, "newBalance": 955
}learnings is keyed by gap skill, so the key always matches an entry in gapSkills — nothing to re-join. Course titles, sources and URLs resolve against the live catalogue. There is no duration field; rank on score and filter on isPremium.Each entry inside a learnings key is a course object. There is no duration and no content-type taxonomy — what you get instead is a relevance score you can sort on and a paywall flag you can filter on.
| Field | Type | Description |
|---|---|---|
courseTitle | string | Title of the recommended course. |
courseUrl | string | Link to the course. |
courseSource | string | Provider, e.g. Udemy, Coursera, YouTube. |
level | string | Course difficulty: Beginner, Intermediate, Advanced or Expert. |
score | number | Relevance score, 0 to 1, for closing that specific gap skill. Sort descending to get the course to assign first. |
isPremium | boolean | true if paid, false if free. |
courseUrl — do not infer it from level.Skill Gap Identification and this endpoint take the identical multipart body. This one returns everything that one does, and adds learnings on top. Run the cheaper endpoint when you only need the diagnosis; run this one when you need the plan. Nothing to transform between them, because nothing changes but the path.
-F "file=@resume.pdf" -F "role=Software Engineer" // diagnosis only "gapSkills": [ { "skill":"Docker", "level":3 } ]
-F "file=@resume.pdf" -F "role=Software Engineer" // same body in, diagnosis plus "gapSkills": [ /* identical */ ], "learnings": { "Docker": [ { "score":0.55 } ] }
Once content is tied to a measured distance, four decisions change first.
Point budget at measured gaps instead of catalogue-wide coverage, and report against levels closed.
Give a person the specific sequence that closes the distance to the role they want, not a reading list.
Skip what the person already demonstrates and target only the band they have yet to cover.
Sequence development for each successor against the requirement of the role ahead of them.
One rate per API call, covering the first 1 MB of input. Bigger documents step up a tier per whole MB. A call that returns thirty courses across eight gap skills costs the same as one that returns three — the document is what you pay for.
role and no document is charged at the base 1 MB tier — $4.50 / 45 credits.413 file_too_large..pdf .doc .docx| Payload size | Cost (USD) | Cost (credits) |
|---|---|---|
| Up to 1 MB | $4.50 | 45 |
| 1 – 2 MB | $9.00 | 90 |
| 2 – 3 MB | $13.50 | 135 |
| 3 – 4 MB | $18.00 | 180 |
| 4 – 5 MB | $22.50 | 225 |
| 5 – 6 MB | $27.00 | 270 |
| 6 – 7 MB | $31.50 | 315 |
| 7 – 8 MB | $36.00 | 360 |
| 8 – 9 MB | $40.50 | 405 |
| 9 – 10 MB (max) | $45.00 | 450 |
role=Software EngineerlearningscreditsUsed: 45Generate a key, spend the 1000 credits on real learning plans, and decide after that. At the base rate that is 22 single-resume plans before you pay anything. For enterprise volumes, reach us at ok@spire.ai
| What you need | Endpoint | Cost per call |
|---|---|---|
| Just the named gaps, for a hiring or mobility decision | /v1/skill-gap/analyze | 35 cr · $3.50 |
| The gaps and the courses that close them | /v1/learning-content/suggest | 45 cr · $4.50 |
| Both, by calling the two endpoints separately | both | 80 cr · $8.00 |
Rates are configured per deployment and can change. creditsUsed in every response reflects what that specific call was actually billed, so don’t hardcode the numbers above.
Failed calls are not charged. A 402 tells you exactly how short you are, so a client can top up and retry without re-uploading the document.
| Status | Code | Meaning |
|---|---|---|
400 | invalid_input | Neither a document nor a target role was provided. |
401 | unauthorized | Missing, invalid, expired or revoked API key. Keys expire after 90 days. |
402 | insufficient_credits | Account balance too low. The body carries required and balance. |
413 | file_too_large | The file exceeds the 10 MB per-file size limit. |
502 | upstream_error | The analysis engine returned an error. Safe to retry after a short delay. |
503 | service_unavailable | The analysis service is briefly unavailable or not configured. Safe to retry. |
{ "error": { "code": "insufficient_credits", "required": 25, "balance": 10 } }Return the content that closes a measured gap, aimed at the level the person actually has to reach, in one call.