Ir al contenido

SDK

Avanzado

@linkerestate/sdk es el paquete que consumen los sitios externos: micrositios de proyecto, landings de campaña, el portal corporativo.

  • npm: @linkerestate/sdk (público)
  • Sin dependencias de ejecución, ESM, Node ≥ 18
Ventana de terminal
pnpm add @linkerestate/sdk

La separación por subpath es la frontera de seguridad: cada entrada exige una llave distinta, y las de servidor no pueden llegar al navegador porque el sitio nunca las importa desde código de cliente.

Subpath Para qué Scope ¿Pública?
@linkerestate/sdk/client Rotación: leer el turno y registrar el clic de WaTel campaign_rr Sí
@linkerestate/sdk/server Publicar un prospecto campaign_leads No, nunca
@linkerestate/sdk/catalog Propiedades y asesores api_v1 No
import { createRoundRobinClient } from "@linkerestate/sdk/client"
const rotation = createRoundRobinClient({
campaignId: RR_ID,
apiKey: RR_API_KEY, // campaign_rr
source: RR_WEBHOOK_KEY, // opcional: atribuye el clic a esa fuente
})
// Botones de WaTel (WhatsApp y llamada), con el asesor de turno
const turn = await rotation.peek() // { waUrl, telUrl, phone } | null
// Ficha del asesor que atenderá el formulario
const lead = await rotation.peekLeadForm() // { leadFormAgentId, agent } | null
// Registra el clic sin bloquear la navegación (sendBeacon). Devuelve un limpiador.
const detach = rotation.attachCommitHandlers()

attachCommitHandlers() engancha [id^="wa-btn"], [data-rr-link="whatsapp"] y [id^="tel-btn"], [data-rr-link="tel"], una sola vez por elemento. Cada clic así enganchado es un turno de WaTel; el carril del formulario no se toca.

import { createCatalogClient } from "@linkerestate/sdk/catalog"
const catalog = createCatalogClient({ apiKey: process.env.LINKER_API_KEY })
const { data, meta } = await catalog.properties({ city: "Punta Cana", page: 1 })
const one = await catalog.property("luxury-beachfront-villa-punta-cana")

Las lecturas del catálogo son cacheables. La rotación no: peek() tiene que reflejar el turno vivo, así que va sin caché.