Tours virtuais

API de tours virtuais

Transforma fotos 360° num tour virtual alojado e pronto a partilhar com uma única chamada. A IA dá nome às divisões e coloca os pontos de navegação entre elas; recebes um URL público do tour e um iframe para incorporar.

Envia as tuas fotos 360° e recebe um tour virtual alojado que podes partilhar ou incorporar. A Pedra importa as fotos equirretangulares, a IA dá nome a cada divisão e coloca os pontos de navegação de porta a porta, e a resposta devolve um tourUrl público e um iframe embedCode pronto a colar. Sem visualizador para alojar e sem pontos de navegação para colocar à mão.

O que obténs com uma única chamada:

  • Uma página de tour alojada — um tourUrl público e um iframe embedCode para qualquer página de anúncio, CRM ou portal. Funciona no telemóvel (com o giroscópio) e no computador.
  • Nomes de divisões com IA — as divisões a que não dás nome recebem nome automaticamente (Entrada, Cozinha, Quarto 1…) no idioma do tour, grátis. Os nomes que envias nunca são alterados.
  • Navegação com IA — a Pedra encontra cada porta na foto e coloca os pontos de navegação entre divisões, nos dois sentidos.
  • Controlo total depois — muda o nome, reordena, remove ou adiciona divisões e substitui os pontos de navegação pelos teus, tudo pela API.
  • Funciona a partir do chat — os mesmos endpoints são ferramentas do servidor MCP da Pedra, por isso o ChatGPT e o Claude podem criar um tour a partir de uma conversa.

Como funciona

Criar um tour é assíncrono: a chamada de criação devolve um tourId de imediato e o tour é construído em segundo plano (cerca de 10 segundos por divisão ligada).

  1. Cria — POST /api/create_virtual_tour com as tuas fotos 360° pela ordem do percurso. Recebes de imediato o tourId, o tourUrl e o embedCode, com status: "processing".
  2. Consulta — chama POST /api/get_virtual_tour a cada poucos segundos até status ser "ready" (ou "failed", com o motivo em error).
  3. Partilha — envia o tourUrl ou cola o embedCode na página do anúncio. O URL mantém-se quando editas o tour mais tarde.
# 1. Create the tour (returns immediately with "status": "processing")
curl -X POST https://app.pedra.ai/api/create_virtual_tour \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "YOUR_API_KEY",
    "name": "Calle Mayor 12",
    "scenes": [
      { "imageUrl": "https://example.com/360/entrance.jpg", "name": "Entrance" },
      { "imageUrl": "https://example.com/360/living-room.jpg" },
      { "imageUrl": "https://example.com/360/kitchen.jpg" },
      { "imageUrl": "https://example.com/360/bedroom.jpg" }
    ]
  }'

# 2. Poll until "status" is "ready" (or "failed")
curl -X POST https://app.pedra.ai/api/get_virtual_tour \
  -H "Content-Type: application/json" \
  -d '{ "apiKey": "YOUR_API_KEY", "tourId": "TOUR_ID" }'

Modos de ligação e créditos

O parâmetro linking decide como os pontos de navegação são colocados. Dar nome às divisões é sempre grátis. Os créditos só são cobrados quando a ligação começa, e uma construção que falha nunca é cobrada.

Modo
O que faz
Custo
sequential
Predefinido. Envia as divisões pela ordem do percurso; cada uma é ligada à seguinte, nos dois sentidos.
máx(3, ⌈divisões ÷ 3⌉) créditos — 3 até 9 divisões, 4 para 12, 10 para 30
smart
A IA compara cada par de divisões e liga as que visivelmente comunicam — para quando não sabes a ordem do percurso. Mais lento; até 40 divisões.
5–160 créditos consoante o número de divisões (tabela abaixo)
none
Sem pontos de navegação. Coloca os teus depois com update_virtual_tour.
Grátis

Ligação smart consoante o número de divisões

Divisões
Créditos
1–6
5 créditos
7–10
12 créditos
11–15
25 créditos
16–20
50 créditos
21–25
70 créditos
26–30
100 créditos
31–35
130 créditos
36–40
160 créditos

