Embedded Creator
Let sellers edit an Experience directly inside your product.
10. Quickstart C — embedded Creator
- Register
https://dashboard.acmestay.exampleas an Integration allowed origin. - Resolve the Experience from your backend (Quickstart A step 1).
- Mint a session (never from the browser):
SESSION_JSON=$(curl -sS -X POST "$ARCHWALK_API_BASE/api/v1/360/creator-sessions" \
-H "Authorization: Bearer $AW360_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"origin\": \"https://dashboard.acmestay.example\",
\"experience_id\": \"$EXPERIENCE_ID\",
\"permitted_actions\": [
\"experiences:read\",
\"experiences:write\",
\"experiences:publish\",
\"panoramas:read\",
\"panoramas:write\",
\"panoramas:upload\"
]
}")
export SESSION_API_ID=$(echo "$SESSION_JSON" | jq -r .api_id)
export CREATOR_SESSION_TOKEN=$(echo "$SESSION_JSON" | jq -r .token)
- Return
SESSION_API_IDandCREATOR_SESSION_TOKENto your dashboard over your own authenticated API (never the Partner API key). - Iframe
srcis only the session id, never the token:
<iframe
id="creator"
title="ArchWalk 360 Creator"
src="https://YOUR_ARCHWALK_APP_HOST/aw360/c/SESSION_API_ID"
style="width:100%;height:80vh;border:0"
></iframe>
- After
creator:ready-for-init, postcreator:initwith{ token }to the Creator origin. See postMessage protocol.
19. Creator session and iframe
Mint — POST /api/v1/360/creator-sessions
Scope creator_sessions:issue. Status 201.
| Field | Required | Notes |
|---|---|---|
origin | Yes | Parent page origin; must be on the Integration allowlist |
permitted_actions | Yes | Non-empty subset of credential scopes; cannot include creator_sessions:issue |
experience_id | One binding required | Opaque Experience id → binding_kind=experience |
external_resource_id | Or this, if no experience_id | binding_kind=external_resource (session may exist before an Experience exists) |
external_customer_id | Optional | Must match the Experience when both are supplied |
ttl_seconds | Optional | Default 1800 (30 min), cap 3600 (60 min) |
binding_kind is not a request field.
Response includes token once, plus api_id, binding fields, origin, permitted_actions, status, timestamps.
Invalidation: expiry, explicit credential revoke (not rotate), Integration/entitlement/org becoming unusable, or Experience becoming unusable for an experience-bound session.
Parent page sequence
- Backend authenticates the hotel user itself.
- Backend resolves Experience and mints session.
- Dashboard creates iframe
src={ARCHWALK_APP_ORIGIN}/aw360/c/{api_id}(no token). - Wait for
creator:ready-for-initfromevent.origin === creatorOriginandevent.source === iframe.contentWindow. iframe.contentWindow.postMessage(initMessage, creatorOrigin)— exact target origin, never*.- Creator validates parent origin/source and token prefix
aw360_cs_{sessionApiId}.…, then calls ArchWalk withAuthorization: Bearer {token}andX-AW360-Parent-Origin. creator:ready— editing can proceed.
Opening /aw360/c/... top-level (not framed) does not complete the handshake.
Creator runtime APIs under /aw360/creator/... are for the ArchWalk iframe, not for your servers.
20. postMessage protocol
This is the Viewer/Creator embed contract implemented by the ArchWalk frontend. Backend OpenAPI does not define these message names; if the frontend protocol changes, this guide must be updated in that same change.
Envelope for all public messages:
{
"source": "archwalk360",
"version": 1,
"type": "<type>"
}
Ignore unknown types. Validate source, version, event.origin, and event.source. Always use an exact targetOrigin.
Viewer (public contract)
Parent → Viewer
| Type | Payload | When |
|---|---|---|
init | envelope only | Optional; establish parent trust if referrer is insufficient |
Viewer → Parent
| Type | Payload | When |
|---|---|---|
viewerOpened | panoramaCount, activePanoramaIndex | Viewer opened |
ready | panoramaCount, activePanoramaIndex | Ready to interact |
panoramaChanged | activePanoramaIndex, label | Active panorama changed |
interaction | kind: pointer | wheel | keyboard | First user interaction |
error | code | Load/fullscreen failures |
fullscreenChanged | fullscreen (boolean) | Fullscreen toggled |
resize | width, height | Size changed |
Viewer error codes: viewer_unavailable, viewer_load_failed, panorama_load_failed, fullscreen_unavailable.
Creator (public contract)
Creator → Parent: creator:ready-for-init, creator:ready, creator:saved (category: experience | panorama | panorama-order | starting-view), creator:dirty (hasUnpublishedChanges, publicationStatus, draftRevision), creator:published (publicId, liveUrl, revisionNumber, sourceDraftRevision), creator:unpublished, creator:error (category, message), creator:reauth-required.
Parent → Creator: creator:init with { "token": "<creator-session-token>" } (exactly those envelope keys plus token).
Internal Creator React events are not a partner contract.
Minimal parent snippet
<script>
const CREATOR_ORIGIN = "https://YOUR_ARCHWALK_APP_HOST";
const iframe = document.getElementById("creator");
const sessionToken = "<creator-session-token>"; // CREATOR_SESSION_TOKEN from your backend, never the API key
window.addEventListener("message", (event) => {
if (event.origin !== CREATOR_ORIGIN) return;
if (event.source !== iframe.contentWindow) return;
const data = event.data;
if (!data || data.source !== "archwalk360" || data.version !== 1) return;
if (data.type === "creator:ready-for-init") {
iframe.contentWindow.postMessage(
{ source: "archwalk360", version: 1, type: "creator:init", token: sessionToken },
CREATOR_ORIGIN
);
}
});
</script>