Skip to main content
Documentation

Quickstart

Upload a panorama, trigger an Argus/VGGT reconstruction task, and poll for output.

This guide follows the domestic reconstruction task flow and adapts it to the overseas gateway. The public product name is Argus; endpoint paths still use vggt.

Create or select a Developer app

Open Apps and select the owning Team. Use an existing app, or have a Team owner choose Create trial app when there is capacity. Each Team may have up to three Developer apps; expired or disabled apps still count.

Creation saves an App request and completes it as soon as the app and AK binding are confirmed. The app uses the shared /open scope; there is no separate Argus capability application. Keep the SK and tokens on your backend. App availability, required inputs, resource access, and limits still apply.

The default 14-day trial is configured by the existing business process. Discuss production workflows or expected image volume in the Realsee Discord community, independently of request completion. Trial extensions require confirmation from the team.

Install the uploader

npm install @realsee/universal-uploader@0.1.1 cos-js-sdk-v5@1.8.3

Argus uses the uploader to send the panorama to the temporary storage location returned by the gateway.

Get an Argus gateway token

Exchange your Developer app credentials through the same overseas gateway token endpoint used by OpenAPI. Send its raw token value in the Authorization header for Argus requests; no separate product credential application is required.

export async function getArgusAccessToken() {
  const body = new URLSearchParams({
    app_key: process.env.REALSEE_APP_KEY!,
    app_secret: process.env.REALSEE_APP_SECRET!,
  })

  const response = await fetch('https://app-gateway.realsee.ai/auth/access_token', {
    method: 'POST',
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    body,
  })

  if (!response.ok) throw new Error(`Argus auth failed: ${response.status}`)
  const payload = await response.json() as {
    code: number
    status: string
    data: { access_token: string }
  }
  if (payload.code !== 0) throw new Error(`Argus auth failed: ${payload.status}`)
  return payload.data.access_token
}

Create an upload token

Send an empty input_image_id to start a new upload session. The gateway returns the stable identifier that must be reused for upload, trigger, and poll requests.

import type { UploadToken } from '@realsee/universal-uploader'

export async function createArgusUpload(accessToken: string) {
  const response = await fetch('https://app-gateway.realsee.ai/open/saas/v1/vggt/upload/token', {
    method: 'POST',
    headers: {
      authorization: `${accessToken}`,
      'content-type': 'application/json',
    },
    body: JSON.stringify({ input_image_id: '' }),
  })

  if (!response.ok) throw new Error(`Upload token failed: ${response.status}`)
  const payload = await response.json() as {
    code: number
    status: string
    data: {
      input_image_id: string
      upload_token: UploadToken
    }
  }
  if (payload.code !== 0) throw new Error(`Upload token failed: ${payload.status}`)

  return {
    inputImageId: payload.data.input_image_id,
    uploadToken: payload.data.upload_token,
  }
}

The response follows the gateway envelope used by other internal service calls: { code, status, data } with success code 0. Pass data.upload_token to the uploader, and retain data.input_image_id for the remaining requests.

Upload panoImage.jpg

The domestic walkthrough fixes the object key to panoImage.jpg. Keep that name unless your Realsee contact gives you a different contract.

Use Uploader.defaultUploadHandler for stable defaults, then override only when your file size requires different multipart settings.

import {
  Uploader,
  type ProviderAdaptor,
  type UploadToken,
} from '@realsee/universal-uploader'

const cosAdaptor: ProviderAdaptor = () => import('@realsee/universal-uploader/adaptors/cos')

export async function uploadArgusPanorama(file: File, uploadToken: UploadToken) {
  const uploader = new Uploader(cosAdaptor, {
    getToken: async () => uploadToken,
  })

  return uploader.upload('panoImage.jpg', file, {
    parallel: Uploader.defaultUploadHandler.parallel,
    partSize: Uploader.defaultUploadHandler.partSize,
    retry: Uploader.defaultUploadHandler.retry,
  })
}

Trigger reconstruction

After upload succeeds, trigger the Argus/VGGT task with the same input_image_id.

export async function triggerArgusTask(accessToken: string, inputImageId: string) {
  const response = await fetch('https://app-gateway.realsee.ai/open/saas/v1/vggt/trigger', {
    method: 'POST',
    headers: {
      authorization: `${accessToken}`,
      'content-type': 'application/json',
    },
    body: JSON.stringify({
      input_image_id: inputImageId,
      type: 'pano',
    }),
  })

  if (!response.ok) throw new Error(`Argus trigger failed: ${response.status}`)
  return response.json()
}

Poll until complete

Poll GET /open/saas/v1/vggt/poll with both type and input_image_id.

export async function pollArgusTask(accessToken: string, inputImageId: string) {
  const url = new URL('https://app-gateway.realsee.ai/open/saas/v1/vggt/poll')
  url.searchParams.set('type', 'pano')
  url.searchParams.set('input_image_id', inputImageId)

  for (let attempt = 0; attempt < 90; attempt += 1) {
    const response = await fetch(url, {
      headers: { authorization: `${accessToken}` },
    })

    if (!response.ok) throw new Error(`Argus poll failed: ${response.status}`)
    const payload = await response.json() as {
      code: number
      status: string
      data: {
        status: 'pending' | 'success' | 'failed'
        alg_task_id?: string
        result_url?: string
        failed_reason?: string
      }
    }
    if (payload.code !== 0) throw new Error(`Argus poll failed: ${payload.status}`)
    const data = payload.data

    if (data.status === 'success') return data
    if (data.status === 'failed') throw new Error('Argus task failed')

    await new Promise((resolve) => setTimeout(resolve, 2000))
  }

  throw new Error('Argus task timed out')
}

Successful responses can include result_url. The public schema guarantees only that this value is a URI; the media type and direct Five SDK compatibility depend on the provisioned integration.

Stable route summary

Use these stable docs URLs while building: