Skip to content

Create embed package

POST
/wp-json/wp2lms-pro/embed-packages/v1/packages
curl --request POST \
--url 'https://example.com/wp-json/wp2lms-pro/embed-packages/v1/packages?blog_id=1' \
--header 'Content-Type: application/json' \
--header 'X-WP-Nonce: <X-WP-Nonce>' \
--data '{ "title": "Interactive lesson", "status": "publish", "html": "<!doctype html><html lang=\"en\"><title>Lesson</title><h1>Welcome</h1></html>" }'

Creates a CPT wp2lms_embed_pkg post (wp_insert_post) and optionally ingests content via ingest_from_request. This does not create WordPress pages: materialization is POST …/materialize-pages or POST …/batch. title is optional: empty after sanitize_text_field becomes “Untitled package”. status is optional, default publish; only publish / draft / private (sanitize_key) are kept, anything else PHP rewrites to publish. Content may be omitted — you get a package with no files (empty launch_path/meta). Otherwise one channel: a multipart file (file / package_file / package_zip, zip or html/htm), JSON files (path tree), or JSON html (stored as index.html). If both files and non-empty html are present and the tree has no index.html, PHP adds index.html from html. An empty files object is not treated as a tree. Ingest error after insert — PHP wp_delete_post(..., true) and returns that WP_Error. Requires manage_network (multisite) or edit_pages. Cookie + X-WP-Nonce or Application Password.

blog_id
integer
>= 1

Network site ID (switch_to_blog). Optional: defaults to the request current blog. Not a package id and not page_id. Minimum 1; on a single site it must match the current site — otherwise 400 embed_packages_invalid_blog. In a network an unknown site or a site from another network is 404 embed_packages_unknown_blog.

Example
1
object
title

Title of the new CPT post. Optional. Empty after sanitize → “Untitled package”. After ingest it may be overwritten from HTML/manifest.

string
status

Post_status of the new post. Optional, default publish. Any other value PHP rewrites to publish.

string
Allowed values: publish draft private
html

Raw HTML of a single launch file. Optional. Stored as index.html when there is no multipart and (if files is present) the tree does not already have index.html.

string
files

Map of relative paths to contents. Keys must be safe relative paths (PackageFilePolicy). An empty object is not treated as a tree. Unsafe path — unsafe_path; disallowed extension — disallowed_extension.

object
key
additional properties
One of:

Raw file text (HTML/CSS/JS).

string
Example
{
"title": "Interactive lesson",
"status": "publish",
"html": "<!doctype html><html lang=\"en\"><title>Lesson</title><h1>Welcome</h1></html>"
}

Package created. Body is package_payload (id, title, status, launch_*, meta).

Media typeapplication/json

package_payload response — CPT post plus flattened meta fields and the full meta object.

object
id

CPT wp2lms_embed_pkg post ID. Same number as {id} in GET/PATCH/DELETE/content/materialize-pages paths.

integer
title

Package post_title. After ingest PHP may replace it with the launch file <title>.

string
status

Package post_status. REST accepts publish/draft/private; the response is whatever is stored.

string
content_type

Copy of meta.content_type (web / scorm1.2 / scorm2004 / xapi or empty).

string
content_tool

Copy of meta.content_tool (authoring-tool detector or empty string).

string
launch_path

Copy of meta.launch_path — relative launch HTML, not a URL.

string
launch_url

Absolute launch URL (uploads baseurl + storage_rel + launch_path). Empty when there is no content.

string format: uri
activity_id

Copy of meta.activity_id.

string
storage_rel

Copy of meta.storage_rel under uploads.

string
is_multipage

Copy of meta.is_multipage.

boolean
pages
Array<object>
object
path

Relative HTML path inside the package directory (posix, no leading /). From PackagePagesIndex::scan.

string
title

Title from the file <title> tag, or the basename if the tag is missing.

string
meta
One of:

Full post meta array _wp2lms_embed_package (PackageMeta::get). Empty object when the package has not been ingested.

object
content_type

Type after ManifestPipeline — web, scorm1.2, scorm2004, or xapi. Empty until content is uploaded.

string
version

Version from the manifest (for SCORM often the same as content_type). Empty string for typical web packages.

string
activity_id

XAPI activity id. If the parser omitted it — {home}wp2lms-embed-package/{id}.

string
launch_path

Relative launch HTML inside storage (from the manifest or fallback index.html).

string
title

Title from launch HTML / manifest; PHP may overwrite the package post_title with this value.

