Tours virtuales

API de tours virtuales

Convierte fotos 360° en un tour virtual alojado y listo para compartir con una sola llamada. La IA pone nombre a las habitaciones y coloca los puntos de navegación entre ellas; recibes una URL pública del tour y un iframe para incrustarlo.

Envía tus fotos 360° y recibe un tour virtual alojado que puedes compartir o incrustar. Pedra importa las fotos equirrectangulares, la IA pone nombre a cada habitación y coloca los puntos de navegación de puerta a puerta, y la respuesta te da un tourUrl público y un iframe embedCode listo para pegar. Sin visor que alojar y sin puntos de navegación que colocar a mano.

Lo que obtienes con una sola llamada:

  • Una página de tour alojada — un tourUrl público y un iframe embedCode para cualquier página de anuncio, CRM o portal. Funciona en móvil (con el giroscopio) y en ordenador.
  • Nombres de habitación con IA — las habitaciones que no nombras reciben nombre automáticamente (Entrada, Cocina, Dormitorio 1…) en el idioma del tour, gratis. Los nombres que envías nunca se cambian.
  • Navegación con IA — Pedra localiza cada puerta en la foto y coloca los puntos de navegación entre habitaciones, en ambos sentidos.
  • Control total después — renombra, reordena, elimina o añade habitaciones y sustituye los puntos de navegación por los tuyos, todo desde la API.
  • Funciona desde el chat — los mismos endpoints son herramientas del servidor MCP de Pedra, así que ChatGPT y Claude pueden crear un tour desde una conversación.

Cómo funciona

Crear un tour es asíncrono: la llamada de creación devuelve un tourId al instante y el tour se construye en segundo plano (unos 10 segundos por habitación enlazada).

  1. Crea — POST /api/create_virtual_tour con tus fotos 360° en el orden del recorrido. Recibes el tourId, el tourUrl y el embedCode al instante, con status: "processing".
  2. Consulta — llama a POST /api/get_virtual_tour cada pocos segundos hasta que status sea "ready" (o "failed", con el motivo en error).
  3. Comparte — envía el tourUrl o pega el embedCode en la página de tu anuncio. La URL no cambia cuando editas el tour después.
# 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 enlace y créditos

El parámetro linking decide cómo se colocan los puntos de navegación. Poner nombre a las habitaciones siempre es gratis. Los créditos se cobran solo cuando empieza el enlazado, y una construcción que falla nunca se cobra.

Modo
Qué hace
Coste
sequential
Por defecto. Envía las habitaciones en el orden del recorrido; cada una se enlaza con la siguiente, en ambos sentidos.
máx(3, ⌈habitaciones ÷ 3⌉) créditos — 3 hasta 9 habitaciones, 4 para 12, 10 para 30
smart
La IA compara cada par de habitaciones y enlaza las que se conectan visiblemente — para cuando no conoces el orden del recorrido. Más lento; hasta 40 habitaciones.
5–160 créditos según el número de habitaciones (tabla abajo)
none
Sin puntos de navegación. Coloca los tuyos después con update_virtual_tour.
Gratis

Enlace smart según el número de habitaciones

Habitaciones
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 cuesta lo mismo que el enlace sequential, contando solo las habitaciones nuevas. get_virtual_tour, list_virtual_tours, update_virtual_tour, delete_virtual_tour y create_upload_link son gratis. Consulta tu saldo con credits.

Crear un tour virtual

POST/api/create_virtual_tour

Importa las fotos 360° y después nombra y enlaza las habitaciones en segundo plano. Envía scenes en el orden del recorrido — la primera es donde se abre el tour. Sin propertyId, se crea una propiedad nueva con el nombre de name. Para crear un tour con fotos que ya están en una propiedad (por ejemplo, las subidas con un enlace de subida), envía solo el propertyId y omite scenes: se usan todas las fotos 360° de la propiedad, en orden de subida. Cada propiedad tiene un tour; si ya tiene uno recibes 409 tour_exists con su tourId.

