Skip to main content
https://.thoughtindustries.com

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.

POSThttps://example.thoughtindustries.com/v3/assetLibraryItems

This endpoint is served by the v3 API. Its full path is https://{instance}.thoughtindustries.com/v3/assetLibraryItems, not the /incoming/v2 base 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 sourceUrl over 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.

NameTypeRequiredLocationDescription
titlestringYesbodyDisplay title. Maximum 500 characters.
assetTypestringYesbodyOne of image, wysiwyg, resource_file, scorm, xapi. certificateTemplate is rejected.
sourceUrlurlYesbodyHosted HTTP or HTTPS URL. Required for every type, including wysiwyg.
descriptionstringNobodyMaximum 5000 characters.
fileNamestringNobodyOriginal file name. Maximum 500 characters. When omitted, the last path segment of sourceUrl is used.
tagIdsuuid[]NobodyTag IDs to associate.
imageAltTextstringNobodyImage only. Maximum 250 characters.
imageCaptionstringNobodyImage only. Maximum 2000 characters.
imageLinkurlNobodyImage only. HTTP or HTTPS.
imageNewTabbooleanNobodyImage only. Open imageLink in a new tab.
imageTitlestringNobodyImage only. Maximum 500 characters.

assetType values you can create

ValueWhat it storesIngest
imageImage fileSynchronous. Response includes body when the fetch succeeds.
resource_filePDF or other downloadable fileSynchronous, same as image.
scormSCORM packageAsynchronous. Status 202, processingStatus: "pending".
xapixAPI packageAsynchronous, same as SCORM.
wysiwygRich-text snippetsourceUrl 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.