add_virtual_tour_scenes custa o mesmo que a ligação sequential, contando apenas as divisões novas. get_virtual_tour, list_virtual_tours, update_virtual_tour, delete_virtual_tour e create_upload_link são grátis. Consulta o teu saldo com credits.

Criar um tour virtual

POST/api/create_virtual_tour

Importa as fotos 360° e depois dá nome e liga as divisões em segundo plano. Envia scenes pela ordem do percurso — a primeira é onde o tour abre. Sem propertyId, é criado um novo imóvel com o nome indicado em name. Para criar um tour com fotos que já estão num imóvel (por exemplo, carregadas através de um link de carregamento), envia apenas o propertyId e omite scenes: são usadas todas as fotos 360° do imóvel, pela ordem de carregamento. Cada imóvel tem um tour; se já tiver um, recebes 409 tour_exists com o respetivo tourId.

apiKeystringobrigatório
A tua chave API.
scenesarray
As fotos 360°, pela ordem do percurso (máx. 50). Obrigatório, exceto se enviares um propertyId cujas fotos 360° vão formar o tour.
imageUrlsarray
Atalho para scenes: uma lista simples de URLs de fotos 360°.
propertyIdstring
Cria o tour neste imóvel. Necessário se as cenas usarem imageId. Sem scenes, são usadas todas as fotos 360° do imóvel pela ordem de carregamento. Omite-o para criar um novo imóvel.
namestring
Título do tour, p. ex. a morada do anúncio. É também o nome do novo imóvel, se for criado.
linkingstring
Como são colocados os pontos de navegação — vê Modos de ligação e créditos.
Values: sequential smart none
Default: sequential
languagestring
Idioma da página do tour e dos nomes de divisões da IA. Os tours que não estão em inglês têm um URL do tipo /pt/virtual-tour/….
Values: en es fr de it pt
Default: en

Objeto scene

Cada cena é { imageUrl } ou { imageId }, com um name opcional. Uma string simples é tratada como imageUrl. Até 50 cenas por tour.

imageUrlstring
URL público (ou URI data:) de uma foto 360° equirretangular — 2:1, até 80 MB. Os links de partilha do Dropbox e do Google Drive funcionam.
imageIdstring
Uma foto 360° que já está no imóvel (de list_property_images com type "360"). Usa-o em vez de imageUrl.
namestring
Nome da divisão. Se o omitires, a IA dá nome à divisão.
curl -X POST https://app.pedra.ai/api/create_virtual_tour \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "YOUR_API_KEY",
    "name": "Calle Mayor 12",
    "linking": "sequential",
    "language": "en",
    "scenes": [
      { "imageUrl": "https://example.com/360/entrance.jpg", "name": "Entrance" },
      { "imageUrl": "https://example.com/360/living-room.jpg" },
      { "imageUrl": "https://example.com/360/kitchen.jpg" },
      { "imageUrl": "https://example.com/360/bedroom.jpg" }
    ]
  }'

Resposta

JSON
{
  "tourId": "1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "propertyId": "196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "name": "Calle Mayor 12",
  "status": "processing",
  "tourUrl": "https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "embedCode": "<iframe src=\"https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19\" title=\"Calle Mayor 12\" width=\"100%\" height=\"600\" style=\"border:0\" allow=\"fullscreen; gyroscope; accelerometer\" allowfullscreen loading=\"lazy\"></iframe>",
  "appUrl": "https://app.pedra.ai/?projectId=196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "shareable": true,
  "sceneCount": 4,
  "linkCount": 0,
  "coverImageUrl": null,
  "createdAt": "2026-09-30T15:22:52.028Z",
  "updatedAt": "2026-09-30T15:22:52.028Z",
  "progress": { "stage": "queued" },
  "scenes": [
    { "sceneId": "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21", "name": "Entrance", "source": "https://example.com/360/entrance.jpg" },
    { "sceneId": "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68", "name": null, "source": "https://example.com/360/living-room.jpg" },
    { "sceneId": "5b2e9c71-0d3a-4a8f-b6e4-9c1f7d2a5e30", "name": null, "source": "https://example.com/360/kitchen.jpg" },
    { "sceneId": "a8d4f0b2-6e1c-4d97-8f3a-2b5c9e7d1a46", "name": null, "source": "https://example.com/360/bedroom.jpg" }
  ],
  "linking": "sequential",
  "creditsCost": 3,
  "estimatedSeconds": 47,
  "message": "Building the tour. Poll get_virtual_tour with this tourId until status is \"ready\" (or \"failed\")."
}

