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.
Como funciona
Seção intitulada “Como funciona”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
Endpoints
Seção intitulada “Endpoints”| Método | Caminho | Escopo | Finalidade |
|---|---|---|---|
GET | /v1/bundles/{bundleId}/processing/options | read:bundle | Listar os tipos de saída possíveis e seus metadados |
POST | /v1/bundles/{bundleId}/processing | write:bundle | Iniciar o processamento das saídas solicitadas |
GET | /v1/bundles/{bundleId}/processings | read:bundle | Listar os registros de processamento do bundle para consultar o progresso |
GET | /v1/site/{siteId}/bundles/{bundleId} | read:hierarchy | Obter o bundle com seus componentes de saída processados (links assinados) |
Etapa 1: listar opções de processamento
Seção intitulada “Etapa 1: listar opções de processamento”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=ASCAuthorization: Bearer {access_token}Parâmetros de consulta
Seção intitulada “Parâmetros de consulta”| Parâmetro | Tipo | Descrição |
|---|---|---|
page | number | Índice de página baseado em 1 (padrão 1) |
limit | number | Tamanho da página (padrão 20, máximo 20) |
sortBy | string | type ou cost (padrão type) |
sortDir | string | ASC ou DESC (padrão ASC) |
A resposta é uma lista paginada ({ items, total }). Cada opção descreve um tipo de saída:
| Campo | Significado |
|---|---|
type | Tipo de componente de saída a passar ao iniciar o processamento (por exemplo, StandardizedPointCloud, OgcPointCloudHlod) |
hasProcessing | true quando um processamento para essa saída já foi iniciado |
cost | Custo 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.
Etapa 2: iniciar o processamento
Seção intitulada “Etapa 2: iniciar o processamento”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}/processingAuthorization: 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.
Resposta de sucesso
Seção intitulada “Resposta de sucesso”204 No Content: o processamento foi aceito e enfileirado.
Resposta de erro
Seção intitulada “Resposta de erro”Quando o processamento não pode ser iniciado, a API retorna 409 Conflict com um error tipado:
Valor de error | Significado |
|---|---|
ProcessingCostMismatch | O cost enviado não corresponde ao total calculado para as saídas solicitadas |
InsufficientProcessingCapacity | O limite de processamento da organização seria excedido |
NoInputDataFoundForProcessing | Nenhum arquivo de entrada finalizado está disponível no bundle |
FailedToLaunchProcessing | O 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.
Etapa 3: consultar o progresso
Seção intitulada “Etapa 3: consultar o progresso”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}/processingsAuthorization: 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:
| Campo | Significado |
|---|---|
id | Identificador do registro de processamento |
status | Status do pipeline (veja a tabela abaixo) |
progress | Percentual de conclusão (0–100) enquanto ativo |
createdAt | Quando o trabalho foi criado |
updatedAt | Quando o trabalho mudou de estado pela última vez |
launchedById | Id do usuário que iniciou o trabalho, ou null |
knownErrors | Falhas estruturadas, cada uma com um errorCode e os errorFilepaths afetados (null quando não específico de arquivo) |
Estados de processamento
Seção intitulada “Estados de processamento”| Status | Terminal? | Significado |
|---|---|---|
Pending | não | Na fila, ainda não iniciado |
Processing | não | O pipeline está em execução |
Restarted | não | O trabalho foi reiniciado e está em execução novamente |
Ready | sim | Saída produzida com sucesso |
Failed | sim | Falha não estruturada do pipeline |
FailedToLaunch | sim | O trabalho nunca entrou no pipeline |
KnownError | sim | Erro 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).
Orientações de consulta
Seção intitulada “Orientações de consulta”- 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.
Recuperando saídas processadas
Seção intitulada “Recuperando saídas processadas”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:
| Campo | Significado |
|---|---|
id | Id do bundle |
name | Nome do bundle |
components | Uma entrada por componente disponível (entradas e saídas processadas) |
Cada componente carrega:
| Campo | Significado |
|---|---|
id | Id do componente |
type | Tipo de componente, por exemplo StandardizedPointCloud, OgcPointCloudHlod |
version | Versão do componente |
signedLink | URL assinada para baixar o componente; nenhum cabeçalho de autenticação necessário |
roots | Caminhos 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).
Exemplo completo
Seção intitulada “Exemplo completo”import timeimport 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 = 15TIMEOUT_SECONDS = 3600deadline = 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")Próxima etapa
Seção intitulada “Próxima etapa”Para recuperar os arquivos de entrada brutos que foram enviados (para arquivamento, reprocessamento ou auditoria), consulte Baixando Arquivos de Entrada.