Referencia de la API
La API de Prewalk forma parte del plan Corporativo. Con una clave de API, tu propio software puede crear recorridos, subir escenas, publicar, leer proyectos y estadísticas, y recibir un webhook firmado en cada etapa del procesamiento. Esta página es la referencia; el estudio y el reproductor público siguen funcionando como siempre.
URL base y convenciones
- URL base:
https://prewalk.co. No usesapp.prewalk.co: redirige (308) y la mayoría de los clientes HTTP descartan el encabezadoAuthorizational redirigir a otro host. - Formato: JSON de entrada y de salida (
Content-Type: application/json), salvo en la subida de escenas, que envía la imagen como cuerpo en bruto de la solicitud. - Los ID tienen 12 caracteres entre letras minúsculas y dígitos, por ejemplo
teeg8crtm0u0. Las fechas van en ISO 8601 y en UTC. - Los errores siempre tienen la misma forma: un estado HTTP y
{"error": {"code": "…", "message": "…"}}; los errores de validación añadenfield. Los códigos aparecen al final de esta página. - Límite de frecuencia: 600 solicitudes por minuto por clave. Si lo superas, recibes un
429con un encabezadoRetry-After(en segundos).
Autenticación
Crea una clave en Configuración → API (propietario de la cuenta o administrador, plan Corporativo). Una clave pertenece a la cuenta, puede limitarse a un perfil de marca y tiene hasta tres permisos: read, write y stats. La clave completa se muestra una sola vez; en la lista solo aparece su prefijo. Hasta 20 claves por cuenta; una clave revocada deja de funcionar al instante.
Authorization: Bearer pw_…
Una clave actúa en nombre de una cuenta. GET /api/me describe lo que la clave puede ver: la cuenta y los límites de su plan, los perfiles de esa cuenta, el perfil con el que actúa la clave (actor) y la propia clave con sus permisos. Nunca devuelve el correo del propietario de la clave ni sus otras cuentas.
Endpoints
| Método y ruta | Permiso | Qué hace |
|---|---|---|
GET /api/me | read | La cuenta, los perfiles y los permisos de la clave |
GET /api/tours | read | Lista los recorridos de la cuenta (limit ≤ 50, cursor, profileId) |
GET /api/tours/{id} | read | Un recorrido con sus escenas, hotspots y configuración |
GET /api/tours/{id}/events | read | El progreso del procesamiento como flujo de eventos enviados por el servidor |
POST /api/tours | write | Crea un recorrido ({"title": "…"}) |
PATCH /api/tours/{id} | write | Cambia el título, la descripción, la categoría, la ubicación, las etiquetas, el slug (la dirección legible), el orden de las escenas, la escena de inicio y los nombres de las escenas |
POST /api/tours/{id}/scenes | write | Sube una imagen 360° como cuerpo en bruto |
POST /api/content/{id}/visibility | write | Publica un recorrido o proyecto, lo deja solo con enlace o lo protege con contraseña |
GET /api/projects | read | Lista los proyectos de la cuenta (limit, cursor, profileId) |
GET /api/projects/{id} | read | Un proyecto con sus recorridos, imágenes, videos y planos |
GET /api/stats/{contentId} | stats | Visualizaciones de un recorrido o proyecto (range en días) |
GET /api/stats/{contentId}/export.csv | stats | Lo mismo en CSV (table = daily, scenes o referrers) |
Cualquier otro endpoint responde 403 api_key_forbidden si se llama con una clave. La cuenta, el equipo, la facturación, las claves de API y los webhooks se gestionan en el navegador.
Recorridos
Listar. GET /api/tours?limit=50 devuelve {"items": […], "next": "…", "usage": {…}}. Envía next como cursor para obtener la página siguiente; usage contiene el número de escenas de la cuenta y sus límites. Cada elemento incluye id, title, visibility, publishedAt, createdAt, updatedAt, el perfil y los recuentos de escenas.
Leer. GET /api/tours/{id} devuelve el recorrido completo: title, description, category, location, tags, slug, visibility (public, link o password), hasPassword, publishedAt, profile, projectId, startScene, coverScene, revision, scenes en orden, hotspots, settings, audio y links (player es la dirección para compartir; post, la página pública cuando está publicado).
Una escena tiene id, name, status (queued, processing, ready o error), createdAt y, opcionalmente, view (la dirección de la vista inicial: yaw, pitch y fov en radianes), north (en radianes; 0 es el centro de la imagen y aumenta hacia la derecha) y, mientras se procesa, stage y pct. Cuando está lista, la escena incluye meta con sus niveles de teselas y la raíz de los archivos multimedia.
Crear. POST /api/tours con {"title": "Harbor View — Unit 4"} devuelve el nuevo recorrido. Si no tiene título, se llama «Untitled tour».
Actualizar. PATCH /api/tours/{id} acepta cualquiera de estos campos y devuelve el recorrido:
title,description,category,location,tags(array de cadenas),slug(la dirección pública: letras minúsculas, dígitos y guiones),commentsEnabled;order: un array de ID de escena en el orden que quieras; las escenas que no incluyas conservan su lugar detrás de las que hayas indicado;startScene: un ID de escena; esa escena pasa al principio (la primera escena es la escena de inicio);coverScene: un ID de escena, onullpara usar la escena de inicio;scenes: un objeto indexado por ID de escena, conname,view({"yaw", "pitch", "fov"}) ynorth(en grados).
Envía If-Match: "<revision>" con la revision que leíste por última vez para rechazar una escritura sobre el cambio de otra persona: la respuesta es entonces 409 revision_conflict, con el recorrido actual en error.tour. Sin If-Match, gana la última escritura.
Subida de escenas
POST /api/tours/{id}/scenes con el archivo de imagen como cuerpo en bruto. Encabezados:
Content-Type:image/jpeg,image/png,image/tiffoimage/webp;x-file-name: el nombre del archivo, codificado para URL (encodeURIComponent); la escena toma ese nombre, así que01-living-room.jpgpasa a llamarse «01 living room»;x-pw-upload-batchyx-pw-upload-index(opcionales): cuando subas en paralelo varios archivos de una misma selección, dales el mismo ID de lote (letras, dígitos,-y_, hasta 32 caracteres) y su índice en la selección; así el servidor mantiene ese orden sin importar qué archivo termine primero. Sin ellos, las escenas se añaden por orden de llegada.
Imágenes aceptadas: panorámicas equirrectangulares 2:1 hasta el ancho máximo del plan (8K en el plan Gratis y 16K a partir de Pro), o panorámicas estereoscópicas 1:1 arriba-abajo a partir de Pro (ojo izquierdo arriba), de hasta 1 GiB. La respuesta es la escena (status: "queued"). El procesamiento va por etapas: primero la escena se vuelve visible (teselas de vista previa); después llegan las teselas a resolución completa («mejora de nitidez») y, a partir de Pro, las texturas para VR; las dos etapas avanzan en paralelo y cualquiera de ellas puede terminar primero. El meta.pending de la escena, el flujo de eventos y los webhooks te indican qué etapas siguen en curso.
Errores: 400 unsupported_format (no es JPG, PNG, TIFF ni WebP), 400 unsupported_ratio (no es 2:1 ni 1:1 arriba-abajo), 400 unreadable_image (un archivo dañado), 402 plan_required (16K o estéreo en un plan que no los incluye), 402 quota_exceeded (el límite de escenas de la cuenta), 413 file_too_large.
Progreso del procesamiento
GET /api/tours/{id}/events es un flujo de eventos enviados por el servidor (text/event-stream). Eventos: hello al conectarse, queue (la posición en la cola de las escenas en espera y un resumen del recorrido, cada pocos segundos mientras haya algo en marcha), scene (status, stage, pct o error) y tour (el recorrido cambió; vuelve a leerlo). Para integraciones entre servidores, es preferible usar los webhooks que se describen más abajo.
Publicación y visibilidad
POST /api/content/{id}/visibility sirve para recorridos y proyectos, y devuelve el contenido:
{"visibility": "link"}: accesible solo a través de su dirección (el valor predeterminado de todo recorrido nuevo);{"visibility": "public", "rightsAccepted": true}: en el perfil, en Explorar e indexable; hace falta unacategory(configúrala antes conPATCH) y confirmas que tienes derecho a publicar las imágenes. Para un proyecto, añade"tourIds": [...]para publicar recorridos junto con él;{"visibility": "password", "password": "…"}: a partir de Pro; omitepasswordpara mantener la contraseña actual.
Un recorrido dentro de un proyecto protegido con contraseña no puede hacerse público ni tener su propia contraseña (409 in_password_project); el acceso lo controla la contraseña del proyecto.
Proyectos
Por ahora, los proyectos son de solo lectura en la API. GET /api/projects los lista con id, title, slug, visibility, category, coverUrl, tourCount, imageCount, videoCount y las fechas; GET /api/projects/{id} añade description, location, tags, urls (public y el enlace privado), los tours con sus escenas y, de la galería, las images, los videos y los floorplans con sus marcadores. Crea proyectos y añade archivos multimedia en el estudio.
Estadísticas
GET /api/stats/{contentId}?range=30 devuelve las visualizaciones de un recorrido o proyecto. Lo que recibes depende del plan: el total histórico en el plan Gratis; una serie daily rellenada con ceros (from, to, hasta 90 días) en Pro; y en Office y Corporativo, hasta 365 días más sources (página, inserción, directo), devices (teléfono, escritorio, visor de realidad virtual), scenes y los referrers de las inserciones. …/export.csv?range=30&table=daily da la tabla diaria; table=scenes, las visualizaciones por escena, y table=referrers, los sitios donde está insertado. Las visualizaciones se cuentan por dirección del visitante y contenido, una vez cada 30 minutos; no se guarda ningún dato personal.
Webhooks
Añade hasta cinco webhooks en Configuración → API. Enviamos un POST firmado con un cuerpo JSON:
{"eventId": "evt_…", "eventType": "scene.ready", "occurredAt": "2026-10-22T09:12:03.000Z",
"data": {"tourId": "…", "sceneId": "…", "status": "ready", "pending": ["refine", "vr"]}}
| Evento | Cuándo | Datos |
|---|---|---|
scene.ready | La escena es visible (teselas de vista previa) | pending: etapas que siguen en curso — refine (teselas a resolución completa) y vr (texturas para visores de realidad virtual); [] cuando la vista previa es la versión final |
scene.sharpened | Las teselas a resolución completa están listas | stage: "refine", ok (false si la etapa se descartó y la escena se queda con la calidad de vista previa), pending |
scene.vr_ready | Las texturas para VR están listas | stage: "vr", ok, pending |
scene.failed | El procesamiento falló de forma definitiva | error con el motivo |
ping | El botón «Enviar prueba» | vacío |
Encabezados: Prewalk-Signature: ts=<unix seconds>;h1=<hex>, donde h1 es el HMAC-SHA256 de ts + ":" + body con el secreto de tu webhook (calculado sobre los bytes exactos que recibiste), además de Prewalk-Event-Id y Prewalk-Event-Type. Mientras hay una rotación del secreto en curso, el encabezado lleva dos valores h1 (ts=…;h1=<new>;h1=<old>) hasta que caduca el secreto anterior: acepta la entrega si cualquiera de ellos se verifica. Verifica la firma, rechaza las marcas de tiempo de hace más de unos minutos y elimina los duplicados por eventId: una entrega se reintenta hasta que tu endpoint responde con un 2xx (diez intentos, a los 30 s y luego con el doble de espera cada vez, unas cuatro horas en total) y el cuerpo reintentado es idéntico byte a byte. Tras 20 entregas fallidas seguidas, el webhook se desactiva y el propietario de la cuenta recibe un correo. Los endpoints deben usar https en una dirección pública; las redirecciones no se siguen. El secreto se puede rotar; el anterior sigue siendo válido durante 24 horas.
Ejemplo paso a paso
# 1. create a tour
curl -s https://prewalk.co/api/tours -H "Authorization: Bearer $PW_KEY" \
-H "Content-Type: application/json" -d '{"title":"Harbor View — Unit 4"}'
# 2. upload two scenes in order
curl -s https://prewalk.co/api/tours/$TOUR/scenes -H "Authorization: Bearer $PW_KEY" \
-H "Content-Type: image/jpeg" -H "x-file-name: 01-living-room.jpg" \
-H "x-pw-upload-batch: sel-1" -H "x-pw-upload-index: 0" --data-binary @01-living-room.jpg
curl -s https://prewalk.co/api/tours/$TOUR/scenes -H "Authorization: Bearer $PW_KEY" \
-H "Content-Type: image/jpeg" -H "x-file-name: 02-kitchen.jpg" \
-H "x-pw-upload-batch: sel-1" -H "x-pw-upload-index: 1" --data-binary @02-kitchen.jpg
# 3. set a category and publish
curl -s -X PATCH https://prewalk.co/api/tours/$TOUR -H "Authorization: Bearer $PW_KEY" \
-H "Content-Type: application/json" -d '{"category":"real-estate","location":"Istanbul"}'
curl -s https://prewalk.co/api/content/$TOUR/visibility -H "Authorization: Bearer $PW_KEY" \
-H "Content-Type: application/json" -d '{"visibility":"public","rightsAccepted":true}'
# 4. views of the last 30 days
curl -s "https://prewalk.co/api/stats/$TOUR?range=30" -H "Authorization: Bearer $PW_KEY"
Inserción
Para insertar no hace falta ninguna clave: cada recorrido tiene https://prewalk.co/embed/{id}, y embed.js ajusta el tamaño del marco y lo abre a pantalla completa en tu página. Los sitios web que pueden mostrar tus inserciones se configuran en Configuración → Imagen de marca. Encontrarás los detalles en la guía de inserción.
Códigos de error
| Estado | Código | Significado |
|---|---|---|
| 400 | invalid_request | Falta un campo o no es válido; field indica cuál |
| 400 | unsupported_format, unsupported_ratio, unreadable_image, rights_required, category_required, project_needs_content | Condiciones previas para subir o publicar (un proyecto necesita un recorrido público, una imagen o un video) |
| 401 | unauthorized, invalid_api_key | No se envió ninguna clave, o la clave está mal formada o revocada |
| 402 | plan_required, quota_exceeded | El plan no incluye la función, o se alcanzó un límite (feature o limit indica cuál) |
| 403 | api_key_forbidden, api_scope_missing | El endpoint no admite claves, o a la clave le falta el permiso |
| 404 | not_found | No es tuyo, se eliminó o el ID no existe |
| 409 | revision_conflict, slug_taken, in_password_project | Edición simultánea (se incluye el recorrido actual), dirección en uso, regla de contraseña del proyecto |
| 413 | file_too_large | Supera el límite de tamaño |
| 429 | rate_limited | Demasiadas solicitudes; espera los segundos indicados en Retry-After |
| 503 | maintenance | Prewalk se está actualizando; vuelve a intentarlo en un minuto |
Cambios
- 10 de noviembre de 2026: un proyecto se puede publicar o proteger con contraseña solo con imágenes o videos. Un proyecto sin nada que mostrar responde
400 project_needs_content, tanto si es público como si tiene contraseña; este código sustituye aproject_needs_public_touryproject_needs_tour, que ya no se envían.GET /api/projectsañadevideoCount. - 22 de octubre de 2026:
scene.readyincluyepending; nuevos eventosscene.sharpenedyscene.vr_ready; encabezados de orden de subidax-pw-upload-batchyx-pw-upload-index; con una clave,GET /api/mesolo describe la cuenta de la clave.
¿Tienes preguntas o te falta algún endpoint? Escribe a hello@prewalk.co.