Obter um tour virtual

POST/api/get_virtual_tour

Devolve o estado do tour e, quando está pronto, as suas cenas, ligações de navegação e definições de apresentação. É o endpoint a consultar depois de create_virtual_tour e add_virtual_tour_scenes.

apiKeystringobrigatório
A tua chave API.
tourIdstringobrigatório
O id do tour (de create_virtual_tour ou list_virtual_tours).
curl -X POST https://app.pedra.ai/api/get_virtual_tour \
  -H "Content-Type: application/json" \
  -d '{ "apiKey": "YOUR_API_KEY", "tourId": "TOUR_ID" }'

Estado

  • processing — em construção. progress.stage é queued, importing, naming ou linking, com done / total quando se aplica.
  • ready — publicado em tourUrl. Inclui scenes, links e settings.
  • failed — não foi cobrado nada. error explica o motivo e failedScenes lista cada foto que não foi possível usar (por exemplo, uma que não é 2:1). As fotos importadas ficam no imóvel, por isso podes substituir a errada e voltar a criar o tour por imageId.

Se uma chamada a add_virtual_tour_scenes falhar, o tour continua ready e inclui lastError e failedScenes. Numa conta do plano gratuito o tour é criado, mas o link público mostra uma página de upgrade: as respostas indicam shareable: false, com um shareableNote.

Resposta

JSON
{
  "tourId": "1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "propertyId": "196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "name": "Calle Mayor 12",
  "status": "ready",
  "tourUrl": "https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "embedCode": "<iframe src=\"https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19\" title=\"Calle Mayor 12\" width=\"100%\" height=\"600\" style=\"border:0\" allow=\"fullscreen; gyroscope; accelerometer\" allowfullscreen loading=\"lazy\"></iframe>",
  "appUrl": "https://app.pedra.ai/?projectId=196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "shareable": true,
  "sceneCount": 4,
  "linkCount": 6,
  "coverImageUrl": "https://img.pedra.ai/f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21",
  "createdAt": "2026-09-30T15:22:52.028Z",
  "updatedAt": "2026-09-30T15:23:41.310Z",
  "scenes": [
    { "sceneId": "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21", "name": "Entrance", "imageUrl": "https://img.pedra.ai/f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21" },
    { "sceneId": "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68", "name": "Living room", "imageUrl": "https://img.pedra.ai/cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68" },
    { "sceneId": "5b2e9c71-0d3a-4a8f-b6e4-9c1f7d2a5e30", "name": "Kitchen", "imageUrl": "https://img.pedra.ai/5b2e9c71-0d3a-4a8f-b6e4-9c1f7d2a5e30" },
    { "sceneId": "a8d4f0b2-6e1c-4d97-8f3a-2b5c9e7d1a46", "name": "Bedroom", "imageUrl": "https://img.pedra.ai/a8d4f0b2-6e1c-4d97-8f3a-2b5c9e7d1a46" }
  ],
  "links": [
    { "linkId": "ai-7c21", "fromSceneId": "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21", "toSceneId": "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68", "yaw": -18, "pitch": 0, "aiGenerated": true },
    { "linkId": "ai-7c22", "fromSceneId": "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68", "toSceneId": "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21", "yaw": 164, "pitch": 0, "aiGenerated": true }
  ],
  "settings": {
    "navigationStyle": "white",
    "navigationSize": "medium",
    "showLabels": false,
    "language": "en"
  }
}

Listar tours virtuais

POST/api/list_virtual_tours

Devolve os tours da conta, do mais recente para o mais antigo (até 100), com os mesmos campos de resumo que get_virtual_tour mas sem scenes, links nem settings. Os tours eliminados ficam de fora.

