curl --request POST \
--url https://prod.skillsdbnext.com/api/v1/learning-suggestions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Advanced Rigging",
"description": "Annual refresher for licensed operators.",
"url": "https://learn.example.com/forklift",
"durationHours": 2.5,
"cost": 120,
"costDescription": "Per seat",
"providerId": "3",
"formatId": "2",
"audienceId": "1",
"courseLevelId": "4",
"referenceId": "LMS-4471",
"typeId": "1",
"note": "Needed for the crane team.",
"skillIds": [
"<string>"
],
"careerIds": [
"<string>"
]
}
'import requests
url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions"
payload = {
"title": "Advanced Rigging",
"description": "Annual refresher for licensed operators.",
"url": "https://learn.example.com/forklift",
"durationHours": 2.5,
"cost": 120,
"costDescription": "Per seat",
"providerId": "3",
"formatId": "2",
"audienceId": "1",
"courseLevelId": "4",
"referenceId": "LMS-4471",
"typeId": "1",
"note": "Needed for the crane team.",
"skillIds": ["<string>"],
"careerIds": ["<string>"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: 'Advanced Rigging',
description: 'Annual refresher for licensed operators.',
url: 'https://learn.example.com/forklift',
durationHours: 2.5,
cost: 120,
costDescription: 'Per seat',
providerId: '3',
formatId: '2',
audienceId: '1',
courseLevelId: '4',
referenceId: 'LMS-4471',
typeId: '1',
note: 'Needed for the crane team.',
skillIds: ['<string>'],
careerIds: ['<string>']
})
};
fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://prod.skillsdbnext.com/api/v1/learning-suggestions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Advanced Rigging',
'description' => 'Annual refresher for licensed operators.',
'url' => 'https://learn.example.com/forklift',
'durationHours' => 2.5,
'cost' => 120,
'costDescription' => 'Per seat',
'providerId' => '3',
'formatId' => '2',
'audienceId' => '1',
'courseLevelId' => '4',
'referenceId' => 'LMS-4471',
'typeId' => '1',
'note' => 'Needed for the crane team.',
'skillIds' => [
'<string>'
],
'careerIds' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions"
payload := strings.NewReader("{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"<string>\"\n ],\n \"careerIds\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-suggestions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"<string>\"\n ],\n \"careerIds\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"<string>\"\n ],\n \"careerIds\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "530",
"title": "Advanced Rigging",
"description": null,
"url": "https://learn.example.com/rigging",
"durationHours": 8,
"cost": 450,
"type": {
"id": "3",
"name": "Online course"
},
"provider": {
"id": "3",
"name": "Online course"
},
"format": {
"id": "3",
"name": "Online course"
},
"audience": {
"id": "3",
"name": "Online course"
},
"courseLevel": {
"id": "3",
"name": "Online course"
},
"referenceId": null,
"note": "Needed for the crane team.",
"suggestedSkillIds": [
"77"
],
"suggestedCareerIds": [
"31"
],
"status": "pending",
"submittedById": "1042",
"submittedAt": "2026-03-01T09:00:00.000Z",
"approvedById": null,
"approvedAt": null,
"rejectedById": null,
"rejectedAt": null,
"rejectionReason": null,
"modifiedOnApproval": false
}
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}Submit a learning suggestion
Proposes a catalogue item. The submission is pending until a global administrator approves or rejects it.
Requires scope: learning:write.
curl --request POST \
--url https://prod.skillsdbnext.com/api/v1/learning-suggestions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"title": "Advanced Rigging",
"description": "Annual refresher for licensed operators.",
"url": "https://learn.example.com/forklift",
"durationHours": 2.5,
"cost": 120,
"costDescription": "Per seat",
"providerId": "3",
"formatId": "2",
"audienceId": "1",
"courseLevelId": "4",
"referenceId": "LMS-4471",
"typeId": "1",
"note": "Needed for the crane team.",
"skillIds": [
"<string>"
],
"careerIds": [
"<string>"
]
}
'import requests
url = "https://prod.skillsdbnext.com/api/v1/learning-suggestions"
payload = {
"title": "Advanced Rigging",
"description": "Annual refresher for licensed operators.",
"url": "https://learn.example.com/forklift",
"durationHours": 2.5,
"cost": 120,
"costDescription": "Per seat",
"providerId": "3",
"formatId": "2",
"audienceId": "1",
"courseLevelId": "4",
"referenceId": "LMS-4471",
"typeId": "1",
"note": "Needed for the crane team.",
"skillIds": ["<string>"],
"careerIds": ["<string>"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
title: 'Advanced Rigging',
description: 'Annual refresher for licensed operators.',
url: 'https://learn.example.com/forklift',
durationHours: 2.5,
cost: 120,
costDescription: 'Per seat',
providerId: '3',
formatId: '2',
audienceId: '1',
courseLevelId: '4',
referenceId: 'LMS-4471',
typeId: '1',
note: 'Needed for the crane team.',
skillIds: ['<string>'],
careerIds: ['<string>']
})
};
fetch('https://prod.skillsdbnext.com/api/v1/learning-suggestions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://prod.skillsdbnext.com/api/v1/learning-suggestions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Advanced Rigging',
'description' => 'Annual refresher for licensed operators.',
'url' => 'https://learn.example.com/forklift',
'durationHours' => 2.5,
'cost' => 120,
'costDescription' => 'Per seat',
'providerId' => '3',
'formatId' => '2',
'audienceId' => '1',
'courseLevelId' => '4',
'referenceId' => 'LMS-4471',
'typeId' => '1',
'note' => 'Needed for the crane team.',
'skillIds' => [
'<string>'
],
'careerIds' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://prod.skillsdbnext.com/api/v1/learning-suggestions"
payload := strings.NewReader("{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"<string>\"\n ],\n \"careerIds\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://prod.skillsdbnext.com/api/v1/learning-suggestions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"<string>\"\n ],\n \"careerIds\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://prod.skillsdbnext.com/api/v1/learning-suggestions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Advanced Rigging\",\n \"description\": \"Annual refresher for licensed operators.\",\n \"url\": \"https://learn.example.com/forklift\",\n \"durationHours\": 2.5,\n \"cost\": 120,\n \"costDescription\": \"Per seat\",\n \"providerId\": \"3\",\n \"formatId\": \"2\",\n \"audienceId\": \"1\",\n \"courseLevelId\": \"4\",\n \"referenceId\": \"LMS-4471\",\n \"typeId\": \"1\",\n \"note\": \"Needed for the crane team.\",\n \"skillIds\": [\n \"<string>\"\n ],\n \"careerIds\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "530",
"title": "Advanced Rigging",
"description": null,
"url": "https://learn.example.com/rigging",
"durationHours": 8,
"cost": 450,
"type": {
"id": "3",
"name": "Online course"
},
"provider": {
"id": "3",
"name": "Online course"
},
"format": {
"id": "3",
"name": "Online course"
},
"audience": {
"id": "3",
"name": "Online course"
},
"courseLevel": {
"id": "3",
"name": "Online course"
},
"referenceId": null,
"note": "Needed for the crane team.",
"suggestedSkillIds": [
"77"
],
"suggestedCareerIds": [
"31"
],
"status": "pending",
"submittedById": "1042",
"submittedAt": "2026-03-01T09:00:00.000Z",
"approvedById": null,
"approvedAt": null,
"rejectedById": null,
"rejectedAt": null,
"rejectionReason": null,
"modifiedOnApproval": false
}
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}{
"type": "https://help.skillsdb.com/api-docs/errors/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "limit must be between 1 and 200",
"instance": "/api/v1/people",
"requestId": "0192c2f1-6f4e-7ab3-b1c4-5f6a7b8c9d0e",
"errors": [
{
"field": "email",
"code": "max_length",
"message": "email must be shorter than or equal to 75 characters"
}
],
"error": "trial_expired",
"upgrade_url": "https://app.skillsdb.com/settings/billing"
}Authorizations
An API key issued by a company administrator — an environment prefix (production: sdb_live_) followed by 32 characters. The prefix identifies the environment and MUST NOT be hard-coded or validated by clients; treat the whole key as opaque. Shown exactly once at creation; only a one-way hash is stored.
Scopes (granted per key on the create screen; :write never implies :read):
skills:readskills:writepeople:readpeople:writecareers:readcareers:writetraining:readtraining:writeflags:readflags:writeorg:readorg:writeassessments:readlearning:readlearning:writecertifications:readcertifications:writeassessments:writeproficiency:readproficiency:writesurveys:readsurveys:writelabels:readlabels:write
Headers
Any unique string (at most 200 characters). Retrying with the same key and identical content replays the stored response for 24h instead of executing twice.
200Body
500"Advanced Rigging"
4000"Annual refresher for licensed operators."
500"https://learn.example.com/forklift"
2.5
120
500"Per seat"
Training provider id (reference list).
"3"
Training format id (reference list).
"2"
Training audience id (reference list).
"1"
Training course level id (reference list).
"4"
100"LMS-4471"
Learning type id.
"1"
1000"Needed for the crane team."
Skill ids the item is proposed for.
Career ids the item is proposed for.
Response
The created resource, enveloped.
Show child attributes
Show child attributes