Pular para o conteúdo

Processamento e Monitoramento

Depois que os arquivos de entrada são enviados, a plataforma pode gerar saídas processadas (nuvens de pontos padronizadas, HLODs de malha, fotosferas e assim por diante). Este guia explica como listar opções de processamento, iniciar o processamento e consultar o progresso até que cada saída atinja um estado terminal.

Ele pressupõe que você tem um bundle com pelo menos uma sessão de envio concluída e possui os escopos read:bundle e write:bundle.


O processamento é do tipo dispare e esqueça: a API enfileira um trabalho de processamento e retorna imediatamente.

sequenceDiagram
  participant Client as Cliente
  participant RCAPI as RCAPI

  Client->>RCAPI: GET processing/options
  RCAPI-->>Client: options + metadata

  Client->>RCAPI: POST processing
  RCAPI-->>Client: accepted or typed error

  loop até que todos estejam terminais
    Client->>RCAPI: GET bundle/processings
    RCAPI-->>Client: processing records (status, progress)
  end
MétodoCaminhoEscopoFinalidade
GET/v1/bundles/{bundleId}/processing/optionsread:bundleListar os tipos de saída possíveis e seus metadados
POST/v1/bundles/{bundleId}/processingwrite:bundleIniciar o processamento das saídas solicitadas
GET/v1/bundles/{bundleId}/processingsread:bundleListar os registros de processamento do bundle para consultar o progresso
GET/v1/site/{siteId}/bundles/{bundleId}read:hierarchyObter o bundle com seus componentes de saída processados (links assinados)

Antes de iniciar, descubra quais saídas o bundle pode produzir e quanto cada uma custa.

GET {api_url}/v1/bundles/{bundleId}/processing/options?page=1&limit=20&sortBy=type&sortDir=ASC
Authorization: Bearer {access_token}
ParâmetroTipoDescrição
pagenumberÍndice de página baseado em 1 (padrão 1)
limitnumberTamanho da página (padrão 20, máximo 20)
sortBystringtype ou cost (padrão type)
sortDirstringASC ou DESC (padrão ASC)

A resposta é uma lista paginada ({ items, total }). Cada opção descreve um tipo de saída:

CampoSignificado
typeTipo de componente de saída a passar ao iniciar o processamento (por exemplo, StandardizedPointCloud, OgcPointCloudHlod)
hasProcessingtrue quando um processamento para essa saída já foi iniciado
costCusto de processamento em bytes para saídas pagas; 0 para saídas do nível gratuito

Exemplo:

{
"items": [
{
"type": "StandardizedPointCloud",
"hasProcessing": false,
"cost": 734003200
},
{
"type": "OgcPointCloudHlod",
"hasProcessing": false,
"cost": 734003200
}
],
"total": 2
}

Ignore as saídas em que hasProcessing é true, a menos que você pretenda reprocessar.

Passe a lista de tipos de componente de saída que você quer que o pipeline produza, mais um campo cost que confirma o custo total de processamento. O servidor soma os valores de cost da Etapa 1 para cada tipo em requestedComponents e rejeita a requisição quando sua confirmação não corresponde.

O processamento começa de forma assíncrona assim que o custo é aceito.

POST {api_url}/v1/bundles/{bundleId}/processing
Authorization: Bearer {access_token}
Content-Type: application/json
{
"requestedComponents": [
"StandardizedPointCloud",
"OgcPointCloudHlod"
],
"cost": 1468006400
}

No exemplo acima, cost é 734003200 + 734003200 da lista de opções da Etapa 1.

204 No Content: o processamento foi aceito e enfileirado.

Quando o processamento não pode ser iniciado, a API retorna 409 Conflict com um error tipado:

Valor de errorSignificado
ProcessingCostMismatchO cost enviado não corresponde ao total calculado para as saídas solicitadas
InsufficientProcessingCapacityO limite de processamento da organização seria excedido
NoInputDataFoundForProcessingNenhum arquivo de entrada finalizado está disponível no bundle
FailedToLaunchProcessingO envio ao pipeline não foi concluído por um motivo inesperado

Exemplo:

{
"error": "ProcessingCostMismatch"
}

A validação estrutural do lote enviado (tipos obrigatórios, extensões, dependências) é aplicada pelo pipeline de processamento após o início. Se sua sessão de envio foi concluída, mas violou o contrato de requirements, o processamento pode falhar mais tarde, mesmo que todos os arquivos tenham sido enviados com sucesso e a chamada de início tenha retornado 204.

Após um início bem-sucedido, consulte os registros de processamento do bundle até que cada um atinja um estado terminal.

GET {api_url}/v1/bundles/{bundleId}/processings
Authorization: Bearer {access_token}

A resposta é uma lista ({ items, total }) com todos os registros de processamento do bundle. Não há parâmetros de consulta; todos os registros são retornados em uma única chamada.

Cada item acompanha um trabalho de processamento:

CampoSignificado
idIdentificador do registro de processamento
statusStatus do pipeline (veja a tabela abaixo)
progressPercentual de conclusão (0100) enquanto ativo
createdAtQuando o trabalho foi criado
updatedAtQuando o trabalho mudou de estado pela última vez
launchedByIdId do usuário que iniciou o trabalho, ou null
knownErrorsFalhas estruturadas, cada uma com um errorCode e os errorFilepaths afetados (null quando não específico de arquivo)
StatusTerminal?Significado
PendingnãoNa fila, ainda não iniciado
ProcessingnãoO pipeline está em execução
RestartednãoO trabalho foi reiniciado e está em execução novamente
ReadysimSaída produzida com sucesso
FailedsimFalha não estruturada do pipeline
FailedToLaunchsimO trabalho nunca entrou no pipeline
KnownErrorsimErro estruturado de validação ou de formato

