Viewer
Publish an immutable Experience revision and embed its public, read-only Viewer.
16. Publish and unpublish
Publishing snapshots the current draft into an immutable Published Revision. The Viewer reads only that current revision. Later draft edits do not change guests until the next successful publish.
Unpublish makes the public Viewer unavailable. The draft remains editable. public_id stays stable.
POST /api/v1/360/experiences/{experience_id}/publish
Scope experiences:publish. Body: { "expected_draft_revision": n }.
- New snapshot →
201 - Exact retry of the same still-current draft revision →
200(no new snapshot)
Publish requires at least one Panorama, exactly one is_starting: true, every Panorama health.status healthy, media still allowed by Integration policy, and a current ready external validation when source is external.
POST /api/v1/360/experiences/{experience_id}/unpublish
Scope experiences:publish. Repeating unpublish is safe.
Publication resource
experience_id, public_id, publication_status, embed_url, revision (revision_id, revision_number, source_draft_revision, published_at) — revision is null after unpublish.
embed_url is returned on publish/unpublish. GET /api/v1/360/experiences/{experience_id} includes publication_status and public_id but not embed_url. After Creator publish, re-read the Experience and build {ARCHWALK_APP_ORIGIN}/aw360/v/{public_id} when publication_status is published.
17. Viewer embed
Frontend route (not the Partner API):
{ARCHWALK_APP_ORIGIN}/aw360/v/{public_id}
embed_url from publish uses this form. No query parameters are required.
Recommended iframe (from the working embed contract):
<iframe
title="ArchWalk 360 Viewer"
src="https://YOUR_ARCHWALK_APP_HOST/aw360/v/PUBLIC_ID"
allow="fullscreen"
allowfullscreen
style="width:100%;height:80vh;border:0"
></iframe>
Do not add sandbox unless you have tested it; the product iframe contract does not require it.
Framing
ArchWalk sets Content-Security-Policy: frame-ancestors 'self' {allowed origins}. If the Integration has no allowed origins, only 'self' can frame — partner sites are blocked.
X-Frame-Options is not used. Document Referrer-Policy: no-referrer is set on the Viewer document.
Allowed origins vs API CORS
| Control | What it is |
|---|---|
Integration allowed_origins | Who may iframe Viewer/Creator (frame-ancestors + postMessage trust) |
| API CORS | ArchWalk-owned web apps calling the API from a browser |
They are not the same list. Partner API keys are server-to-server; do not call /api/v1/360 from a public website using the API key.
The Viewer document fetches /aw360/public/{public_id} (payload) and embed-policy. Those public routes are unauthenticated. Usage ingest POST /aw360/public/{public_id}/usage/open is rate-limited separately; you do not need to call it.
Public payload fields: public_id, name, branding, revision, starting_panorama_index, panoramas, navigation_links, and nullable floor_plan (media_url plus placements of panorama_id, x, y, heading_degrees). ETag version aw360-public-v3.
Direct top-level opening of the Viewer URL is supported for ArchWalk-hosted viewing; third-party iframe still requires allowed origins.
Optional parent → Viewer init message: send if document.referrer cannot establish trust (see postMessage).
18. Allowed origins
An origin is scheme://host[:port] only — no path, query, fragment, userinfo, or wildcard.
Valid:
https://www.acmestay.examplehttps://dashboard.acmestay.examplehttps://partner.example.com:8443http://localhost:3000andhttp://127.0.0.1:3000(loopback http only)
Invalid: https://www.acmestay.example/rooms, *, https://user:pass@host, null.
https default port 443 and http default port 80 are normalized away.
Allowed origins affect:
- Viewer CSP
frame-ancestors - Creator CSP
frame-ancestors - Creator session mint (
originmust be registered) - Viewer postMessage parent trust
For Creator, the document policy uses the Integration origin list; the handshake expects the configured parent origin (the first registered origin is used as the expected parent for the Creator document policy). Mint the session origin as the actual parent page origin.