curl --request POST \
--url https://api.dock.us/{version}/learning-assignments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"materials": [
{
"id": "RiHO4e0Ju3DS"
}
],
"learners": [
{
"id": "vKLoKUiy3Rbp"
}
],
"reviewers": [
{
"type": "manager"
},
{
"type": "user",
"email": "lead@acme.com"
}
],
"approvalPolicy": "all",
"dueDate": "2026-11-30",
"dueInDays": 30,
"reminders": {
"weekly": false,
"onDueDate": false
},
"allowDuplicates": false
}
'import requests
url = "https://api.dock.us/{version}/learning-assignments"
payload = {
"materials": [{ "id": "RiHO4e0Ju3DS" }],
"learners": [{ "id": "vKLoKUiy3Rbp" }],
"reviewers": [
{ "type": "manager" },
{
"type": "user",
"email": "lead@acme.com"
}
],
"approvalPolicy": "all",
"dueDate": "2026-11-30",
"dueInDays": 30,
"reminders": {
"weekly": False,
"onDueDate": False
},
"allowDuplicates": False
}
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({
materials: [{id: 'RiHO4e0Ju3DS'}],
learners: [{id: 'vKLoKUiy3Rbp'}],
reviewers: [{type: 'manager'}, {type: 'user', email: 'lead@acme.com'}],
approvalPolicy: 'all',
dueDate: '2026-11-30',
dueInDays: 30,
reminders: {weekly: false, onDueDate: false},
allowDuplicates: false
})
};
fetch('https://api.dock.us/{version}/learning-assignments', 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://api.dock.us/{version}/learning-assignments",
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([
'materials' => [
[
'id' => 'RiHO4e0Ju3DS'
]
],
'learners' => [
[
'id' => 'vKLoKUiy3Rbp'
]
],
'reviewers' => [
[
'type' => 'manager'
],
[
'type' => 'user',
'email' => 'lead@acme.com'
]
],
'approvalPolicy' => 'all',
'dueDate' => '2026-11-30',
'dueInDays' => 30,
'reminders' => [
'weekly' => false,
'onDueDate' => false
],
'allowDuplicates' => false
]),
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://api.dock.us/{version}/learning-assignments"
payload := strings.NewReader("{\n \"materials\": [\n {\n \"id\": \"RiHO4e0Ju3DS\"\n }\n ],\n \"learners\": [\n {\n \"id\": \"vKLoKUiy3Rbp\"\n }\n ],\n \"reviewers\": [\n {\n \"type\": \"manager\"\n },\n {\n \"type\": \"user\",\n \"email\": \"lead@acme.com\"\n }\n ],\n \"approvalPolicy\": \"all\",\n \"dueDate\": \"2026-11-30\",\n \"dueInDays\": 30,\n \"reminders\": {\n \"weekly\": false,\n \"onDueDate\": false\n },\n \"allowDuplicates\": false\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://api.dock.us/{version}/learning-assignments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"materials\": [\n {\n \"id\": \"RiHO4e0Ju3DS\"\n }\n ],\n \"learners\": [\n {\n \"id\": \"vKLoKUiy3Rbp\"\n }\n ],\n \"reviewers\": [\n {\n \"type\": \"manager\"\n },\n {\n \"type\": \"user\",\n \"email\": \"lead@acme.com\"\n }\n ],\n \"approvalPolicy\": \"all\",\n \"dueDate\": \"2026-11-30\",\n \"dueInDays\": 30,\n \"reminders\": {\n \"weekly\": false,\n \"onDueDate\": false\n },\n \"allowDuplicates\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dock.us/{version}/learning-assignments")
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 \"materials\": [\n {\n \"id\": \"RiHO4e0Ju3DS\"\n }\n ],\n \"learners\": [\n {\n \"id\": \"vKLoKUiy3Rbp\"\n }\n ],\n \"reviewers\": [\n {\n \"type\": \"manager\"\n },\n {\n \"type\": \"user\",\n \"email\": \"lead@acme.com\"\n }\n ],\n \"approvalPolicy\": \"all\",\n \"dueDate\": \"2026-11-30\",\n \"dueInDays\": 30,\n \"reminders\": {\n \"weekly\": false,\n \"onDueDate\": false\n },\n \"allowDuplicates\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"assignments": [
{
"object": "learning-assignment",
"id": "As5gNm3Kq0Zp",
"material": {
"object": "course",
"id": "RiHO4e0Ju3DS",
"url": "https://api.dock.us/v1/courses/RiHO4e0Ju3DS",
"name": "Sales onboarding"
},
"learners": [
{
"user": {
"id": "RiHO4e0Ju3DS",
"updatedAt": "2021-01-01T00:00:00.000Z",
"createdAt": "2021-01-01T00:00:00.000Z",
"object": "user",
"url": "https://api.dock.us/v1/users/RiHO4e0Ju3DS",
"firstName": "John",
"lastName": "Doe",
"avatar": "https://dock.us/avatar.png",
"email": "john.doe@example.com",
"name": "John Doe"
},
"status": "assigned",
"dueDate": "2026-11-30T00:00:00.000Z",
"warnings": []
}
]
}
]
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "The request could not be understood or was missing required parameters"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Access denied. You are not authorized to access this resource"
}
}{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please try again later"
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "The server has encountered a situation it does not know how to handle"
}
}Assign learning
Assign published courses and pathways to learners, the same as publishing a new assignment with Specific people in Learning admin. One assignment is created per material; every learner gets each one with the same reviewers, due date and reminders, and is emailed that it was assigned.
Get course and pathway IDs from courses and pathways, or Copy ID in Dock. Only published materials can be assigned.
Only an admin’s API key can assign learning; a key whose creator is no longer an admin gets 403. Each request can make at most 500 enrollments (materials × learners); split larger ones.
The request is checked before anything is created: an unknown, unpublished or archived material, or a learner or reviewer that is not a Dock user in your company (client users included), returns 400 naming each one, and nothing is assigned.
A learner who already has a pathway in progress is skipped. A learner who already has a course in progress is skipped too, so retrying a request does not enroll anyone twice; set allowDuplicates to give them a second enrollment of the course instead.
curl --request POST \
--url https://api.dock.us/{version}/learning-assignments \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"materials": [
{
"id": "RiHO4e0Ju3DS"
}
],
"learners": [
{
"id": "vKLoKUiy3Rbp"
}
],
"reviewers": [
{
"type": "manager"
},
{
"type": "user",
"email": "lead@acme.com"
}
],
"approvalPolicy": "all",
"dueDate": "2026-11-30",
"dueInDays": 30,
"reminders": {
"weekly": false,
"onDueDate": false
},
"allowDuplicates": false
}
'import requests
url = "https://api.dock.us/{version}/learning-assignments"
payload = {
"materials": [{ "id": "RiHO4e0Ju3DS" }],
"learners": [{ "id": "vKLoKUiy3Rbp" }],
"reviewers": [
{ "type": "manager" },
{
"type": "user",
"email": "lead@acme.com"
}
],
"approvalPolicy": "all",
"dueDate": "2026-11-30",
"dueInDays": 30,
"reminders": {
"weekly": False,
"onDueDate": False
},
"allowDuplicates": False
}
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({
materials: [{id: 'RiHO4e0Ju3DS'}],
learners: [{id: 'vKLoKUiy3Rbp'}],
reviewers: [{type: 'manager'}, {type: 'user', email: 'lead@acme.com'}],
approvalPolicy: 'all',
dueDate: '2026-11-30',
dueInDays: 30,
reminders: {weekly: false, onDueDate: false},
allowDuplicates: false
})
};
fetch('https://api.dock.us/{version}/learning-assignments', 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://api.dock.us/{version}/learning-assignments",
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([
'materials' => [
[
'id' => 'RiHO4e0Ju3DS'
]
],
'learners' => [
[
'id' => 'vKLoKUiy3Rbp'
]
],
'reviewers' => [
[
'type' => 'manager'
],
[
'type' => 'user',
'email' => 'lead@acme.com'
]
],
'approvalPolicy' => 'all',
'dueDate' => '2026-11-30',
'dueInDays' => 30,
'reminders' => [
'weekly' => false,
'onDueDate' => false
],
'allowDuplicates' => false
]),
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://api.dock.us/{version}/learning-assignments"
payload := strings.NewReader("{\n \"materials\": [\n {\n \"id\": \"RiHO4e0Ju3DS\"\n }\n ],\n \"learners\": [\n {\n \"id\": \"vKLoKUiy3Rbp\"\n }\n ],\n \"reviewers\": [\n {\n \"type\": \"manager\"\n },\n {\n \"type\": \"user\",\n \"email\": \"lead@acme.com\"\n }\n ],\n \"approvalPolicy\": \"all\",\n \"dueDate\": \"2026-11-30\",\n \"dueInDays\": 30,\n \"reminders\": {\n \"weekly\": false,\n \"onDueDate\": false\n },\n \"allowDuplicates\": false\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://api.dock.us/{version}/learning-assignments")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"materials\": [\n {\n \"id\": \"RiHO4e0Ju3DS\"\n }\n ],\n \"learners\": [\n {\n \"id\": \"vKLoKUiy3Rbp\"\n }\n ],\n \"reviewers\": [\n {\n \"type\": \"manager\"\n },\n {\n \"type\": \"user\",\n \"email\": \"lead@acme.com\"\n }\n ],\n \"approvalPolicy\": \"all\",\n \"dueDate\": \"2026-11-30\",\n \"dueInDays\": 30,\n \"reminders\": {\n \"weekly\": false,\n \"onDueDate\": false\n },\n \"allowDuplicates\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dock.us/{version}/learning-assignments")
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 \"materials\": [\n {\n \"id\": \"RiHO4e0Ju3DS\"\n }\n ],\n \"learners\": [\n {\n \"id\": \"vKLoKUiy3Rbp\"\n }\n ],\n \"reviewers\": [\n {\n \"type\": \"manager\"\n },\n {\n \"type\": \"user\",\n \"email\": \"lead@acme.com\"\n }\n ],\n \"approvalPolicy\": \"all\",\n \"dueDate\": \"2026-11-30\",\n \"dueInDays\": 30,\n \"reminders\": {\n \"weekly\": false,\n \"onDueDate\": false\n },\n \"allowDuplicates\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"assignments": [
{
"object": "learning-assignment",
"id": "As5gNm3Kq0Zp",
"material": {
"object": "course",
"id": "RiHO4e0Ju3DS",
"url": "https://api.dock.us/v1/courses/RiHO4e0Ju3DS",
"name": "Sales onboarding"
},
"learners": [
{
"user": {
"id": "RiHO4e0Ju3DS",
"updatedAt": "2021-01-01T00:00:00.000Z",
"createdAt": "2021-01-01T00:00:00.000Z",
"object": "user",
"url": "https://api.dock.us/v1/users/RiHO4e0Ju3DS",
"firstName": "John",
"lastName": "Doe",
"avatar": "https://dock.us/avatar.png",
"email": "john.doe@example.com",
"name": "John Doe"
},
"status": "assigned",
"dueDate": "2026-11-30T00:00:00.000Z",
"warnings": []
}
]
}
]
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "The request could not be understood or was missing required parameters"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Access denied. You are not authorized to access this resource"
}
}{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please try again later"
}
}{
"error": {
"code": "INTERNAL_SERVER_ERROR",
"message": "The server has encountered a situation it does not know how to handle"
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Courses and pathways to assign, 1 to 20. materials × learners can be at most 500 per request
1 - 20 elementsShow child attributes
Show child attributes
People to assign, 1 to 500, each by user id or email
1 - 500 elements- Option 1
- Option 2
Show child attributes
Show child attributes
Who reviews (up to 20) each learner's course submissions. Empty (the default) means no review. Reviews apply to courses, including the courses inside a pathway. Nobody reviews their own work
20Show child attributes
Show child attributes
[
{ "type": "manager" },
{ "type": "user", "email": "lead@acme.com" }
]
With several reviewers: whether all of them or any one must approve
all, any Due date in YYYY-MM-DD format, today or later. Provide at most one of dueDate or dueInDays; with neither there is no due date
"2026-11-30"
Due this many days after the assignment, 1 to 3650
1 <= x <= 365030
Reminder emails to learners who haven't finished. Both are off by default
Show child attributes
Show child attributes
Give learners who already have a course in progress a second enrollment of it, instead of skipping them. Pathways are never assigned twice
Response
The assignments created, one per material, in request order
Show child attributes
Show child attributes