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

Media

Choose whether ArchWalk or your own CDN hosts Panorama files.

Managed media

ArchWalk stores panorama bytes.

External media

Your organization keeps media on its CDN.

Need to create the source images first? See the Capture guide.

9. Quickstart B — external media

Same as Quickstart A, replacing the upload with validation.

Responsibility: ArchWalk does not host or control this file. You own HTTPS, CORS, durability, and a stable URL. Short-lived signed URLs (AWS SigV4, GCS, Azure SAS, CloudFront signed query params) are rejected.

bash
VALIDATION_JSON=$(curl -sS -X POST "$ARCHWALK_API_BASE/api/v1/360/experiences/$EXPERIENCE_ID/external-media-validations" \
  -H "Authorization: Bearer $AW360_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://cdn.acmestay.example/panoramas/room_12345.jpg"}')
export VALIDATION_ID=$(echo "$VALIDATION_JSON" | jq -r .validation_id)
export BROWSER_CHECK_URL=$(echo "$VALIDATION_JSON" | jq -r .browser_check_url)

The create response includes challenge_token and browser_check_url once (BROWSER_CHECK_URL). Open that URL (ArchWalk Viewer attestation). When GET validation shows status: "ready" and expired: false, attach using $VALIDATION_ID and the current $DRAFT_REVISION:

bash
PANORAMA_JSON=$(curl -sS -X POST "$ARCHWALK_API_BASE/api/v1/360/experiences/$EXPERIENCE_ID/panoramas" \
  -H "Authorization: Bearer $AW360_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"expected_draft_revision\": $DRAFT_REVISION,
    \"label\": \"Living room\",
    \"is_starting\": true,
    \"media\": { \"type\": \"external\", \"validation_id\": \"$VALIDATION_ID\" }
  }")
export DRAFT_REVISION=$(echo "$PANORAMA_JSON" | jq -r .draft_revision)

Then publish as in Quickstart A (step 6), using the updated $DRAFT_REVISION.


13. Managed upload flow

Routes (all scope panoramas:upload):

  1. POST /api/v1/360/experiences/{experience_id}/panorama-uploads
  2. Client PUT to upload_url
  3. POST .../panorama-uploads/{upload_id}/complete
  4. GET .../panorama-uploads/{upload_id}
  5. DELETE .../panorama-uploads/{upload_id} (discard)

Initiate body: content_type, declared_size_bytes (> 0), optional client_request_id (1–64 chars).

Initiate response extra fields: upload_url, method (PUT), headers (include Content-Type and If-None-Match: *).

Treat upload_url as a secret: short-lived, do not log it.

Accepted types and ceilings (operational defaults, not an SLA)

ConstraintDefault
MIMEimage/jpeg, image/png, image/webp
Declared / verified size150 MiB
Minimum width2048 px
Maximum width16384 px
Maximum pixels16384 × 8192
Aspect~2:1 equirectangular (about 2% tolerance)
Presigned PUT TTL15 minutes
Ready but unattached TTL24 hours

Do not alter returned object keys. ArchWalk chooses storage keys.

client_request_id retries: same Experience + same id + same content_type/size returns the existing upload. A different payload with the same id is rejected.

Completing an already-ready upload is safe (returns the ready resource).



14. External media flow

Warning: ArchWalk does not own partner-hosted files. If the object disappears, CORS breaks, or the URL becomes a signed/temporary link, the Viewer can fail. External media counts as zero managed-storage bytes.

Partner routes (scope panoramas:write)

  • POST /api/v1/360/experiences/{experience_id}/external-media-validations
  • GET /api/v1/360/experiences/{experience_id}/external-media-validations/{validation_id}

Body: { "url": "https://..." } (max 2048 characters).

Create returns the validation resource plus once: challenge_token, browser_check_url.

GET never returns the challenge again.

Browser attestation (not Partner-key auth)

  • GET /api/v1/360/external-media-validations/{validation_id}/browser-check
  • POST /api/v1/360/external-media-validations/{validation_id}/browser-check

These use Authorization: Bearer with the challenge token, not the API key. The hosted browser_check_url already encodes that flow (/aw360/media-check#<challenge>). POST body: { "outcome": "rendered" } or { "outcome": "failed" }.

Statuses: server probe first (server_validated), then browser ready or failed. expired is derived from ready_expires_at (default ready lifetime 24 hours). Attach only a non-expired ready validation.

URL rules partners must satisfy

  • https only (no http upgrade/downgrade)
  • Default allowed port 443
  • Public global addresses only (no localhost, private, link-local, metadata, CGNAT, etc.)
  • Redirects revalidated; https→http rejected; redirect loop/count limited
  • No userinfo in the URL
  • Known cloud signed-URL query patterns rejected
  • Uncompressed responses (Content-Encoding identity)
  • Trustworthy Content-Length / Content-Range size
  • JPEG/PNG/WebP; ~2:1; same dimension ceilings as managed uploads
  • CORS: Access-Control-Allow-Origin must be * or ArchWalk's validation origin

Anonymous probe: ArchWalk does not forward your cookies or Authorization to the media host.



15. External media troubleshooting

SymptomLikely causeFix
archwalk_360_external_url_invalidNot a clean https URLUse https, no userinfo/path tricks, port 443
archwalk_360_external_url_appears_temporarySigned/SAS/CloudFront query paramsPublish a stable public CDN URL
archwalk_360_external_url_target_not_allowedPrivate/special IP after DNSHost on public CDN
archwalk_360_external_unsafe_redirectBad/loop/http redirectRedirect only to allowed https URLs
archwalk_360_external_cors_not_allowedMissing/wrong ACAOAllow ArchWalk origin or *
archwalk_360_external_content_type_mismatchWrong Content-TypeServe image/jpeg, image/png, or image/webp
archwalk_360_external_size_unknown / too_largeMissing size or over capSend valid length/range; stay under size ceiling
archwalk_360_external_host_timeoutSlow or Slowloris originServe promptly; avoid header/body drip
Browser check failsCORS, mixed content, decode failureMatch server CORS; use a real equirectangular image
Health later unhealthyFile moved or CORS changedKeep the final_url durable; re-validate and re-attach
Validation expired: trueReady TTL elapsedRun a new validation before attach/publish

PreviousEmbedded Creator
NextCapture guide