apiKeystringobrigatório
A tua chave API.
propertyIdstring
Devolve apenas o tour deste imóvel.
curl -X POST https://app.pedra.ai/api/list_virtual_tours \
  -H "Content-Type: application/json" \
  -d '{ "apiKey": "YOUR_API_KEY" }'

Resposta

JSON
{
  "tours": [
    {
      "tourId": "1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
      "propertyId": "196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
      "name": "Calle Mayor 12",
      "status": "ready",
      "tourUrl": "https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
      "embedCode": "<iframe …></iframe>",
      "appUrl": "https://app.pedra.ai/?projectId=196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
      "shareable": true,
      "sceneCount": 4,
      "linkCount": 6,
      "coverImageUrl": "https://img.pedra.ai/f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21",
      "createdAt": "2026-09-30T15:22:52.028Z",
      "updatedAt": "2026-09-30T15:23:41.310Z"
    }
  ]
}

Atualizar um tour virtual

POST/api/update_virtual_tour

Muda o nome do tour ou das suas divisões, reordena ou remove divisões, substitui os pontos de navegação e muda o seu aspeto. Grátis e imediato. A validação é tudo ou nada: se algum campo for inválido, nada muda. Devolve o tour completo, como get_virtual_tour, ou 409 tour_processing enquanto o tour ainda está a ser construído.

apiKeystringobrigatório
A tua chave API.
tourIdstringobrigatório
O id do tour (de create_virtual_tour ou list_virtual_tours).
namestring
Novo título do tour.
sceneNamesobject
Nomes das divisões por sceneId, p. ex. { "<sceneId>": "Cozinha" }.
sceneOrderarray
Cada sceneId exatamente uma vez, pela nova ordem. A primeira é onde o tour abre.
removeScenesarray
sceneIds a retirar do tour. As fotos ficam no imóvel e as ligações que as envolvem são removidas. Tem de ficar pelo menos uma cena.
linksarray
Substitui TODAS as ligações de navegação. Cada ligação vai num só sentido: { fromSceneId, toSceneId, yaw, pitch? }.
navigationStylestring
Cor dos pontos de navegação.
Values: white blue
navigationSizestring
Tamanho dos pontos de navegação.
Values: small medium large
showLabelsboolean
Mostrar sempre o nome da divisão de destino junto a cada ponto de navegação.
languagestring
Idioma da página do tour.
Values: en es fr de it pt

Objeto link

fromSceneIdstringobrigatório
A cena em que o ponto de navegação aparece.
toSceneIdstringobrigatório
A cena para onde leva.
yawnumberobrigatório
Ângulo horizontal na foto de fromScene, de −180 a 180. 0 é o centro da foto; negativo é à esquerda.
pitchnumber
Ângulo vertical, de −90 a 90. 0 é o horizonte.
Default: 0

Para ajustar as ligações da IA em vez de começar do zero, lê links de get_virtual_tour, edita a lista e envia-a de volta.

curl -X POST https://app.pedra.ai/api/update_virtual_tour \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "YOUR_API_KEY",
    "tourId": "TOUR_ID",
    "sceneNames": { "a8d4f0b2-6e1c-4d97-8f3a-2b5c9e7d1a46": "Main bedroom" },
    "sceneOrder": [
      "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21",
      "5b2e9c71-0d3a-4a8f-b6e4-9c1f7d2a5e30",
      "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68",
      "a8d4f0b2-6e1c-4d97-8f3a-2b5c9e7d1a46"
    ],
    "navigationSize": "large",
    "showLabels": true
  }'

Resposta