apiKeystringobligatorio
Tu clave API.
scenesarray
Las fotos 360°, en el orden del recorrido (máx. 50). Obligatorio salvo que envíes un propertyId cuyas fotos 360° formarán el tour.
imageUrlsarray
Atajo para scenes: una lista simple de URLs de fotos 360°.
propertyIdstring
Crea el tour en esta propiedad. Necesario si las escenas usan imageId. Sin scenes, se usan todas las fotos 360° de la propiedad en orden de subida. Omítelo para crear una propiedad nueva.
namestring
Título del tour, p. ej. la dirección del anuncio. También es el nombre de la propiedad nueva si se crea una.
linkingstring
Cómo se colocan los puntos de navegación — mira Modos de enlace y créditos.
Values: sequential smart none
Default: sequential
languagestring
Idioma de la página del tour y de los nombres de habitación de la IA. Los tours que no están en inglés tienen una URL tipo /es/virtual-tour/….
Values: en es fr de it pt
Default: en

Objeto scene

Cada escena es { imageUrl } o { imageId }, con un name opcional. Un string simple se trata como imageUrl. Hasta 50 escenas por tour.

imageUrlstring
URL pública (o URI data:) de una foto 360° equirrectangular — 2:1, hasta 80 MB. Funcionan los enlaces compartidos de Dropbox y Google Drive.
imageIdstring
Una foto 360° que ya está en la propiedad (de list_property_images con type "360"). Úsalo en lugar de imageUrl.
namestring
Nombre de la habitación. Si lo omites, la IA le pone nombre.
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" }
    ]
  }'

Respuesta

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\")."
}

Obtener un tour virtual

POST/api/get_virtual_tour

Devuelve el estado del tour y, cuando está listo, sus escenas, enlaces de navegación y ajustes de visualización. Es el endpoint que debes consultar tras create_virtual_tour y add_virtual_tour_scenes.

apiKeystringobligatorio
Tu clave API.
tourIdstringobligatorio
El id del tour (de create_virtual_tour o 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 — en construcción. progress.stage es queued, importing, naming o linking, con done / total cuando aplica.
  • ready — publicado en tourUrl. Incluye scenes, links y settings.
  • failed — no se ha cobrado nada. error explica el motivo y failedScenes lista cada foto que no se pudo usar (por ejemplo, una que no es 2:1). Las fotos que sí se importaron se quedan en la propiedad, así que puedes sustituir la incorrecta y volver a crear el tour por imageId.

Si una llamada a add_virtual_tour_scenes falla, el tour sigue ready e incluye lastError y failedScenes. En una cuenta del plan gratuito el tour se crea, pero su enlace público muestra una página de mejora de plan: las respuestas indican shareable: false, con un shareableNote.

Respuesta

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 virtuales

POST/api/list_virtual_tours

Devuelve los tours de la cuenta, del más reciente al más antiguo (hasta 100), con los mismos campos de resumen que get_virtual_tour pero sin scenes, links ni settings. Los tours eliminados no aparecen.

apiKeystringobligatorio
Tu clave API.
propertyIdstring
Devuelve solo el tour de esta propiedad.
curl -X POST https://app.pedra.ai/api/list_virtual_tours \
  -H "Content-Type: application/json" \
  -d '{ "apiKey": "YOUR_API_KEY" }'

Respuesta

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"
    }
  ]
}

Actualizar un tour virtual

POST/api/update_virtual_tour

Cambia el nombre del tour o de sus habitaciones, reordena o elimina habitaciones, sustituye los puntos de navegación y cambia su aspecto. Gratis e instantáneo. La validación es de todo o nada: si algún campo no es válido, no cambia nada. Devuelve el tour completo, como get_virtual_tour, o 409 tour_processing mientras el tour se está construyendo.

