This guide adapts the Domestic panorama-to-VR tutorial to the separately provisioned overseas Pano-to-3D contract. It uploads a ZIP containing multiple panoramas, creates a Realsee project, and returns a browsable VR URL.
Two reconstruction contracts
The overseas gateway exposes two different capabilities:
- Argus/VGGT uses
/open/saas/v1/vggt/*for oneinput_image_idand returns reconstruction output throughresult_url. - Pano-to-3D uses
/open/v1/pano/*for a multi-panorama ZIP and returns a Realsee project plusvr_url.
This page follows the Pano-to-3D contract in open-pano-to-3d.openapi.json. Do not mix its task_code, ZIP location, or status fields into Argus/VGGT requests.
Before you start
- Submit an App request that explicitly describes the multi-panorama-to-VR workflow and expected monthly volume. Access to Argus/VGGT does not by itself document access to Pano-to-3D.
- Keep the approved app key, app secret, gateway access token, upload credentials, and task orchestration on your backend.
- Prepare equirectangular JPG panoramas and the ZIP manifest described below.
- Install the verified uploader and its COS adaptor peer:
npm install @realsee/universal-uploader@0.1.1 cos-js-sdk-v5@1.8.3All requests in this guide use the overseas production gateway:
https://app-gateway.realsee.aiZIP package format
Create one ZIP with manifest.json at its root and the panorama files under images/:
my-project.zip
├── manifest.json
└── images/
├── entrance.jpg
├── entrance-02.jpg
├── end-of-nave.jpg
├── presbyterium.jpg
└── high-altar.jpgExample manifest.json:
{
"version": "1.0",
"floor_map": {
"0": 1,
"1": 2
},
"project_name": "my-pano-project",
"scan_list": [
{ "id": "entrance", "floor": 0 },
{ "id": "entrance-02", "floor": 0 },
{ "id": "end-of-nave", "floor": 0 },
{ "id": "presbyterium", "floor": 1 },
{ "id": "high-altar", "floor": 1 }
]
}| Field | Type | Description |
|---|---|---|
version | string | Package version. Use "1.0" for this workflow. |
floor_map | object | Maps each scan_list[].floor key to the displayed floor number. |
project_name | string | Name recorded in the package. Use the same stable project name when submitting the task. |
scan_list | array | Ordered panorama records. |
scan_list[].id | string | Must match the corresponding JPG filename without its extension. |
scan_list[].floor | number | Floor key represented in floor_map. |
Every file under images/ must have a matching scan_list entry. For a single-floor project, one mapping such as { "0": 0 } is sufficient.
Workflow
Get access_token → get upload credentials → upload ZIP → submit task → poll task_code → read vr_urlGet an access token
Call POST /auth/access_token with application/x-www-form-urlencoded data:
app_key=<reviewed_app_key>&app_secret=<reviewed_app_secret>A successful response contains data.access_token and data.expire_at. Send the raw token in the Authorization header on the remaining requests; do not add a Bearer prefix.
Get upload credentials
Call GET /open/v1/pano/file/token with the gateway token:
GET /open/v1/pano/file/token
Authorization: <raw_gateway_access_token>Unlike the Argus/VGGT upload-token endpoint, this request has no input_image_id and returns the UploadToken fields directly under data.
Key response fields include:
| Field | Purpose |
|---|---|
tmpSecretId, tmpSecretKey, sessionToken | Temporary object-storage credentials. Never log them. |
bucket, region, host | Upload destination. |
prefix | Prefix that must be prepended to the uploaded ZIP key. |
ttl, expire | Credential lifetime in seconds. Here expire is a TTL, not the expire_at Unix timestamp returned by authentication. |
download_type, download_host | Determine which file-location field to send when submitting the task. |
custom_domain, custom_scheme | Provider endpoint values used by the upload adaptor. |
If the gateway returns code: -3, refresh the access token before requesting a new upload token.
Upload the ZIP
Create the uploader with the COS adaptor and pass the complete data object from the previous response as its UploadToken:
import {
Uploader,
type ProviderAdaptor,
type UploadToken,
} from '@realsee/universal-uploader'
const cosAdaptor: ProviderAdaptor = () => import('@realsee/universal-uploader/adaptors/cos')
export async function uploadPanoramaZip(zipFile: File, token: UploadToken) {
const uploader = new Uploader(cosAdaptor, {
getToken: async () => token,
})
const uploadKey = 'my-project.zip'
await uploader.upload(uploadKey, zipFile, {
parallel: Uploader.defaultUploadHandler.parallel,
partSize: Uploader.defaultUploadHandler.partSize,
retry: Uploader.defaultUploadHandler.retry,
})
return `${token.prefix}${uploadKey}`
}The returned string is the full object path used as private_cos_key. If download_host is non-empty and your upload adaptor returns a download_url, retain that URL for zip_cos_url instead.
Submit the processing task
Call POST /open/v1/pano/task/submit. project_name is required, and the runtime requires one ZIP location:
- Use
private_cos_keywhendownload_hostis empty, which represents the private-bucketpresignflow. - Use
zip_cos_urlwhen the upload result provides a downloadable URL.
Private-bucket example:
{
"project_name": "my-pano-project",
"private_cos_key": "vrfile/release/open_task_original/T-XXXXXXXXXX/pano/1700000000/my-project.zip"
}Successful data contains both identifiers:
type PanoTaskSubmission = {
project_id: string
task_code: string
}Retain task_code for status polling. It is not interchangeable with the Argus/VGGT input_image_id or alg_task_id fields.
Poll for completion
Call GET /open/v1/pano/task/status with the returned task code:
GET /open/v1/pano/task/status?task_code=<task_code>
Authorization: <raw_gateway_access_token>The response data follows this schema:
type PanoTaskStatus = {
project_id: string
status: 'pending' | 'processing' | 'success' | 'failed'
vr_url: string
}Continue polling while the status is pending or processing. On success, vr_url contains the complete browsable Realsee URL. Stop and surface a retry or support path on failed.
The access token can expire during a long-running task. If the envelope returns code: -3 and status: "access_token expired", refresh the token and continue polling with the same task_code.
Response envelope
Pano-to-3D responses use the gateway envelope:
| Field | Description |
|---|---|
request_id, trace_id | Identifiers to retain in server-side diagnostics. |
business_code | String business result or error code. |
code | 0 for success, -1 for a business failure, and -3 for an expired access token. |
status | Success or error description. |
data | Endpoint-specific data; it can be null on failure. |
cost | Server processing time in milliseconds. |
Do not expose the app secret, access token, temporary storage credentials, object path, or raw gateway diagnostics in browser logs or analytics.
For the single-image Argus/VGGT workflow, use the Argus Quickstart and Argus API Reference instead.