JSON
{
  "tourId": "1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "propertyId": "196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "name": "Calle Mayor 12",
  "status": "ready",
  "tourUrl": "https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "embedCode": "<iframe src=\"https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19\" title=\"Calle Mayor 12\" width=\"100%\" height=\"600\" style=\"border:0\" allow=\"fullscreen; gyroscope; accelerometer\" allowfullscreen loading=\"lazy\"></iframe>",
  "appUrl": "https://app.pedra.ai/?projectId=196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "shareable": true,
  "sceneCount": 4,
  "linkCount": 6,
  "coverImageUrl": "https://img.pedra.ai/f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21",
  "createdAt": "2026-09-30T15:22:52.028Z",
  "updatedAt": "2026-09-30T15:23:41.310Z",
  "scenes": [
    { "sceneId": "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21", "name": "Entrance", "imageUrl": "https://img.pedra.ai/f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21" },
    { "sceneId": "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68", "name": "Living room", "imageUrl": "https://img.pedra.ai/cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68" },
    { "sceneId": "5b2e9c71-0d3a-4a8f-b6e4-9c1f7d2a5e30", "name": "Kitchen", "imageUrl": "https://img.pedra.ai/5b2e9c71-0d3a-4a8f-b6e4-9c1f7d2a5e30" },
    { "sceneId": "a8d4f0b2-6e1c-4d97-8f3a-2b5c9e7d1a46", "name": "Bedroom", "imageUrl": "https://img.pedra.ai/a8d4f0b2-6e1c-4d97-8f3a-2b5c9e7d1a46" }
  ],
  "links": [
    { "linkId": "ai-7c21", "fromSceneId": "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21", "toSceneId": "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68", "yaw": -18, "pitch": 0, "aiGenerated": true },
    { "linkId": "ai-7c22", "fromSceneId": "cf0a13ee-8b4d-4f62-a0c7-3e9d5b1f2a68", "toSceneId": "f1815046-2a7c-4e3b-9d15-6b8e0c4a7f21", "yaw": 164, "pitch": 0, "aiGenerated": true }
  ],
  "settings": {
    "navigationStyle": "white",
    "navigationSize": "medium",
    "showLabels": false,
    "language": "en"
  }
}

Adicionar divisões a um tour

POST/api/add_virtual_tour_scenes

Adiciona fotos 360° a um tour existente. Com ligação sequential só é ligado o troço novo: a última divisão existente à primeira nova, e depois cada divisão nova à seguinte. As ligações existentes, incluindo as que colocaste, mantêm-se. Custa máx(3, ⌈divisões novas ÷ 3⌉) créditos. É assíncrono como a criação, e o tour continua publicado entretanto — consulta get_virtual_tour até status voltar a ser "ready".

apiKeystringobrigatório
A tua chave API.
tourIdstringobrigatório
O id do tour (de create_virtual_tour ou list_virtual_tours).
scenesarrayobrigatório
As fotos 360° a adicionar, no mesmo formato que em create_virtual_tour. As cenas por imageId têm de ser fotos 360° do imóvel do tour.
linkingstring
sequential liga o troço novo; none adiciona as divisões sem pontos de navegação.
Values: sequential none
Default: sequential
curl -X POST https://app.pedra.ai/api/add_virtual_tour_scenes \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "YOUR_API_KEY",
    "tourId": "TOUR_ID",
    "scenes": [
      { "imageUrl": "https://example.com/360/bathroom.jpg", "name": "Bathroom" },
      { "imageUrl": "https://example.com/360/terrace.jpg" }
    ]
  }'

Resposta

JSON
{
  "tourId": "1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "propertyId": "196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "name": "Calle Mayor 12",
  "status": "processing",
  "tourUrl": "https://app.pedra.ai/virtual-tour/1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19",
  "sceneCount": 6,
  "linkCount": 6,
  "progress": { "stage": "queued" },
  "addedScenes": [
    { "sceneId": "3e7b1a95-4c0f-4b2d-9e68-1a5d8c3f7b02", "name": "Bathroom", "source": "https://example.com/360/bathroom.jpg" },
    { "sceneId": "9f6c2d48-7a1e-4e5b-8c3d-0b4a6f9e2d17", "name": null, "source": "https://example.com/360/terrace.jpg" }
  ],
  "creditsCost": 3,
  "estimatedSeconds": 31,
  "message": "Adding the scenes. The tour stays live while this runs. Poll get_virtual_tour until status is \"ready\"."
}

Eliminar um tour virtual

POST/api/delete_virtual_tour