apiKeystringobligatorio
Tu clave API.
tourIdstringobligatorio
El id del tour (de create_virtual_tour o list_virtual_tours).
namestring
Nuevo título del tour.
sceneNamesobject
Nombres de habitación por sceneId, p. ej. { "<sceneId>": "Cocina" }.
sceneOrderarray
Cada sceneId exactamente una vez, en el nuevo orden. La primera es donde se abre el tour.
removeScenesarray
sceneIds que quitar del tour. Las fotos se quedan en la propiedad y se eliminan los enlaces que las usan. Debe quedar al menos una escena.
linksarray
Sustituye TODOS los enlaces de navegación. Cada enlace va en un sentido: { fromSceneId, toSceneId, yaw, pitch? }.
navigationStylestring
Color de los puntos de navegación.
Values: white blue
navigationSizestring
Tamaño de los puntos de navegación.
Values: small medium large
showLabelsboolean
Mostrar siempre el nombre de la habitación de destino junto a cada punto de navegación.
languagestring
Idioma de la página del tour.
Values: en es fr de it pt

Objeto link

fromSceneIdstringobligatorio
La escena en la que se muestra el punto de navegación.
toSceneIdstringobligatorio
La escena a la que lleva.
yawnumberobligatorio
Ángulo horizontal en la foto de fromScene, de −180 a 180. 0 es el centro de la foto; negativo es a la izquierda.
pitchnumber
Ángulo vertical, de −90 a 90. 0 es el horizonte.
Default: 0

Para ajustar los enlaces de la IA en lugar de empezar de cero, lee links de get_virtual_tour, edita la lista y reenvíala.

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

Respuesta

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"
  }
}

Añadir habitaciones a un tour

POST/api/add_virtual_tour_scenes

Añade fotos 360° a un tour existente. Con enlace sequential solo se enlaza el tramo nuevo: la última habitación existente con la primera nueva, y luego cada habitación nueva con la siguiente. Los enlaces existentes, incluidos los que colocaste tú, se mantienen. Cuesta máx(3, ⌈habitaciones nuevas ÷ 3⌉) créditos. Es asíncrono como la creación, y el tour sigue publicado mientras tanto — consulta get_virtual_tour hasta que status vuelva a ser "ready".

apiKeystringobligatorio
Tu clave API.
tourIdstringobligatorio
El id del tour (de create_virtual_tour o list_virtual_tours).
scenesarrayobligatorio
Las fotos 360° que añadir, con la misma forma que en create_virtual_tour. Las escenas por imageId deben ser fotos 360° de la propiedad del tour.
linkingstring
sequential enlaza el tramo nuevo; none añade las habitaciones sin puntos de navegación.
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" }
    ]
  }'

Respuesta

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 un tour virtual

POST/api/delete_virtual_tour

Elimina el tour. Su enlace público devuelve 404 a partir de ese momento; las fotos 360° se quedan en la propiedad, así que puedes crear un tour nuevo con ellas. Eliminar solo está disponible en la API — no es una herramienta MCP.

