Create Asset Library Item
Create an Asset Library item from a hosted sourceUrl. SCORM and xAPI ingest asynchronously.
Creates an Asset Library item from a hosted URL. Thought Industries fetches sourceUrl and stores
the file. Image and resource_file (PDF and other downloads) ingest in the request. SCORM and xAPI
return immediately and finish in the background — poll
Get Asset Library Item until processingStatus is ready or
failed.
https://example.thoughtindustries.com/v3/assetLibraryItemsThis endpoint is served by the v3 API. Its full path is
https://{instance}.thoughtindustries.com/v3/assetLibraryItems, not the/incoming/v2base URL used by the rest of this reference. Use the full URL shown in the examples below.
Hosted URL only. There is no multipart upload and no pre-signed upload URL. The instance fetches
sourceUrlover HTTP or HTTPS. Do not point it at internal, loopback, or private-network addresses.
Example request — image (synchronous)
curl -X POST "https://{instance}.thoughtindustries.com/v3/assetLibraryItems" \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"title": "Test Image Asset",
"assetType": "image",
"sourceUrl": "https://picsum.photos/id/237/400/300.jpg",
"description": "A test image for API validation",
"fileName": "test-dog.jpg",
"imageAltText": "A cute dog",
"imageCaption": "Photo from picsum",
"imageLink": "https://example.com",
"imageNewTab": true,
"imageTitle": "Dog Photo"
}'Example request — SCORM (asynchronous)
curl -X POST "https://{instance}.thoughtindustries.com/v3/assetLibraryItems" \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"title": "Test SCORM Asset",
"assetType": "scorm",
"sourceUrl": "https://example.com/packages/golf-scorm-2004.zip",
"description": "A test SCORM package for API validation",
"fileName": "golf-scorm-2004.zip"
}'Parameters
Requires the centrallibrary.new permission. A company API key satisfies this. A manager session
needs that permission on the role.
| Name | Type | Required | Location | Description |
|---|---|---|---|---|
title | string | Yes | body | Display title. Maximum 500 characters. |
assetType | string | Yes | body | One of image, wysiwyg, resource_file, scorm, xapi. certificateTemplate is rejected. |
sourceUrl | url | Yes | body | Hosted HTTP or HTTPS URL. Required for every type, including wysiwyg. |
description | string | No | body | Maximum 5000 characters. |
fileName | string | No | body | Original file name. Maximum 500 characters. When omitted, the last path segment of sourceUrl is used. |
tagIds | uuid[] | No | body | Tag IDs to associate. |
imageAltText | string | No | body | Image only. Maximum 250 characters. |
imageCaption | string | No | body | Image only. Maximum 2000 characters. |
imageLink | url | No | body | Image only. HTTP or HTTPS. |
imageNewTab | boolean | No | body | Image only. Open imageLink in a new tab. |
imageTitle | string | No | body | Image only. Maximum 500 characters. |
assetType values you can create
| Value | What it stores | Ingest |
|---|---|---|
image | Image file | Synchronous. Response includes body when the fetch succeeds. |
resource_file | PDF or other downloadable file | Synchronous, same as image. |
scorm | SCORM package | Asynchronous. Status 202, processingStatus: "pending". |
xapi | xAPI package | Asynchronous, same as SCORM. |
wysiwyg | Rich-text snippet | sourceUrl is accepted and not fetched. body stays null. |
Image-specific fields (imageAltText, imageCaption, imageLink, imageNewTab, imageTitle)
are rejected unless assetType is image.
Example response — image (201)
Note the data wrapper — v3 endpoints nest their payload under data.
{
"data": {
"id": "7a6b5c4d-3e2f-1a0b-9c8d-7e6f5a4b3c2d",
"title": "Test Image Asset",
"assetType": "image",
"description": "A test image for API validation",
"body": "https://ti-course-uploads.s3.amazonaws.com/…/test-dog.jpg",
"contentType": "image/jpeg",
"fileName": "test-dog.jpg",
"tagIds": [],
"version": 1,
"locationIds": [],
"imageAltText": "A cute dog",
"imageCaption": "Photo from picsum",
"imageLink": "https://example.com",
"imageNewTab": true,
"imageTitle": "Dog Photo",
"isNew": true,
"processingStatus": "ready",
"createdAt": "2026-08-26T15:36:24.000Z",
"updatedAt": "2026-08-26T15:36:24.000Z"
}
}Example response — SCORM (202)
{
"data": {
"id": "443d8182-d461-4568-a777-918ca729fd85",
"title": "Test SCORM Asset",
"assetType": "scorm",
"description": "A test SCORM package for API validation",
"body": null,
"contentType": null,
"fileName": "golf-scorm-2004.zip",
"tagIds": [],
"version": 1,
"locationIds": [],
"imageAltText": null,
"imageCaption": null,
"imageLink": null,
"imageNewTab": false,
"imageTitle": null,
"isNew": true,
"processingStatus": "pending",
"createdAt": "2026-08-26T20:19:55.000Z",
"updatedAt": "2026-08-26T20:19:55.000Z"
}
}A 202 is not a finished package. Poll GET /v3/assetLibraryItems/{id} until
processingStatus is ready (then body is populated) or failed. Failed ingest jobs are not
retried by sending the same ID — create a new item.
The new item appears in the admin Asset Library after search indexing completes. That write is best-effort and does not change this response.
Errors
Image fields on a non-image type return 422:
{
"code": "IMAGE_FIELDS_NOT_ALLOWED",
"message": "Image-specific fields can only be set on assets with type \"image\".",
"category": "BUSINESS_LOGIC",
"timestamp": "2026-08-26T15:36:24.000Z",
"statusCode": 422
}A sourceUrl the instance cannot fetch or store for an image or resource_file returns 422
with code: "ASSET_UPLOAD_FAILED" and
message: "Failed to process the asset file. Please verify the source URL and try again."
If a SCORM or xAPI job cannot be queued, the item is still created and the response is 202 with
processingStatus: "failed". Check that field; do not assume 202 means the package will become
ready.
Malformed field values — a non-enum assetType, a sourceUrl that is not http/https, a
non-UUID in tagIds, or any unrecognized property — return 400 with code: "BAD_REQUEST" and
category: "CLIENT_ERROR". message names the field. timestamp, statusCode, and
metadata.errors are present on the same body; see List Asset Library Items
for the shape.
A missing or invalid API key returns 401 with code: "UNAUTHENTICATED". A manager session
without centrallibrary.new returns 403 with code: "FORBIDDEN" and
message: "Insufficient permissions: centrallibrary.new required".
Rate limit
60 requests per 60 seconds, counted per instance. This limit is specific to this endpoint and is
independent of the per-family rate limits that apply to /incoming/v2 endpoints. For more than a
handful of files, use Batch create.