string
mastery_score

Mastery score from imsmanifest (SCORM), otherwise null.

number
nullable
content_tool

Authoring-tool detector: ispring, articulate_rise, articulate_storyline, articulate_presenter, captivate, elucidat, or an empty string.

string
storage_rel

Path from uploads basedir, wp2lms-embed-packages/{id}/.

string
uploaded_at

Unix time of the last successful content write (time() in finalize).

integer
is_multipage

True only for content_type=web with no content_tool and ≥2 HTML files in the index.

boolean
pages

HTML index (path+title) when the package is multipage; otherwise [].

Array<object>
object
path

Relative HTML path inside the package directory (posix, no leading /). From PackagePagesIndex::scan.

string
title

Title from the file <title> tag, or the basename if the tag is missing.

string
Example
{
"id": 42,
"title": "Interactive lesson",
"status": "publish",
"content_type": "web",
"content_tool": "",
"launch_path": "index.html",
"launch_url": "https://lms.example.com/wp-content/uploads/wp2lms-embed-packages/42/index.html",
"activity_id": "https://lms.example.com/wp2lms-embed-package/42",
"storage_rel": "wp2lms-embed-packages/42/",
"is_multipage": false,
"pages": [],
"meta": {
"content_type": "web",
"version": "",
"activity_id": "https://lms.example.com/wp2lms-embed-package/42",
"launch_path": "index.html",
"title": "Interactive lesson",
"mastery_score": null,
"content_tool": "",
"storage_rel": "wp2lms-embed-packages/42/",
"uploaded_at": 1726252800,
"pages": [],
"is_multipage": false
}
}

Embed_packages_bad_file — multipart is not ZIP or HTML/HTM; embed_packages_invalid_blog — invalid blog_id.

Media typeapplication/json
object
code

WP_Error code (get_error_code()), e.g. embed_packages_not_found.

string
message

WP_Error text (get_error_message()).

string
data

WP_Error data. Usually { "status": 404 }. Ingest/materialize errors without status are returned by WordPress REST as 500.

object
Example
{
"code": "embed_packages_not_found",
"message": "Package not found.",
"data": {
"status": 404
}
}

Not authenticated. WordPress REST: rest_forbidden (status 401) when there is no cookie session. Cookie + X-WP-Nonce or Application Password.

Media typeapplication/json
object
code

WP_Error code (get_error_code()), e.g. embed_packages_not_found.

string
message

WP_Error text (get_error_message()).

string
data

WP_Error data. Usually { "status": 404 }. Ingest/materialize errors without status are returned by WordPress REST as 500.

object
Example
{
"code": "embed_packages_not_found",
"message": "Package not found.",
"data": {
"status": 404
}
}

Missing manage_network (multisite) or edit_pages (single site), or invalid REST nonce (rest_cookie_invalid_nonce).

Media typeapplication/json
object
code

WP_Error code (get_error_code()), e.g. embed_packages_not_found.

string
message

WP_Error text (get_error_message()).

string
data

WP_Error data. Usually { "status": 404 }. Ingest/materialize errors without status are returned by WordPress REST as 500.

object
Example
{
"code": "embed_packages_not_found",
"message": "Package not found.",
"data": {
"status": 404
}
}

Embed_packages_unknown_blog — that site does not exist in the network, or it belongs to another network.

Media typeapplication/json
object
code

WP_Error code (get_error_code()), e.g. embed_packages_not_found.

string
message

WP_Error text (get_error_message()).

string
data

WP_Error data. Usually { "status": 404 }. Ingest/materialize errors without status are returned by WordPress REST as 500.

object
Example
{
"code": "embed_packages_not_found",
"message": "Package not found.",
"data": {
"status": 404
}
}

WP_Error with no HTTP status in data — wp_insert_post or ingest failure (empty_tree, unsafe_path, disallowed_extension, zip_open, unzip_failed, process_failed, mkdir_failed, write_failed, invalid_file_value, unsafe_zip, missing_zip, and similar). WordPress REST surfaces those as 500. The package is deleted on ingest failure.

Media typeapplication/json
object
code

WP_Error code (get_error_code()), e.g. embed_packages_not_found.

string
message

WP_Error text (get_error_message()).

string
data

WP_Error data. Usually { "status": 404 }. Ingest/materialize errors without status are returned by WordPress REST as 500.

object
Example
{
"code": "embed_packages_not_found",
"message": "Package not found.",
"data": {
"status": 404
}
}