Elimina o tour. O link público passa a devolver 404; as fotos 360° ficam no imóvel, por isso podes criar um novo tour com elas. Eliminar só está disponível na API — não existe como ferramenta MCP.

apiKeystringobrigatório
A tua chave API.
tourIdstringobrigatório
O id do tour (de create_virtual_tour ou list_virtual_tours).
curl -X POST https://app.pedra.ai/api/delete_virtual_tour \
  -H "Content-Type: application/json" \
  -d '{ "apiKey": "YOUR_API_KEY", "tourId": "TOUR_ID" }'

Resposta

JSON
{
  "message": "Virtual tour deleted. Its 360° photos are still in the property.",
  "tourId": "1d7aabf8-3c2e-4b8a-9f61-0c5d2e7a4b19"
}
POST/api/create_upload_link

Devolve uma página de carregamento sem login para um imóvel, válida durante 24 horas. Envia-a a quem tem as fotos — o fotógrafo, o agente, o proprietário. Abre-a no telemóvel ou no computador, larga as fotos (até 100 ficheiros, JPEG, PNG ou WebP, até 80 MB cada; as fotos HEIC do iPhone funcionam quando carregadas a partir do próprio iPhone) e vê miniaturas, progresso e um "Tudo pronto" no fim. Os ficheiros são ordenados pelo nome, que nas câmaras 360° corresponde à ordem de captura — normalmente também a ordem do percurso.

type define o que a página aceita:

  • "any" (predefinição) — fotos normais e fotos 360°. As imagens 2:1 são detetadas e guardadas automaticamente como fotos 360°. Usa-o para fotos a editar, mobilar ou transformar em vídeo, ou uma mistura.
  • "360" — só fotos 360°; tudo o resto é rejeitado com uma mensagem clara. Usa-o quando o link é para um tour virtual.

As fotos são guardadas como na app web: as normais com 2048 px no lado maior (3072 px se o ficheiro tiver mais de 20 MB) e as 360° com 4096 px de largura (6144 px acima de 20 MB).

É também assim que um assistente de chat obtém fotos de um telemóvel: o Claude não consegue passar anexos do chat a uma ferramenta, e as fotos que ainda estão no telemóvel nem sequer estão no chat, por isso o assistente cria um link de carregamento, tu carregas as fotos e ele continua. (No ChatGPT, as fotos anexadas ao chat funcionam diretamente — vê Servidor MCP.) O link só pode adicionar fotos a esse imóvel — não dá nenhum outro acesso à conta. Quando o carregamento terminar, chama list_property_images (type "photo" ou "360") para obter URLs para editar ou transformar em vídeo, ou create_virtual_tour com o propertyId e sem scenes.

Limites: 5 links de carregamento por dia no plano gratuito, 50 nos planos pagos (429 upload_link_limit) — cada link funciona 24 horas, por isso reutiliza o de hoje em vez de criar outro. Cada ficheiro carregado através de um link conta também para o limite diário de carregamento.

apiKeystringobrigatório
A tua chave API.
propertyIdstring
O imóvel para onde vão as fotos. Omite-o para criar um novo imóvel com o nome indicado em name.
namestring
Nome do novo imóvel, p. ex. a morada do anúncio. Aparece na página de carregamento.
typestring
O que a página aceita: "any" para fotos e fotos 360° (as imagens 2:1 são guardadas como 360° automaticamente), ou "360" só para fotos 360° — usa-o para um tour virtual.
Values: any 360
Default: any
languagestring
Idioma da página de carregamento.
Values: en es fr de it pt
Default: en
curl -X POST https://app.pedra.ai/api/create_upload_link \
  -H "Content-Type: application/json" \
  -d '{ "apiKey": "YOUR_API_KEY", "name": "Calle Mayor 12", "type": "360", "language": "es" }'

Resposta

