Skip to main content
Documentation

End-to-End Reconstruction Task

Create an Argus reconstruction task from image upload through final 3D-space output.

This tutorial walks you through creating your first 3D reconstruction task, from uploading an image to obtaining the final 3D output. Keep gateway access tokens and task orchestration on your backend. Return temporary upload credentials only to the authenticated client that is performing the upload, and do not log them.

Step 1: Install dependencies

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

Step 2: Request upload credentials

Send an empty input_image_id to create an upload session and request temporary credentials from the overseas Argus gateway. This request must use POST /open/saas/v1/vggt/upload/token and the Argus access token returned by /auth/access_token. Reuse the returned input_image_id for every later step.

The gateway wraps successful data in { code, status, data }, so read upload_token and input_image_id from data.

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

const ARGUS_GATEWAY = 'https://app-gateway.realsee.ai'

type ArgusEnvelope<T> = {
  code: number
  status: string
  data: T
}

async function readArgusData<T>(response: Response): Promise<T> {
  if (!response.ok) throw new Error(`Argus request failed: ${response.status}`)

  const payload = await response.json() as ArgusEnvelope<T>
  if (payload.code !== 0) throw new Error(`Argus request failed: ${payload.status}`)
  return payload.data
}

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

  const data = await readArgusData<{
    upload_token: UploadToken
    input_image_id: string
  }>(response)

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

Step 3: Initialize the upload tool

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

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

export function createArgusUploader(uploadToken: UploadToken) {
  return new Uploader(cosAdaptor, {
    getToken: async () => uploadToken,
  })
}

Step 4: Upload the image

Configuration parameters

  • key: string — object name; use the required fixed name panoImage.jpg.
  • file — panorama content as a File or Blob.

Add the image-upload method:

export async function uploadArgusPanorama(file: File, uploadToken: UploadToken) {
  const uploader = createArgusUploader(uploadToken)

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

Step 5: Trigger the VGGT depth task

After the upload succeeds, trigger reconstruction with the same input_image_id.

  • Endpoint: POST /open/saas/v1/vggt/trigger
  • Example parameters:
{
  "input_image_id": "2aa48574-86a7-41ae-9643-xxxx",
  "type": "pano"
}

Add the task-creation method:

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

  return readArgusData<Record<string, unknown>>(response)
}

Step 6: Poll until the task completes

Poll the overseas gateway with both type=pano and the same input_image_id.

  • Endpoint: GET /open/saas/v1/vggt/poll?type=pano&input_image_id=id
  • Logic:
    • Periodically query the task status (pendingsuccess or failed)
    • On success, return the output metadata documented by the provisioned integration

Add the task-status polling method:

type ArgusTaskStatus = {
  status: 'pending' | 'success' | 'failed'
  alg_task_id?: string
  result_url?: string
  failed_reason?: string
}

export async function pollArgusTask(accessToken: string, inputImageId: string) {
  const url = new URL(`${ARGUS_GATEWAY}/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 },
    })
    const data = await readArgusData<ArgusTaskStatus>(response)

    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')
}

See the Argus API Reference for the complete request and response contract.