Skip to content
AW
ArchWalk 360/Developer Docs

GET STARTED

  • Overview
  • Quickstart
  • Partner integration

GUIDES

  • Embedded Creator
  • Media
  • Capture guide
  • Viewer

REFERENCE

  • Authentication
  • API Reference
  • Errors & troubleshooting

API Reference

Detailed Experience and Panorama resources, retry behavior, and Partner API routes.

11. Experience API

Auth: Authorization: Bearer API key. Tenant is taken from the credential. No org id in the path.

Optimistic concurrency: mutating routes take expected_draft_revision (except archive/restore/delete).

POST /api/v1/360/experiences

Scopeexperiences:write
PurposeCreate or resolve by external identity
Bodyname (string), external_resource_id (string), external_customer_id (optional)
Success201 created or 200 existing PartnerExperienceResource

GET /api/v1/360/experiences

Scopeexperiences:read
Querylifecycle_status (active | archived), publication_status (unpublished | published), external_resource_id, external_customer_id, cursor, limit (1–100, default 50)
Success{ "items": [...], "next_cursor": string | null }

Deletion-requested Experiences are omitted from list/get.

GET /api/v1/360/experiences/{experience_id}

Scope experiences:read. 404 if missing or pending deletion.

PATCH /api/v1/360/experiences/{experience_id}

Scope experiences:write. Body: expected_draft_revision, name.

POST /api/v1/360/experiences/{experience_id}/archive

Scope experiences:write. Sets lifecycle archived. Cannot publish while archived.

POST /api/v1/360/experiences/{experience_id}/restore

Scope experiences:write. Returns lifecycle active.

DELETE /api/v1/360/experiences/{experience_id}

Scope experiences:write. Status 202. Requests deletion; the resource becomes 404 for normal reads while the external identity stays reserved.

Experience resource fields

experience_id, public_id, name, external_customer_id, external_resource_id, lifecycle_status, publication_status, draft_revision, created_at, updated_at, archived_at, deletion_requested_at

public_id is the stable Viewer identity. It does not change when you republish.



12. Panorama API

Draft Panoramas only. Published Viewer content is a snapshot, not these rows.

There is no Partner reorder-all endpoint. Set sort_order on create/patch. Creator has its own order API for the iframe editor.

GET /api/v1/360/experiences/{experience_id}/panoramas

Scope panoramas:read. { "items": [...], "draft_revision": n }

POST /api/v1/360/experiences/{experience_id}/panoramas

Scope panoramas:write. Status 201.

Body:

FieldNotes
expected_draft_revisionRequired
labelRequired
sort_orderOptional int
initial_yawRadians, default 0, range ±2π
initial_pitchRadians, default 0, range ±π/2
initial_fovDegrees, default 75, must satisfy 0 < fov < 180
is_startingDefault false. Publish requires exactly one starting Panorama.
mediaDiscriminated: { "type": "managed", "upload_id" } or { "type": "external", "validation_id" }

GET /api/v1/360/experiences/{experience_id}/panoramas/{panorama_id}

Scope panoramas:read.

PATCH /api/v1/360/experiences/{experience_id}/panoramas/{panorama_id}

Scope panoramas:write. Always send expected_draft_revision. Other fields optional. Omitted fields are left unchanged.

DELETE /api/v1/360/experiences/{experience_id}/panoramas/{panorama_id}?expected_draft_revision={n}

Scope panoramas:write. Query param expected_draft_revision is required. Response: { "panorama_id", "deleted": true, "draft_revision" }.

Panorama resource fields

panorama_id, experience_id, label, sort_order, source_type (managed | external), managed_upload_id, external_validation_id, external_url, camera fields, is_starting, health (status, checked_at, error_code, next_check_at), timestamps, draft_revision.

Navigation links

Navigation links are directed connections between two Panoramas in the same Experience. Each link has its own opaque navigation_link_id; multiple links may share the same source and target. Reverse links are not created automatically.

Read routes require panoramas:read. Create, update, and delete routes require panoramas:write and the current expected_draft_revision.