Consulte até que cada registro esteja em um estado terminal (Ready, Failed, FailedToLaunch ou KnownError).

Exemplo de resposta em andamento:

{
"items": [
{
"id": "3f2b1c4d-8e7a-4b2c-9d1e-0a1b3c4d4e6f",
"status": "Processing",
"progress": 42,
"createdAt": "2026-06-01T14:05:00Z",
"updatedAt": "2026-06-01T14:12:00Z",
"launchedById": "b1a2c3d4-5e6f-7a8b-9c0d-1e2f3a2b2c1d",
"knownErrors": []
},
{
"id": "9c0d1e2f-3a4b-5c6d-7e8f-9a0b2c3d3e4f",
"status": "Pending",
"progress": 0,
"createdAt": "2026-06-01T14:05:00Z",
"updatedAt": "2026-06-01T14:05:00Z",
"launchedById": "b1a2c3d4-5e6f-7a8b-9c0d-1e2f3a3b1c1d",
"knownErrors": []
}
],
"total": 2
}

Exemplo com um erro conhecido:

{
"items": [
{
"id": "3f2b1c4d-8e7a-4b2c-9d1e-0a2b3c4d4e5f",
"status": "KnownError",
"progress": 100,
"createdAt": "2026-06-01T14:05:00Z",
"updatedAt": "2026-06-01T14:48:00Z",
"launchedById": "b1a2c3d4-5e6f-7a8b-1c0d-2e6f3a4b5c6d",
"knownErrors": [
{
"errorCode": "MissingTrajectory",
"errorFilepaths": ["scan.las"]
}
]
}
],
"total": 1
}

A lista de processamentos não inclui o type de saída por registro. Para mapear as saídas concluídas de volta aos seus tipos de componente e links assinados, obtenha os componentes do bundle (consulte Recuperando saídas processadas).

  • Intervalo: de 1 a 5 minutos é um padrão razoável. O processamento pode levar de vários minutos a várias horas, dependendo do tamanho da entrada.
  • Limites de taxa: os endpoints de bundle compartilham um bucket de limite de taxa com vários outros endpoints. Evite consultas com intervalos menores que um minuto.

Assim que um registro de processamento atinge Ready, obtenha o bundle para conseguir seus componentes de saída e seus links de download assinados. Os detalhes do bundle ficam no endpoint de hierarquia:

GET {api_url}/v1/site/{siteId}/bundles/{bundleId}
Authorization: Bearer {access_token}

Este endpoint requer o escopo read:hierarchy e retorna o bundle com seu array components:

CampoSignificado
idId do bundle
nameNome do bundle
componentsUma entrada por componente disponível (entradas e saídas processadas)

Cada componente carrega:

CampoSignificado
idId do componente
typeTipo de componente, por exemplo StandardizedPointCloud, OgcPointCloudHlod
versionVersão do componente
signedLinkURL assinada para baixar o componente; nenhum cabeçalho de autenticação necessário
rootsCaminhos de ponto de entrada dentro do componente, quando aplicável

Exemplo:

{
"id": "a6f75b3c-f261-4b27-9a2a-9a6cc4178a13",
"name": "ZF capture 2026-06-01",
"components": [
{
"id": "5d6e7f8a-9b0c-1d2e-3f4a-1b3c7d4e8f0a",
"type": "StandardizedPointCloud",
"version": "1",
"signedLink": "https://cdn…/components/…?X-Amz-…"
}
]
}

Um projeto do RealityPlan expõe o mesmo bundle por GET /v1/reality-plan/{projectId}/bundles/{bundleId} (escopo read:twin).

import time
import requests
API_URL = "https://<your-regional-api-url>"
TOKEN = "<access_token>"
BUNDLE_ID = "<bundleId>"
headers = {"Authorization": f"Bearer {TOKEN}"}
base = f"{API_URL}/v1/bundles/{BUNDLE_ID}"
# 1. Discover outputs.
options = requests.get(
f"{base}/processing/options",
headers=headers,
params={"page": 1, "limit": 20},
).json()
options_by_type = {item["type"]: item for item in options["items"]}
to_process = [
item["type"]
for item in options["items"]
if not item["hasProcessing"]
]
total_cost = sum(options_by_type[t]["cost"] for t in to_process)
print(f"Launching: {to_process} (cost: {total_cost})")
# 2. Start processing.
response = requests.post(
f"{base}/processing",
headers=headers,
json={"requestedComponents": to_process, "cost": total_cost},
)
if response.status_code == 409:
raise RuntimeError(
f"Processing failed to start: {response.json().get('error')}"
)
response.raise_for_status() # expect 204
# 3. Poll until every job is terminal.
TERMINAL = {"Ready", "Failed", "FailedToLaunch", "KnownError"}
POLL_SECONDS = 15
TIMEOUT_SECONDS = 3600
deadline = time.time() + TIMEOUT_SECONDS
while time.time() < deadline:
listing = requests.get(
f"{base}/processings",
headers=headers,
).json()
processings = listing.get("items", [])
for p in processings:
print(f" {p['id']}: {p['status']} ({p['progress']}%)")
if processings and all(p["status"] in TERMINAL for p in processings):
break
time.sleep(POLL_SECONDS)
else:
raise TimeoutError("Processing did not finish within the timeout")

Para recuperar os arquivos de entrada brutos que foram enviados (para arquivamento, reprocessamento ou auditoria), consulte Baixando Arquivos de Entrada.