Create a content record

Prev Next
Post
/contents

Creates a content record in created (draft) state.

A request can carry at most one upload item (elearning, video or image) plus one non-upload item (rich_text or url). For each upload item the response returns a signedPutUrls entry — PUT the artefact to that URL to complete the item. Upload items and url items are processed asynchronously; rich_text items complete synchronously.

authorRef is required. It is your organisation's reference for the acting user and drives the recorded authorship. The user must exist in your organisation and be active. A new, suspended, expired or deleted user is rejected. An optional collaborationId makes the collaboration own the content; the author is then recorded as the actor and must be a member of that collaboration.

skills and topics are only stored when publishWhenReady is true; without it the request is rejected, because they would be discarded. To tag a draft, publish it with skills and topics later. Every skill must already exist in your organisation; a topic is a free name. Both are stored in the content tags, and the reads return tags, skills and topics.

completionType: on_elearning_completion never completes for a web format e-learning package. The request is rejected when meta.format: web is supplied explicitly; when the format is detected during processing, the content stays in created state instead.

isOfficial: true creates the content as endorsed. A cpdCategoryId is only accepted on endorsed content, so send it together with isOfficial: true; without it the request is rejected with 400. The category must exist in your organisation, or the request is rejected with 422.

A thumbnail is required before the content can publish. This endpoint does not take image bytes. Send thumbnail: { uploadId } with a UUID you generate, and the response returns a matching signedPutUrls entry. PUT the image (JPEG, PNG, GIF or WebP) to that URL, the same way you PUT an item file. Thumbnail processing is asynchronous: the content stays created until the image has been resized and stored, then it becomes ready, and it publishes on its own when publishWhenReady is true. The URL is valid for about 10 minutes. To get a new one, or to replace the thumbnail later, send a PATCH with thumbnail again. Content without a thumbnail never becomes ready. Bytes that are not a readable image end as a placeholder thumbnail, which still counts as a thumbnail for readiness, so check what you upload. The uploadId must differ from every item uploadId in the same request (400 otherwise).

OAuth2 (Cognito) tokens need the api/write or api/all scope. API tokens are not scoped.

Security
HTTP
Type basic

HTTP Basic authentication using your Tenant ID and API secret.

  • Username is the Tenant ID (i.e. eu-west-2_AbcdEfghI)
  • Password is the API secret you would have received.

You can also authenticate using OAuth 2.0 client credentials (oauth2 security scheme) instead of Basic auth.

OAuth

OAuth 2.0 client credentials authentication.

Use the following token endpoints (replace :tenantId with your Tenant ID):

  • Public API access tokens

    • Staging: https://public.api.learnstaging.link/oauth2/token/:tenantId
    • Production: https://public.api.learn.link/oauth2/token/:tenantId
    • Staging MEA: https://public.api.meastaging.learn.tech/oauth2/token/:tenantId
    • Production MEA: https://public.api.mea.learn.tech/oauth2/token/:tenantId
  • Webhooks access tokens

    • Staging: https://user.api.learnstaging.link/oauth2/token/:tenantId
    • Production: https://user.api.learn.link/oauth2/token/:tenantId
    • Staging MEA: https://user.api.meastaging.learn.tech/oauth2/token/:tenantId
    • Production MEA: https://user.api.mea.learn.tech/oauth2/token/:tenantId

All access tokens must be sent using the Authorization: Bearer <access_token> header.

Scopes

For API access (non-webhooks), the following scopes are available:

  • api/all – Full read and write access to the API.
  • api/read – Read-only access to the API.
  • api/write – Write access to the API.

For webhooks, the following scopes are available:

  • api/webhooks – Access to webhook functionality.
  • api/all – Full read and write access to the API, including webhooks.

Tokens must include appropriate scopes for the endpoints you wish to call.

FlowClient Credentials
Token URLhttps://public.api.learn.link/oauth2/token/:tenantId
Scopes:
api/writeWrite access to the API.
Body parameters
createContent

An e-learning package with a welcome text

Creates a draft with one upload item and one rich text item, and stores a skill and a topic with it. It also asks for a thumbnail upload URL. PUT the package bytes and the thumbnail image to the two returned signedPutUrls entries; once both are processed the content publishes itself.

