API de publicación de ConnectorProperty
Versión del contrato: 2026-09-17 (viene también en la cabecera
X-ConnectorProperty-Api-Version y en el campo api_version de cada respuesta).
Esta API es para integradores: softwares de corretaje (CRM) que publican en ConnectorProperty las propiedades de sus corredoras. El integrador envía cada alta, cambio o baja en el momento en que ocurre; ConnectorProperty valida, publica y devuelve las consultas de los interesados.
1. Resumen
| URL base | https://connectorproperty.com/api/v1 |
| Autenticación | Authorization: Bearer <API key> |
| Formato | JSON UTF-8. Campos en inglés, snake_case |
| Fechas | ISO 8601 en UTC (2026-09-17T14:03:12.481Z) |
| Modelo | El integrador empuja los cambios (PUT/DELETE). Publicación inmediata |
| Identificadores | Los del integrador (external_id). No hace falta guardar ids nuestros |
| Consultas | Webhook firmado hacia el integrador + consulta periódica de respaldo |
Flujo típico:
PUT /publishers/{id}— da de alta la corredora (una vez, y cuando cambie).PUT /publishers/{id}/agents/{id}— da de alta a cada agente.PUT /listings/{id}— publica o actualiza una propiedad.DELETE /listings/{id}— la despublica.- Recibe las consultas por webhook y avisa con
POST /leads/{id}/eventscuando el agente respondió.
2. Autenticación y ambientes
PUT /api/v1/listings/NX-00012 HTTP/1.1
Host: connectorproperty.com
Authorization: Bearer cp_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: application/json
- Hay dos tipos de llave:
cp_live_…— producción. Lo publicado aparece en el portal.cp_test_…— pruebas. Se valida y se guarda igual, pero nunca se muestra públicamente. Cada respuesta trae unapreview_urlprivada.
- Los datos de prueba y producción están separados: un
external_idde pruebas no toca el de producción. - Guarden la llave como secreto del servidor. Si se filtra, avisen y se revoca.
- Sin llave, inválida o revocada:
401 unauthorized.
3. Corredoras (publishers)
Quien publica: una corredora o un corredor independiente.
PUT /publishers/{external_id}
{
"kind": "agency",
"name": "Focolare Propiedades",
"legal_name": "Focolare Propiedades SpA",
"rut": "77.123.456-7",
"email": "contacto@focolare.cl",
"phone": "+56223456789",
"website": "https://focolare.cl",
"logo_url": "https://…/logo.png",
"active": true
}
| Campo | Obligatorio | Notas |
|---|---|---|
kind |
sí | agency · independent_broker |
name |
sí | Marca comercial, la que ve el público. |
legal_name |
sí | Razón social o nombre legal. |
rut |
sí | RUT de la empresa o del corredor independiente. Con o sin puntos; se valida el dígito verificador. |
email, phone |
no | phone en E.164 (+56…). |
website, logo_url |
no | https. |
active |
no | Por defecto true. Con false, todas sus propiedades dejan de mostrarse (no se borran) y vuelven solas al reactivarla. |
Respuesta 200 (o 201 si es nueva):
{
"data": {
"external_id": "focolare",
"name": "Focolare Propiedades",
"rut": "77123456-7",
"active": true,
"verification": { "rut_valid": true, "sii_status": "pending", "verified_at": null }
},
"api_version": "2026-09-17"
}
Verificación. ConnectorProperty verifica el RUT y la razón social contra
el SII y muestra un sello "Corredora verificada" cuando coincide.
sii_status: pending · verified · mismatch (el nombre no coincide) ·
not_found. La verificación no bloquea la publicación.
4. Agentes
PUT /publishers/{publisher_external_id}/agents/{external_id}
{
"name": "Javiera Soto",
"title": "Corredora de Propiedades",
"email": "javiera@focolare.cl",
"phone": "+56988823456",
"whatsapp": "+56988823456",
"photo_url": "https://…/javiera.webp",
"profile_url": "https://llaveprop.com/javiera-soto",
"active": true
}
| Campo | Obligatorio | Notas |
|---|---|---|
name, email |
sí | email recibe copia de las consultas si el integrador no tiene webhook. |
phone, whatsapp |
uno de los dos | E.164. El botón de WhatsApp de la ficha usa whatsapp. |
active |
no | Con false sus propiedades dejan de mostrarse y vuelven solas al reactivarlo. |
Respuesta 200/201 con el agente guardado.
5. Propiedades (listings)
5.1 PUT /listings/{external_id} — publicar o actualizar
Crea la propiedad si no existe y la reemplaza entera si existe (no es un parche: envíen siempre todos los campos). Es idempotente: repetir la misma petición no cambia nada. Si la propiedad estaba despublicada, la vuelve a publicar.
{
"publisher_external_id": "focolare",
"agent_external_id": "cmu3msc0g01d5y0sg8k4q1x2z",
"code": "NX-00012",
"source_url": "https://llaveprop.com/p/NX-00012",
"operation": "rent",
"property_type": "apartment",
"availability": "available",
"title": "Departamento 2D/2B con vista despejada",
"description": "Luminoso, a pasos del metro…",
"price": { "amount": 850000, "currency": "CLP" },
"common_expenses_clp": 120000,
"bedrooms": 2,
"bathrooms": 2,
"parking_spaces": 1,
"storage_units": 1,
"built_area_m2": 72.5,
"land_area_m2": null,
"floor": 8,
"total_floors": 20,
"year_built": 2018,
"orientation": "Norte",
"furnished": true,
"pets_allowed": true,
"features": ["Piscina", "Gimnasio"],
"location": {
"region": "Metropolitana de Santiago",
"commune": "Providencia",
"street": "Av. Providencia",
"number": "1234",
"unit": "801",
"lat": -33.42612,
"lng": -70.61705,
"show_exact_address": false
},
"photos": [
{ "url": "https://llaveprop.com/uploads/fotos/1789-ab12.jpg", "caption": "Living" }
],
"video_url": null,
"virtual_tour_url": null,
"sii_role": null,
"rent_requirements": {
"income_multiple": 3,
"guarantee_months": 1,
"requires_guarantor": false
},
"published_at": "2026-09-10T18:22:05.110Z"
}
Campos
| Campo | Obligatorio | Notas |
|---|---|---|
publisher_external_id |
sí | Debe existir (sección 3). |
agent_external_id |
sí | Debe existir y pertenecer a esa corredora. |
code |
sí | Código visible en el CRM. Se muestra en la ficha. |
source_url |
no | Ficha en el sitio del integrador. |
operation |
sí | sale · rent |
property_type |
sí | apartment · house · office · commercial · land · warehouse · farm (parcela) · parking |
availability |
no | available (por defecto) · reserved |
title |
sí | 10 a 120 caracteres, texto plano. |
description |
sí | 30 a 8.000 caracteres, texto plano con saltos de línea. Sin teléfonos ni correos (se usa el contacto del agente). |
price.amount |
sí | Mayor que 0. |
price.currency |
sí | UF · CLP. ConnectorProperty muestra siempre ambas monedas con la UF del día. |
common_expenses_clp |
ver 5.4 | Gastos comunes mensuales en pesos. 0 si no tiene. |
bedrooms, bathrooms, parking_spaces, storage_units |
no | Enteros ≥ 0. null = no informado. |
built_area_m2, land_area_m2 |
ver 5.4 | Metros cuadrados. |
floor, total_floors, year_built |
no | Enteros. |
orientation |
no | Norte, Nororiente, Oriente, Suroriente, Sur, Surponiente, Poniente, Norponiente. |
furnished, pets_allowed |
no | Booleanos, por defecto false. |
features |
no | Lista de textos en español, máximo 60. |
location.region |
sí | Nombre de la región. |
location.commune |
sí | Nombre de la comuna de Chile. Se aceptan mayúsculas y tildes variables ("nunoa", "Ñuñoa"). Una comuna desconocida rechaza la propiedad. |
location.street, number, unit |
no | |
location.lat, lng |
recomendado | Sin coordenadas la propiedad aparece en la lista pero no en el mapa. |
location.show_exact_address |
no | Por defecto false: se muestra solo la comuna y una zona aproximada de ~300 m; calle y número nunca se publican. |
photos |
sí | 1 a 25, en orden (la primera es la portada). url pública https, JPEG/PNG/WebP, idealmente ≥ 1.200 px de ancho. Con menos de 12 fotos la propiedad se publica, pero con puntaje de calidad bajo. |
video_url |
no | YouTube o Vimeo. |
virtual_tour_url |
no | Matterport u otro tour https. |
sii_role |
no | Rol de avalúo SII (1234-56). Permite mostrar avalúo fiscal y contribuciones. |
rent_requirements |
no | Solo arriendo. income_multiple (renta líquida exigida, en veces el arriendo), guarantee_months, requires_guarantor. |
published_at |
no | Primera publicación en el CRM. |
Campos desconocidos se ignoran. Nunca envíen datos del propietario ni la comisión: no hay campos para eso y se descartan.
Respuesta
201 si es nueva, 200 si se actualizó (o no cambió nada):
{
"data": {
"external_id": "NX-00012",
"public_code": "CP-10042",
"status": "published",
"url": "https://connectorproperty.com/propiedad/CP-10042-departamento-arriendo-providencia",
"preview_url": null,
"result": "updated",
"quality": {
"score": 82,
"warnings": [
{ "field": "photos", "code": "few_photos", "message": "Tiene 3 foto(s). Con menos de 12 fotos el aviso aparece más atrás en los resultados." }
]
},
"updated_at": "2026-09-17T14:03:12.481Z"
},
"api_version": "2026-09-17"
}
result:created·updated·unchanged·republished.status: ver 5.3.quality.warningsno impiden publicar. Los errores sí (ver sección 8).
5.2 DELETE /listings/{external_id} — despublicar
DELETE /listings/NX-00012?reason=closed
reason |
Cuándo |
|---|---|
unpublished |
El agente la despublicó o pausó (por defecto). |
closed |
Se vendió o arrendó. |
agent_inactive |
El agente fue dado de baja. |
publisher_suspended |
La corredora fue suspendida en el CRM. |
portal_disabled |
La corredora desactivó ConnectorProperty. |
La propiedad no se borra: queda despublicada con su motivo y su historial.
Un PUT posterior la vuelve a publicar. Es idempotente: despublicar algo ya
despublicado responde 200. Si nunca existió, 404.
Respuesta 200:
{ "data": { "external_id": "NX-00012", "status": "unpublished", "reason": "closed" }, "api_version": "2026-09-17" }
5.3 Estados
status |
Significado |
|---|---|
published |
Visible en el portal. |
hidden |
Guardada, pero no visible porque la corredora o el agente están inactivos. Vuelve sola. |
unpublished |
Despublicada por el integrador (DELETE). |
moderated |
Retirada por ConnectorProperty (sospecha de fraude, contenido indebido). Viene con moderation_reason, y se avisa por webhook. Contacten a soporte. |
5.4 Reglas de calidad
Errores (rechazan la petición con 422):
common_expenses_clpobligatorio (puede ser0) paraapartmentyoffice.built_area_m2obligatorio paraapartment,house,office,commercialywarehouse;land_area_m2obligatorio paralandyfarm.- Precio fuera de rango razonable para su moneda y operación (p. ej. un arriendo de $500 o una venta de UF 5.000.000).
built_area_m2> 0 y < 100.000;bedrooms≤ 50;bathrooms≤ 50.
Advertencias (publican igual, bajan el puntaje de calidad):
- Menos de 12 fotos (baja el puntaje de forma importante), sin coordenadas, descripción de menos de 200 caracteres.
- Teléfonos o correos dentro de la descripción (se ocultan al mostrarla).
- Arriendo sin
rent_requirements.
El puntaje de calidad (0–100) influye en el orden por relevancia.
5.5 GET /listings/{external_id}
Devuelve el estado de la propiedad en ConnectorProperty: status, url,
quality, motivo de baja o moderación y estadísticas de los últimos 30 días:
{
"data": {
"external_id": "NX-00012",
"public_code": "CP-10042",
"status": "published",
"url": "https://connectorproperty.com/propiedad/CP-10042-…",
"unpublished_reason": null,
"moderation_reason": null,
"quality": { "score": 82, "warnings": [] },
"stats_30d": { "views": 312, "whatsapp_clicks": 14, "phone_clicks": 3, "leads": 5 },
"updated_at": "2026-09-17T14:03:12.481Z"
},
"api_version": "2026-09-17"
}
5.6 GET /listings — reconciliación
Lista todas las propiedades del integrador en ConnectorProperty, para comparar con el CRM y corregir diferencias.
| Parámetro | Por defecto | Descripción |
|---|---|---|
status |
todas | published · hidden · unpublished · moderated |
limit |
100 | 1 a 500 |
cursor |
— | next_cursor de la página anterior |
{
"data": [ { "external_id": "NX-00012", "status": "published", "updated_at": "…" } ],
"has_more": false,
"next_cursor": null,
"api_version": "2026-09-17"
}
Recomendado una vez al día: todo lo que esté published aquí y no deba estar
publicado en el CRM, se despublica con DELETE.
6. Consultas (leads)
Cuando un interesado escribe desde la ficha, ConnectorProperty crea una consulta y la entrega al integrador.
6.1 Webhook
El integrador registra una URL https (se configura con soporte). Cada
evento llega como POST:
POST /webhooks/connectorproperty HTTP/1.1
Content-Type: application/json
X-ConnectorProperty-Event: lead.created
X-ConnectorProperty-Delivery: 5b1f7e0c-…
X-ConnectorProperty-Signature: t=1789653792,v1=5f2c…
{
"event": "lead.created",
"created_at": "2026-09-17T14:05:00.000Z",
"environment": "live",
"data": {
"id": "a6f0c3e2-…",
"type": "question",
"listing_external_id": "NX-00012",
"listing_public_code": "CP-10042",
"publisher_external_id": "focolare",
"agent_external_id": "cmu3msc0g01d5y0sg8k4q1x2z",
"name": "Pedro Pérez",
"email": "pedro@example.com",
"phone": "+56911112222",
"message": "Hola, ¿sigue disponible? ¿Se puede visitar el sábado?",
"created_at": "2026-09-17T14:05:00.000Z"
}
}
type:question·visit_request.- Firma:
v1esHMAC-SHA256(secreto_webhook, "<t>.<cuerpo crudo>")en hexadecimal. Verifiquen la firma y rechacentcon más de 5 minutos de diferencia. - Respondan
2xxen menos de 10 segundos. Si no, se reintenta con espera creciente durante 24 horas. Pueden llegar repetidos: usendata.id. - Otros eventos:
listing.moderated(conexternal_idyreason).
6.2 Consulta periódica (respaldo)
GET /leads?since=2026-09-17T00:00:00.000Z&limit=100&cursor=…
Devuelve las consultas creadas desde since, en orden ascendente, con la
misma forma que data del webhook, más has_more y next_cursor.
6.3 Tiempo de respuesta
Cuando el agente responde al interesado (correo, llamada, WhatsApp), el integrador lo informa una vez:
POST /leads/{id}/events
{ "type": "first_response", "occurred_at": "2026-09-17T14:31:00.000Z", "channel": "whatsapp" }
channel:email·phone·whatsapp·other.- Si ya estaba informado, responde
200sin cambiar la fecha original.
ConnectorProperty muestra en la ficha el tiempo de respuesta típico del agente: la mediana de los últimos 90 días, con al menos 3 consultas. Las consultas sin respuesta después de 72 horas cuentan como 72 horas. Con menos de 3 consultas se muestra "Nuevo en ConnectorProperty".
Sugerencia para CRMs: informen first_response cuando la consulta pasa de
"nueva" a "contactada".
7. Límites
- 600 peticiones por minuto por llave. Al superarlo:
429con cabeceraRetry-After(segundos). - Tamaño máximo del cuerpo: 1 MB.
- Ante
429o5xx, reintenten con espera creciente (1 s, 2 s, 4 s…).
8. Errores
Todos los errores tienen la misma forma:
{
"error": {
"code": "validation_failed",
"message": "La propiedad tiene 2 errores.",
"details": [
{ "field": "common_expenses_clp", "code": "required", "message": "Obligatorio para departamentos (usa 0 si no tiene)." },
{ "field": "location.commune", "code": "unknown_commune", "message": "Comuna desconocida: \"Provdencia\". ¿Quisiste decir \"Providencia\"?" }
]
}
}
| HTTP | code |
Cuándo |
|---|---|---|
| 400 | invalid_json |
El cuerpo no es JSON válido. |
| 400 | invalid_parameter |
Parámetro de consulta inválido (limit, cursor, since, reason). |
| 401 | unauthorized |
Falta la llave, es inválida o fue revocada. |
| 404 | not_found |
El recurso no existe para este integrador y ambiente. |
| 409 | publisher_not_found |
publisher_external_id no existe. |
| 409 | agent_not_found |
agent_external_id no existe o es de otra corredora. |
| 413 | payload_too_large |
Cuerpo de más de 1 MB. |
| 422 | validation_failed |
Uno o más campos no cumplen. Detalle en details. |
| 429 | rate_limited |
Ver sección 7. |
| 5xx | — | Error de ConnectorProperty: reintentar con espera. |
9. Ejemplo con curl
export CP_API_KEY="cp_test_…"
BASE=https://connectorproperty.com/api/v1
curl -s -X PUT "$BASE/publishers/focolare" \
-H "Authorization: Bearer $CP_API_KEY" -H "Content-Type: application/json" \
-d '{"kind":"agency","name":"Focolare Propiedades","legal_name":"Focolare Propiedades SpA","rut":"77.123.456-7"}'
curl -s -X PUT "$BASE/listings/NX-00012" \
-H "Authorization: Bearer $CP_API_KEY" -H "Content-Type: application/json" \
-d @propiedad.json
curl -s -X DELETE "$BASE/listings/NX-00012?reason=closed" \
-H "Authorization: Bearer $CP_API_KEY"
10. Próximamente
- Feed XML en formato LIFULL/Trovit, para CRMs que ya lo generan y no quieren integrar la API: ConnectorProperty lo leerá periódicamente.