Create body: expected_draft_revision, source_panorama_id, target_panorama_id, yaw, pitch.

Patch body: expected_draft_revision plus one or more of target_panorama_id, yaw, or pitch. Delete sends expected_draft_revision as a query parameter.

Coordinates are spherical: yaw and pitch identify the point in the source Panorama. Publishing snapshots the current navigation graph for the Viewer.

Optional floor plan

An Experience may have one optional floor-plan image. Existing Panoramas may optionally have normalized x/y positions on that image (0..1, origin top-left of the displayed image). Optional heading_degrees is clockwise from plan-up, normalized to [0, 360). Partial placement is valid. Floor plan placement is not required to publish.

This is not another content hierarchy and does not create navigation links. Marker identity is the existing panorama_id.

Upload lifecycle (same write-once PUT as panoramas, JPEG/PNG/WebP, no 2:1 panorama check; max 8192×8192 and 32 megapixels):

  1. POST /api/v1/360/experiences/{experience_id}/floor-plan-uploads (panoramas:upload)
  2. Client PUT to upload_url
  3. POST .../floor-plan-uploads/{upload_id}/complete
  4. PUT /api/v1/360/experiences/{experience_id}/floor-plan with { "expected_draft_revision", "upload_id" } (panoramas:write)

GET .../floor-plan returns { "floor_plan": null | { media_url, placements }, "draft_revision" }.

PUT .../panoramas/{panorama_id}/floor-plan-position sets { x, y, heading_degrees }. Delete that path (query expected_draft_revision) clears that Panorama's placement.

Replacing the floor-plan image keeps existing placements. Removing the floor plan clears the image and all draft placements in one revision bump. Guests see the previous published plan until the next successful publish. The public payload includes nullable floor_plan (etag version aw360-public-v3).



22. Idempotency and retries

ActionRetry behavior
POST Experience create/resolveSafe. Same external identity → 200 existing row. Name is not overwritten.
POST publishSafe exact retry of the same current draft revision → 200, no new snapshot. Stale expected_draft_revision → 409.
POST unpublishSafe to repeat.
Credential revoke (settings)Safe to repeat.
Managed upload with client_request_idSafe if payload matches.
Complete ready uploadSafe.
PATCH / POST panoramasNot idempotent; uses draft revision. Retry after re-read.
DELETE ExperienceRequests deletion (202). Do not assume a second call is a no-op for every state.
POST Creator sessionNot idempotent — each call mints a new session.


27. Partner API route index

Path parameters use the FastAPI names (experience_api_id, and so on). Those values are the opaque ids returned in JSON as experience_id, panorama_id, upload_id, and validation_id.