{
  "title": "Onboarding pack",
  "languageCode": "en-gb",
  "authorRef": "UID30084022",
  "publishWhenReady": true,
  "thumbnail": {
    "uploadId": "8b1e3d2a-4c5f-4e6a-9b7c-0d1e2f3a4b5c"
  },
  "skills": [
    "leadership"
  ],
  "topics": [
    "onboarding"
  ],
  "completionType": "on_elearning_completion",
  "items": [
    {
      "type": "elearning",
      "rank": 0,
      "meta": {
        "name": "course.zip",
        "uploadId": "123e4567-e89b-42d3-a456-426614174000"
      }
    },
    {
      "type": "rich_text",
      "rank": 1,
      "summary": "Welcome",
      "meta": {
        "body": "

Welcome to the team!

" } } ] }
Expand All
object

authorRef and, when present, collaborationId are validated in your organisation before anything is created.

title
string Required
Min length3
Max length150
ExampleOnboarding pack
languageCode
string Required

The content language, for example en-gb.

Exampleen-gb
authorRef
string Required

Your organisation's reference for the acting user. The user becomes the recorded actor, and the author unless a collaboration owns the content. The user must be active. A new, suspended, expired or deleted user is rejected.

ExampleUID30084022
collaborationId
string

The collaboration that owns the content. The authorRef user must be a member of it, or the request is rejected with 422.

Pattern^[0-9a-fA-F]{24}$
Example5c8936159ec2d00010cdd334
publishWhenReady
boolean

Publish automatically when the content becomes ready: every item has completed processing and the content has a thumbnail. Send thumbnail to get a thumbnail upload URL in the same response; without a thumbnail the content stays created. The flag is stored so the publish happens as soon as the record is ready.

skills
Array of string

Skills to associate with the content. Each name must be an existing skill in your organisation, or the request is rejected with 422. Only accepted together with publishWhenReady: true. Stored in the content tags alongside the topics.

string
Max length255
Exampleleadership
topics
Array of string

Topics to associate with the content. Free names; a topic is not checked against your organisation's tags. Only accepted together with publishWhenReady: true. Stored in the content tags alongside the skills. A name cannot appear in both lists.

string
Max length255
Exampleonboarding
primaryCategory
string

The declared category. A default is inferred when it is omitted. The value is case insensitive, but send it in lower case.

Valid values[ "file", "article", "elearning", "url", "quiz", "assessment", "video", "event", "pathway", "question", "standard" ]
Exampleelearning
completionType
string

How the content is completed. Defaults to auto. auto, confirm and external apply to any content; on_elearning_completion requires an e-learning item. The quiz, assessment and interactive types require item types this API cannot create yet, so they are rejected with a 409.

Valid values[ "auto", "confirm", "external", "on_passing_quizzes", "on_passing_observer_completed_quizzes", "on_passing_assessments", "on_elearning_completion", "on_completing_interactive" ]
customDurationInMs
integer

A custom duration in milliseconds.

Minimum1.0
Example60000
isOfficial
boolean

Create the content as endorsed by your organisation. Defaults to false.

Exampletrue
cpdCategoryId
string

The CPD category to record this content against. Only accepted together with isOfficial: true (400 otherwise). The category must exist in your organisation (422 otherwise).

Pattern^[0-9a-fA-F]{24}$
Example507f1f77bcf86cd799439012
thumbnail
object (ContentThumbnailInput)

Asks for a thumbnail upload URL. The content thumbnail is uploaded like an item file: give the upload a UUID here and PUT the image bytes (JPEG, PNG, GIF or WebP) to the signedPutUrls entry that echoes it. The uploadId is not stored; it only pairs this request with its response entry, so it must differ from every item uploadId in the same request (400 otherwise). A content has one thumbnail, and a later upload replaces it. Processing is asynchronous: the thumbnail counts for readiness once the image has been resized and stored.

uploadId
string (uuid) Required

A UUID you generate for this upload.

Example8b1e3d2a-4c5f-4e6a-9b7c-0d1e2f3a4b5c
items
Array

The content items. At most one upload item (elearning, video or image) plus one non-upload item (rich_text or url) per request. Each rank must be unique.

OneOf
ContentCreateRichTextItem
object (ContentCreateRichTextItem)
type
string Required
Valid values[ "rich_text" ]
rank
integer Required

The display position of the item.

Minimum0.0
summary
string Required

A short description of the item.

meta
object Required
body
string Required

The rich text body. May contain HTML.

Min length1
Max length100000
ContentCreateUrlItem
object (ContentCreateUrlItem)
type
string Required
Valid values[ "url" ]
rank
integer Required
Minimum0.0
summary
string Required
meta
object Required
url
string Required

A public HTTP(S) address. The link preview is generated asynchronously.

Examplehttps://example.com/guide
ContentCreateElearningItem
object (ContentCreateElearningItem)
type
string Required
Valid values[ "elearning" ]
rank
integer Required
Minimum0.0
summary
string
meta
object Required
name
string Required

The package file name, for example course.zip.

Examplecourse.zip
uploadId
string (uuid) Required

A client-generated UUID for the upload. The response echoes it in signedPutUrls.

format
string

The package format. Normally detected during processing — supply it only when known.

Valid values[ "scorm12", "scorm2004", "cmi5", "tincan", "web" ]
ContentCreateFileItem
object (ContentCreateFileItem)
type
string Required

The file kind. The file extension in meta.name must match it.

Valid values[ "video", "image" ]
rank
integer Required
Minimum0.0
summary
string
meta
object Required
name
string Required

The file name, for example intro.mp4 or cover.png.

Exampleintro.mp4
uploadId
string (uuid) Required

A client-generated UUID for the upload. The response echoes it in signedPutUrls.

canDownload
boolean Required

Whether learners can download the file.

Responses
201

Created — the content is in created (draft) state

Expand All

The created content with its presigned upload URLs. In the rare case that the content was created but could not be read back, the response is the minimal form: id, status and signedPutUrls only. The content exists in both cases — do not retry the request. A full body also satisfies the minimal shape, so this is anyOf.

AnyOf
object
object
id
string

Unique identifier for the content

Pattern^[0-9a-fA-F]{24}$
Example5c8936159ec2d00010cdd334
title
string

Title of the content

Max length255
ExampleAn amazing video
description
string

Detailed description of the content, may contain HTML

Max length65536
ExampleThis content looked really interesting and relevant to recent conversations in the development team
tags
Array of string

List of tags associated with this content. Omitted when the tag source cannot be read, so an absent field means "tags unavailable" rather than "no tags".

string
Max length255
Examplelearning
skills
Array of string

The tags entries that the taxonomy marks as a skill. Additive: every name is also in tags. A tag the taxonomy does not hold is in neither skills nor topics. Both fields are absent when the taxonomy cannot be read.

string
Max length255
Exampleleadership
topics
Array of string

The tags entries that the taxonomy marks as a topic. Additive: every name is also in tags. A tag the taxonomy does not hold is in neither topics nor skills. Both fields are absent when the taxonomy cannot be read.

string
Max length255
Exampleonboarding
type
string

The kind of artifact associated with this content record.

Courses are represented as pathway. Pathways will be served by a dedicated Pathways API in a future release and will stop appearing on this endpoint at that point, so treat pathway as temporary here.

Valid values[ "article", "assessment", "broadcast", "cmi5", "elearning", "event", "file", "mixed", "pathway", "question", "quiz", "scorm", "url", "video" ]
Max length24
Examplevideo
createdAt
string (date-time)

Timestamp when the content was created

Example2019-03-13T16:15:24.000Z
updatedAt
string (date-time)

Timestamp when the content was last updated

Example2019-03-13T16:15:24.000Z
author
string | null

User ID who authored this content. Nullable for auto-curated content.

Pattern^[0-9a-fA-F]{24}$
Example5c8936159ec2d00010cdd334
isOfficial
boolean

Whether the content has been recognized for its importance or validity by the customer organization

Exampletrue
cpdCategoryId
string | null

The CPD category the content is recorded against, or null when it has none. Present when a record is read by its id or returned by a v2 create or update, for content held by the content source that carries CPD data. The field is not present in the results of the list endpoint, nor on a record that exists only in the legacy content source.

Pattern^[0-9a-fA-F]{24}$
Example507f1f77bcf86cd799439012
duration
object | null

The expected time to complete the content. Null for Event content types. For SAP-imported content, this value may reflect a system default rather than a precise measured duration.

value
integer | null

Duration in the specified unit. Null when no duration is available (e.g. pathways).

Example15
unit
string

The unit of the duration value. Always 'minutes'.

Valid values[ "minutes" ]
Exampleminutes
contentHistory
Array of object (ContentHistoryEntry)

Chronological history of actions on this content (from content-service). May be empty when there is no recorded history.

object
action
string

Type of change or event recorded for the content.

timestamp
string (date-time)

When the action occurred.

performedBy
object (ContentHistoryPerformedBy)
type
string

Kind of actor (for example user or system).

value
string

Identifier or value associated with the actor.

lastUpdatedBy
object | null

Last actor who updated the content, derived from history (or author fallback). Null when neither history nor author resolves.

id
string | null

User ID or service identifier.

email
string | null

Email from the user view when available.

reference
string | null

External reference (e.g. HR id) when stored on the user view.

provider
object

The content provider. Defaults to Thrive for natively created content.

id
string

Provider identifier key.

Examplethrive
name
string

Human-readable provider display name.

ExampleThrive
status
string

Lifecycle status of the content. A legacy (content-service) record derives the value: archived content reports archived, content with a publish time reports published, and all other content reports created. A content-core record maps its lifecycle status onto the same values, where draft and ready both report created. deleted is a filter value only and is never returned: a legacy record returned by a deleted status filter reports its pre-deletion state, and a deleted content-core record is physically gone.

Valid values[ "created", "published", "archived" ]
Examplepublished
items
Array of object (ContentItemState)

The items that make up a content record, with per-item processing state. Only GET /contents/{id} returns this field, and only for records served from content-core; the GET /contents list never includes it.

object

One item within a content record, with its processing state.

id
string

Unique identifier for the item

Example5c8936159ec2d00010cdd334
type
string

The item type

Exampleelearning
rank
integer

The item's position within the content, lowest first

Example0
summary
string

A short label for the item, shown to learners

ExampleWelcome
status
string

The item's processing state. An item must reach ok before the content can become ready.

Valid values[ "processing", "ok", "error" ]
Exampleprocessing
error
string | null

Why processing failed, when status is error

Exampleopenapi-json-null-sentinel-value-2BF93600-0FE4-4250-987A-E5DDB203E464
signedPutUrls
Array of object (SignedPutUrl)

One entry for each upload item in the request, plus one for the thumbnail when the request carried thumbnail. Empty when the request carried neither. In the rare case that the thumbnail URL could not be issued, its entry is missing while the content was still created; send a PATCH with thumbnail to get one.

object

A presigned URL to PUT one upload's bytes to: an item file, or the content thumbnail image.

uploadId
string (uuid)

The uploadId you supplied for the item, or for the thumbnail, this URL belongs to

Example4f1c2b7e-9a3d-4c8e-b2f1-6d0a7c5e3b91
url
string

The presigned URL. Time-limited (about 10 minutes) — upload promptly.

Examplehttps://s3.example.com/uploads/4f1c2b7e?X-Amz-Signature=...
ContentWriteMinimalResponse
object (ContentWriteMinimalResponse)
id
string

Unique identifier for the content

Example5f9d88d6e1b2a34c56d78902
status
string
Valid values[ "created", "published", "archived" ]
Examplecreated
signedPutUrls
Array of object (SignedPutUrl)

On a create, one entry for each upload item in the request. On an update, one entry for each upload item added and each item whose file was replaced. Plus one for the thumbnail when the request carried thumbnail. Empty when the request carried none.

object

A presigned URL to PUT one upload's bytes to: an item file, or the content thumbnail image.

uploadId
string (uuid)

The uploadId you supplied for the item, or for the thumbnail, this URL belongs to

Example4f1c2b7e-9a3d-4c8e-b2f1-6d0a7c5e3b91
url
string

The presigned URL. Time-limited (about 10 minutes) — upload promptly.

Examplehttps://s3.example.com/uploads/4f1c2b7e?X-Amz-Signature=...
400

Bad Request — a cross-field rule failed (more than one upload or non-upload item, skills or topics without publishWhenReady, a name in both skills and topics, on_elearning_completion with a web format item, cpdCategoryId without isOfficial: true, a thumbnail uploadId that repeats an item uploadId), or the upstream content source rejected the payload (see violations when present)

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
401

Unauthorized

object

Unauthorized

status
number
Example401
error
string
ExampleUnauthorized
message
string
403

Forbidden — the OAuth2 token does not carry the api/write or api/all scope

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
409

Conflict — the upstream content source reported a conflict, for example a duplicate import reference

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
415

Unsupported Media Type — Content-Type must be application/json

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
422

Unprocessable Content — a field failed validation (see violations), authorRef does not match an active user, collaborationId does not resolve in this organisation, the author is not a member of the collaboration, a skill is not an existing skill in this organisation, or cpdCategoryId does not match a CPD category in this organisation

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
429

Too Many Requests — the upstream content source is rate limiting this organisation. Retry after the Retry-After header when it is present.

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
500

Internal Server Error — the request failed inside the API service. The content may not have been created.

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
502

Upstream content source failure, or the skills or the CPD category could not be verified — the content was not created

Expand All
object

The error envelope of the V2 endpoints.

error
object
status
integer
Example422
error
string
ExampleUnprocessable Entity
message
string
ExampleValidation failed
violations
Array of object (V2Violation)

Present on field validation failures. One entry per failed rule.

object

One failed validation rule.

reference
string

The dotted path of the field that failed, for example items.0.meta.body. Empty for a body-level rule.

Exampletitle
message
string

Why the field failed.

Example"title" length must be at least 3 characters long
default

An unexpected error has occurred

When any default error occurs it may be a system failure and persistent errors may require support.

Expand All
id
string
ExampleUNIQUEREFERENCE111000
timestamp
string
Example2020-03-09T22:18:26.625Z
eventType
string
Valid values[ "user_joined", "user_updated", "user_suspended" ]
message
object

The server is unable to process the request

status
number
Example500
error
string
ExampleInternal Server Error