Expand dynamic shortcodes
const url = 'https://example.com/wp-json/wp2lms/turbo/v1/dsh/expand';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"items":[{"id":"island-hero","src":"e2RzaDpwb3N0OmNvbnRlbnR9","post_id":42}],"post_id":42}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/wp-json/wp2lms/turbo/v1/dsh/expand \ --header 'Content-Type: application/json' \ --data '{ "items": [ { "id": "island-hero", "src": "e2RzaDpwb3N0OmNvbnRlbnR9", "post_id": 42 } ], "post_id": 42 }'Publicly expands Dynamic Shortcode islands for hydration on a Turbo page. PHP: at most 40 items (Expander::MAX_ITEMS); src is the base64url-encoded shortcode source (decodeSrc), not raw {dsh:…} in JSON. Root post_id sets $GLOBALS['post'] for context; a per-item post_id wins.
Empty/non-array items or every item dropped (empty id/src, bad base64) — 400 invalid_items. More than 40 — 400 too_many_items. Dynamic Shortcodes plugin missing or filter wp2turbo/dsh/enable disabled the bridge — 403 disabled. A wp_rest nonce is required (403 invalid_nonce).
This is not GET …/static/{id} and not the heartbeat data[wp2t_dsh] fallback. REST has no 503: the heartbeat 503 is not mapped onto this route. A cookie session is not required.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Islands to expand, max 40. Empty array or non-array — 400 invalid_items. A JSON string is json_decoded by PHP.
object
Client hydration-island id (same value as expansions[].id). Empty id is dropped by PHP.
Shortcode source as base64url (Expander::encodeSrc / decodeSrc), not raw {dsh:…}. Empty or undecodable items are skipped. Decoded src limit is 16384 bytes.
Post context for this island (overrides root post_id). 0 / omitted — root post_id is used.
Post ID for setup_postdata / default post:content embed when an item has no post_id of its own.
Example
{ "items": [ { "id": "island-hero", "src": "e2RzaDpwb3N0OmNvbnRlbnR9", "post_id": 42 } ], "post_id": 42}Responses
Section titled “Responses”Ok, expansions list (id, html, optional hash), assets object (styles/scripts/headScripts), fresh wp_rest nonce.
object
PHP always true on HTTP 200.
Island list in processing order, not an object keyed by id.
object
Same island id as in the request.
Expanded HTML. Island errors become an HTML comment <!-- dsh-error: … -->, not a WP_Error for the whole request.
Fragment contentHash, only when the island is a post:content embed via StaticPageRenderer.
object
CSS required by the inserted islands.
object
Style or script URL; may be null for an inline script.
Inline JS when PHP provided the inline key.
Body scripts.
object
Style or script URL; may be null for an inline script.
Inline JS when PHP provided the inline key.
Head scripts.
object
Style or script URL; may be null for an inline script.
Inline JS when PHP provided the inline key.
Fresh wp_create_nonce(‘wp_rest’) for the next expand.
Example
{ "ok": true, "expansions": [ { "id": "island-hero", "html": "<p>John Petrov</p>" } ], "assets": { "styles": [], "scripts": [], "headScripts": [] }, "nonce": "a1b2c3d4e5"}Invalid_items — no valid islands; too_many_items — more than 40 items.
object
Machine-readable WP_Error code (for example wp2lms_static_builder_busy, rest_forbidden, invalid_nonce).
Human-readable error message from PHP / WordPress REST.
Usually { status: <HTTP code> }. If status is missing, core REST often returns 500.
object
Example
{ "code": "wp2lms_static_builder_busy", "message": "Build is currently building and cannot be updated.", "data": { "status": 409 }}Disabled — Dynamic Shortcodes missing or wp2turbo/dsh/enable=false; invalid_nonce — missing/invalid wp_rest nonce.
object
Machine-readable WP_Error code (for example wp2lms_static_builder_busy, rest_forbidden, invalid_nonce).
Human-readable error message from PHP / WordPress REST.
Usually { status: <HTTP code> }. If status is missing, core REST often returns 500.
object
Example
{ "code": "wp2lms_static_builder_busy", "message": "Build is currently building and cannot be updated.", "data": { "status": 409 }}