MethodPathScope
POST/api/v1/360/experiencesexperiences:write
GET/api/v1/360/experiencesexperiences:read
GET/api/v1/360/experiences/{experience_api_id}experiences:read
PATCH/api/v1/360/experiences/{experience_api_id}experiences:write
POST/api/v1/360/experiences/{experience_api_id}/archiveexperiences:write
POST/api/v1/360/experiences/{experience_api_id}/restoreexperiences:write
DELETE/api/v1/360/experiences/{experience_api_id}experiences:write
GET/api/v1/360/experiences/{experience_api_id}/panoramaspanoramas:read
POST/api/v1/360/experiences/{experience_api_id}/panoramaspanoramas:write
GET/api/v1/360/experiences/{experience_api_id}/panoramas/{panorama_api_id}panoramas:read
PATCH/api/v1/360/experiences/{experience_api_id}/panoramas/{panorama_api_id}panoramas:write
DELETE/api/v1/360/experiences/{experience_api_id}/panoramas/{panorama_api_id}panoramas:write
GET/api/v1/360/experiences/{experience_api_id}/navigation-linkspanoramas:read
POST/api/v1/360/experiences/{experience_api_id}/navigation-linkspanoramas:write
GET/api/v1/360/experiences/{experience_api_id}/navigation-links/{navigation_link_id}panoramas:read
PATCH/api/v1/360/experiences/{experience_api_id}/navigation-links/{navigation_link_id}panoramas:write
DELETE/api/v1/360/experiences/{experience_api_id}/navigation-links/{navigation_link_id}panoramas:write
POST/api/v1/360/experiences/{experience_api_id}/publishexperiences:publish
POST/api/v1/360/experiences/{experience_api_id}/unpublishexperiences:publish
POST/api/v1/360/experiences/{experience_api_id}/panorama-uploadspanoramas:upload
POST/api/v1/360/experiences/{experience_api_id}/panorama-uploads/{upload_api_id}/completepanoramas:upload
GET/api/v1/360/experiences/{experience_api_id}/panorama-uploads/{upload_api_id}panoramas:upload
DELETE/api/v1/360/experiences/{experience_api_id}/panorama-uploads/{upload_api_id}panoramas:upload
POST/api/v1/360/experiences/{experience_api_id}/floor-plan-uploadspanoramas:upload
POST/api/v1/360/experiences/{experience_api_id}/floor-plan-uploads/{upload_api_id}/completepanoramas:upload
GET/api/v1/360/experiences/{experience_api_id}/floor-plan-uploads/{upload_api_id}panoramas:upload
DELETE/api/v1/360/experiences/{experience_api_id}/floor-plan-uploads/{upload_api_id}panoramas:upload
GET/api/v1/360/experiences/{experience_api_id}/floor-planpanoramas:read
PUT/api/v1/360/experiences/{experience_api_id}/floor-planpanoramas:write
DELETE/api/v1/360/experiences/{experience_api_id}/floor-planpanoramas:write
PUT/api/v1/360/experiences/{experience_api_id}/panoramas/{panorama_api_id}/floor-plan-positionpanoramas:write
DELETE/api/v1/360/experiences/{experience_api_id}/panoramas/{panorama_api_id}/floor-plan-positionpanoramas:write
POST/api/v1/360/experiences/{experience_api_id}/external-media-validationspanoramas:write
GET/api/v1/360/experiences/{experience_api_id}/external-media-validations/{validation_api_id}panoramas:write
GET/api/v1/360/external-media-validations/{validation_api_id}/browser-checkchallenge token
POST/api/v1/360/external-media-validations/{validation_api_id}/browser-checkchallenge token
POST/api/v1/360/creator-sessionscreator_sessions:issue

Public (no Partner API key):

MethodPath
GET/aw360/public/{public_id}
GET/aw360/public/{public_id}/embed-policy
POST/aw360/public/{public_id}/usage/open

Frontend documents:

SurfacePath
Viewer/aw360/v/{public_id}
Creator/aw360/c/{session_api_id}
External media check/aw360/media-check

Hosted Organization settings (/archwalk-360/integrations, Clerk) and Manager (/archwalk-360/experiences) are not the Partner API.

OpenAPI at {ARCHWALK_API_BASE}/openapi.json includes the whole ArchWalk backend. Filter paths that start with /api/v1/360 (and /aw360/public if needed). Do not treat architect/admin routes as partner contract.



28. Reference integration

A Bookme-style partner host lives in the ArchWalk frontend repository at examples/aw360-bookme-reference/. It is executable documentation, not a production ArchWalk surface.

It demonstrates:

  • Partner marketplace authentication (mocked) with no ArchWalk / Clerk login for the seller
  • Server-side AW360_REFERENCE_API_KEY (aw360_sk_…) that never reaches the browser
  • POST /api/v1/360/experiences create-or-resolve by external_resource_id
  • POST /api/v1/360/creator-sessions mint, iframe /aw360/c/{api_id}, exact-origin creator:ready-for-init / creator:init
  • Public listing iframe /aw360/v/{public_id} after publication
  • Hybrid plugin import at /seller/plugin (200 mock physical rooms → 8 visual variants → 8 Experiences) and guest reuse at /listing/plugin?room=101

See that folder's README.md for environment variables, bootstrap (scripts/aw360_reference_bootstrap.py in the backend repository), and how to run the seller, listing, and plugin pages.


PreviousAuthentication
NextErrors & troubleshooting