JSON
{
  "uploadUrl": "https://app.pedra.ai/upload/q7Ht2vXk9LmP4wRz8NcB1sYd6FgJ3eUa0KoV5iTn?lang=es",
  "propertyId": "196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "propertyName": "Calle Mayor 12",
  "type": "360",
  "expiresAt": "2026-10-01T15:26:30.687Z",
  "maxFiles": 100,
  "appUrl": "https://app.pedra.ai/?projectId=196e742a-5b0d-4c9e-8a3f-7e2b1c6d9f04",
  "message": "Send this link to whoever has the 360° photos. It works on a phone or a computer with no login, for 24 hours. When they're done, list the property's photos (list_property_images; type "360" for 360° photos) and use them."
}

Carregar fotos 360°

Os tours são criados a partir de fotos 360° equirretangulares — os panoramas 2:1 que as câmaras 360° exportam. Cada foto é verificada (2:1, aceita-se 1,9–2,1, até 80 MB) e guardada como JPEG com 4096 px de largura (6144 px se o ficheiro tiver mais de 20 MB). Há três formas de as carregar:

  1. URLs públicos, diretamente — passa-os como scenes a create_virtual_tour. Ideal quando as fotos já estão online (o teu CDN ou bucket de armazenamento). Os links de partilha do Dropbox e do Google Drive são convertidos automaticamente em downloads diretos.
  2. add_images_to_property com type: "360" — guarda primeiro as fotos num imóvel (até 10 por chamada) e depois chama create_virtual_tour apenas com o propertyId. Também aceita URIs data:, por isso podes enviar ficheiros locais em base64 — um ou poucos por chamada, abaixo do limite de 50 MB por pedido.
  3. Um link de carregamento — quando as fotos estão no telemóvel ou na câmara de alguém e não online. Vê create_upload_link com type: "360".

Enviar ficheiros 360° locais como URIs data:, dois por chamada, e depois criar o tour:

import base64
import pathlib
import requests

API = "https://app.pedra.ai/api"
API_KEY = "YOUR_API_KEY"

def data_uri(path):
    return "data:image/jpeg;base64," + base64.b64encode(path.read_bytes()).decode()

# Sorted by file name = shooting order on most 360° cameras
files = sorted(pathlib.Path("./calle-mayor-12").glob("*.jpg"))

prop = requests.post(f"{API}/create_property",
                     json={"apiKey": API_KEY, "name": "Calle Mayor 12"}).json()

for i in range(0, len(files), 2):  # two per call keeps the body under 50 MB
    res = requests.post(f"{API}/add_images_to_property", json={
        "apiKey": API_KEY,
        "propertyId": prop["propertyId"],
        "type": "360",
        "imageUrls": [data_uri(p) for p in files[i:i + 2]],
    }).json()
    for f in res["failed"]:
        print("Skipped:", f["error"])

# No scenes: every 360° photo in the property, in upload order
tour = requests.post(f"{API}/create_virtual_tour",
                     json={"apiKey": API_KEY, "propertyId": prop["propertyId"]}).json()

Erros

Os erros chegam como { "error": "...", "code": "..." } (code apenas onde indicado). Vê Erros e limites para o modelo geral.

  • 400 — dados inválidos: uma foto que não é 360°, mais de 50 cenas, um valor de linking desconhecido. no_panoramas: o imóvel ainda não tem fotos 360°. no_new_scenes: todas as cenas que estás a adicionar já estão no tour.
  • 402 insufficient_credits — com creditsRequired, creditsAvailable e upgradeUrl. Nada é criado nem cobrado.
  • 404 — User not found (chave API errada), Virtual tour not found ou Property not found for this account.
  • 409 — tour_exists: o imóvel já tem um tour (o respetivo tourId vem na resposta). tour_processing: o tour ainda está a ser construído — espera até estar pronto. tour_failed: a construção falhou — elimina o tour e cria-o de novo.
  • 429 — upload_limit: as fotos enviadas por URL ultrapassariam o limite diário de carregamento da conta (30 por dia no plano gratuito, 500 nos planos pagos, reposto à meia-noite UTC); a chamada inteira é recusada e nada é guardado. upload_link_limit: a conta já criou os links de carregamento de hoje.

Seguinte

Cria tours a partir do ChatGPT ou do Claude com o servidor MCP, gere as fotos de um tour com a API de propriedades, ou transforma o mesmo anúncio num vídeo.