apiKeystringobligatorio
Tu clave API.
tourIdstringobligatorio
El id del tour (de create_virtual_tour o 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" }'

Respuesta

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

Devuelve una página de subida sin inicio de sesión para una propiedad, válida durante 24 horas. Envíala a quien tenga las fotos — el fotógrafo, el agente, el propietario. La abre en el móvil o en el ordenador, suelta las fotos (hasta 100 archivos, JPEG, PNG o WebP, de hasta 80 MB cada uno; las fotos HEIC del iPhone funcionan si se suben desde el propio iPhone) y ve miniaturas, progreso y un "Todo listo" al terminar. Los archivos se ordenan por nombre de archivo, que en las cámaras 360° es el orden de captura — normalmente también el orden del recorrido.

type define lo que acepta la página:

  • "any" (por defecto) — fotos normales y fotos 360°. Las imágenes 2:1 se detectan y se guardan como fotos 360° automáticamente. Úsalo para fotos que vas a editar, amueblar o convertir en vídeo, o una mezcla.
  • "360" — solo fotos 360°; cualquier otra cosa se rechaza con un mensaje claro. Úsalo cuando el enlace es para un tour virtual.

Las fotos se guardan igual que en la app web: las normales a 2048 px en el lado largo (3072 px si el archivo supera 20 MB) y las 360° a 4096 px de ancho (6144 px por encima de 20 MB).

También es la forma en que un asistente de chat obtiene fotos de un móvil: Claude no puede pasar adjuntos del chat a una herramienta, y las fotos que siguen en el móvil ni siquiera están en el chat, así que el asistente crea un enlace de subida, tú subes las fotos y él continúa. (En ChatGPT, las fotos adjuntadas al chat funcionan directamente — mira Servidor MCP.) El enlace solo puede añadir fotos a esa propiedad — no da ningún otro acceso a la cuenta. Cuando termine la subida, llama a list_property_images (type "photo" o "360") para obtener URLs que editar o convertir en vídeo, o a create_virtual_tour con el propertyId y sin scenes.

Límites: 5 enlaces de subida al día en el plan gratuito, 50 en los de pago (429 upload_link_limit) — cada enlace funciona 24 horas, así que reutiliza el de hoy en vez de crear otro. Cada archivo subido con un enlace cuenta también para el límite diario de subidas.

apiKeystringobligatorio
Tu clave API.
propertyIdstring
La propiedad a la que van las fotos. Omítelo para crear una propiedad nueva con el nombre de name.
namestring
Nombre de la propiedad nueva, p. ej. la dirección del anuncio. Se muestra en la página de subida.
typestring
Lo que acepta la página: "any" para fotos y fotos 360° (las imágenes 2:1 se guardan como 360° automáticamente), o "360" solo para fotos 360° — úsalo para un tour virtual.
Values: any 360
Default: any
languagestring
Idioma de la página de subida.
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" }'

Respuesta

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."
}

Subir fotos 360°

Los tours se crean con fotos 360° equirrectangulares — los panoramas 2:1 que exportan las cámaras 360°. Se comprueba que cada foto sea 2:1 (se acepta 1,9–2,1) y de hasta 80 MB, y se guarda como JPEG de 4096 px de ancho (6144 px si el archivo supera 20 MB). Hay tres formas de subirlas:

  1. URLs públicas, directamente — pásalas como scenes a create_virtual_tour. Lo mejor cuando las fotos ya están online (tu CDN o bucket de almacenamiento). Los enlaces compartidos de Dropbox y Google Drive se convierten automáticamente en descargas directas.
  2. add_images_to_property con type: "360" — guarda primero las fotos en una propiedad (hasta 10 por llamada) y luego llama a create_virtual_tour solo con el propertyId. También acepta URIs data:, así que puedes enviar archivos locales en base64 — uno o unos pocos por llamada, por debajo del límite de 50 MB por petición.
  3. Un enlace de subida — cuando las fotos están en el móvil o la cámara de alguien y no online. Mira create_upload_link con type: "360".

Enviar archivos 360° locales como URIs data:, dos por llamada, y después crear el 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()

Errores

Los errores llegan como { "error": "...", "code": "..." } (code solo donde se indica). Mira Errores y límites para el modelo general.

  • 400 — datos no válidos: una foto que no es 360°, más de 50 escenas, un valor de linking desconocido. no_panoramas: la propiedad aún no tiene fotos 360°. no_new_scenes: todas las escenas que añades ya están en el tour.
  • 402 insufficient_credits — con creditsRequired, creditsAvailable y upgradeUrl. No se crea ni se cobra nada.
  • 404 — User not found (clave API incorrecta), Virtual tour not found o Property not found for this account.
  • 409 — tour_exists: la propiedad ya tiene un tour (su tourId viene en la respuesta). tour_processing: el tour aún se está construyendo — espera a que esté listo. tour_failed: la construcción falló — elimina el tour y vuelve a crearlo.
  • 429 — upload_limit: las fotos enviadas por URL superarían el límite diario de subidas de la cuenta (30 al día en el plan gratuito, 500 en los de pago, se reinicia a medianoche UTC); se rechaza la llamada entera y no se guarda nada. upload_link_limit: la cuenta ya ha creado sus enlaces de subida de hoy.

Siguiente

Crea tours desde ChatGPT o Claude con el servidor MCP, gestiona las fotos de un tour con la API de propiedades o convierte el mismo anuncio en un vídeo.