Introducción

La Partner API del Performance Hub permite que las plataformas de socios externas se integren sin problemas con los módulos principales del Performance Hub. La API admite visión artificial, análisis, registro del acceso de los miembros e información sobre las instalaciones.

Formato de las solicitudes

La API acepta cuerpos de solicitud codificados en JSON y devuelve respuestas codificadas en JSON.

Limitación de frecuencia

Para garantizar un uso justo y la estabilidad del sistema, las cuentas de la Partner API empiezan con estos límites predeterminados:

  • 5 solicitudes por segundo por endpoint
  • Recomendado: 1000 elementos como máximo por solicitud por lotes para un rendimiento óptimo
  • 10MB como máximo de tamaño de la carga útil

Los límites de frecuencia se pueden ajustar y tu administrador de cuenta de socio del Performance Hub puede configurarlos caso por caso. Si tu integración necesita más rendimiento para el lanzamiento, las migraciones, las cargas retroactivas de informes o las instalaciones de gran volumen, plantéalo durante la incorporación o antes de la ventana de cambio prevista.

URL base

https://partner-api.performancehub.co/partner/v1/

Autenticación

Para acceder a la Partner API, es necesario autenticarse con claves secretas de API. Genera y administra tus claves desde la Partner Console.

Las claves de API son tus credenciales para acceder a los recursos de socios. Cada clave tiene acceso restringido a datos específicos de la organización y se puede desactivar al instante cuando sea necesario.

Trata tus claves de API con cuidado: ¡proporcionan acceso completo a tu cuenta! Nunca expongas estas claves en repositorios públicos, aplicaciones del lado del cliente ni en ningún lugar donde puedan quedar comprometidas.

Autentica las solicitudes con HTTP Basic Auth y pasa tu clave de API como nombre de usuario. Deja la contraseña vacía.

La API solo acepta conexiones HTTPS seguras. Se rechazan las solicitudes HTTP sin cifrar, al igual que cualquier solicitud que no incluya credenciales de autenticación válidas.

Solicitud de ejemplo

curl https://partner-api.performancehub.co/partner/v1/organisations \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:
# The colon prevents curl from asking for a password.

Verificar la clave secreta

curl https://partner-api.performancehub.co/partner/v1/auth/ping \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:
# Returns { "message": "You are successfully authorised as <PartnerName>" }

Lista de comprobación para la puesta en producción

Usa esta lista de comprobación antes de habilitar una integración de socio para instalaciones en producción.

Configuración de la Partner Console

  • Tu perfil de socio está completo.
  • La URL del logotipo, el sitio web, la categoría y la descripción son correctos.
  • El método de vinculación de datos está configurado: Direct Link o Linking Identifier.
  • La vinculación de instalaciones se probó con al menos una instalación real.
  • Se usa el tipo de clave adecuado:
    • Dryrun para pruebas de escritura no destructivas.
    • Read-only para consumir datos de forma segura.
    • Live solo cuando estés listo para afectar los datos de producción.

Autenticación y administración de claves

  • Las claves secretas se guardan solo en el servidor.
  • Las claves no están incrustadas en aplicaciones del lado del cliente, aplicaciones móviles, repositorios públicos ni tickets de soporte.
  • Se probaron la rotación y la revocación de claves.
  • Tu equipo sabe qué clave usa cada entorno.

Validación de datos

  • Los campos obligatorios están presentes en cada endpoint al que llamas.
  • Los identificadores de instalación coinciden con el método de vinculación configurado.
  • Los ID de tu sistema son estables y no cambian entre sincronizaciones.
  • Las importaciones grandes se dividen en lotes que respetan los límites documentados.
  • Los elementos de lote fallidos se pueden identificar y volver a enviar.

Pruebas de endpoints

Antes del lanzamiento, prueba todos los endpoints de los que depende tu integración:

  • Se pueden leer las organizaciones y las instalaciones.
  • Se pueden guardar y actualizar miembros.
  • Los planes de membresía, las zonas de acceso y los horarios de acceso se sincronizan correctamente.
  • Los registros de entrada se aceptan y se pueden relacionar con tu sistema.
  • Las instantáneas de informes usan el período de informe y las métricas previstos.
  • Los flujos del controlador de puertas y portones se prueban con hardware real, cuando corresponde.

Preparación de Access Time Windows

Si la integración proporciona Access Time Windows:

  • Los ejemplos absolutos y semanales superan la lista de comprobación de certificación del productor.
  • Las épocas son segundos Unix enteros sin comillas; se probaron los límites exactos [from, to).
  • Se verificaron los valores predeterminados en UTC, las zonas horarias IANA personalizadas de la integración y los cambios de horario de verano pertinentes.
  • Una única secuencia de revisiones duradera y monótona por miembro y fuente coordina las actualizaciones incrementales, la conciliación y los reintentos.
  • Los operadores entienden el comportamiento de los valores omitidos, el reemplazo completo, las repeticiones idempotentes, los conflictos, los datos obsoletos y el [] explícito.
  • Cada scope_key, incluido default, tiene una asignación aprobada en el Performance Hub; se probó que las claves desconocidas deniegan el acceso.
  • Están configurados la frecuencia de actualización prevista de la integración, la antigüedad máxima de la fuente, el comportamiento ante fuentes obsoletas y las alertas.
  • Se comprobó que un error en la consulta a la fuente de origen no emite una instantánea vacía ni parcial.
  • La convergencia de la secuencia en el entorno de pruebas, la cancelación o revocación y los límites de inicio y fin en las puertas físicas cumplen los objetivos acordados.
  • Se verificaron las reglas habituales y los permisos permanentes como vías alternativas, y las ventanas no pueden omitir la desactivación del usuario, blockAllAccess, el mantenimiento ni la geovalla.

Preparación del control de acceso

En las integraciones de control de acceso:

  • Tu sistema toma la decisión de acceso antes de llamar al Performance Hub.
  • La integración gestiona device_offline, maintenance_mode_active y unlock_confirmation_timeout.
  • Los operadores entienden que un tiempo de espera agotado significa que el desbloqueo no se confirmó.
  • Tus registros guardan el event_id y el command_id devueltos.
  • Tienes un proceso alternativo manual para el personal de la instalación.

Gestión de errores y reintentos

  • Las respuestas 400, 401, 403, 404, 409 y 422 se muestran a los operadores o a los equipos de soporte en lugar de reintentarse a ciegas.
  • Las respuestas 429, 500, 502, 503 y 504 usan una lógica de reintento acotada con retroceso.
  • Los errores repetidos generan una alerta en tu sistema.
  • La integración nunca descarta registros fallidos de forma silenciosa.

Observabilidad

  • Tus registros incluyen el endpoint, la marca de tiempo, el identificador de instalación, el ID del registro de origen, el resultado de la solicitud y el cuerpo de la respuesta.
  • Tu equipo de soporte puede buscar por ID de miembro, ID de instalación, ID de registro de entrada o ID de evento de desbloqueo.
  • Tienes una forma de repetir o conciliar las sincronizaciones fallidas.

Lanzamiento en producción

  • El Performance Hub confirmó tu acceso a producción.
  • Al menos una instalación de producción habilitó tu integración.
  • Tu clave de producción está activa.
  • Tus contactos operativos y técnicos están actualizados.
  • Tu proceso de soporte está documentado para los clientes.

Una vez completadas estas comprobaciones, tu integración configurada aparecerá en el directorio de socios del Performance Hub, dentro de la plataforma principal del Performance Hub.

Prácticas recomendadas

Usa estos patrones para que las integraciones de socios sean predecibles, observables y seguras para las instalaciones.

Identifica las instalaciones de forma coherente

Elige el método de vinculación configurado para tu cuenta de socio y úsalo de forma coherente:

  • Direct Link: usa el facility_id del Performance Hub que devuelve el endpoint de instalaciones.
  • Linking Identifier: usa tu propio identificador de ubicación, como un ID de sucursal, un código de ubicación o un número de tienda.

No envíes ambos identificadores en la misma solicitud. El Performance Hub resuelve las solicitudes con el método de vinculación configurado para tu cuenta de socio.

Consulta Métodos de vinculación de socios para obtener instrucciones de configuración.

Escribe por lotes con cuidado

La Partner API acepta cuerpos de solicitud JSON y está diseñada para flujos de sincronización por lotes, donde así se documenta. Mantén los lotes acotados y reintentables.

Pautas predeterminadas:

  • Usa hasta 1000 elementos por solicitud por lotes para un rendimiento óptimo.
  • Mantén las cargas útiles por debajo de 10MB.
  • No superes 5 solicitudes por segundo por endpoint.

Los límites de frecuencia se pueden ajustar y tu administrador de cuenta de socio del Performance Hub puede configurarlos caso por caso. Si prevés importaciones de gran volumen, tráfico de lanzamiento o cargas retroactivas de informes, acuerda el rendimiento necesario antes de la ventana de cambio.

Si necesitas sincronizar un conjunto de datos grande, divídelo en fragmentos deterministas y registra el ID de cada fragmento en tu sistema. Así es más fácil analizar los reintentos fallidos.

Reintenta de forma segura

Usa el retroceso exponencial para los errores transitorios, como 429, 500, 502, 503 y 504.

Evita los bucles de reintento rápidos. Un buen punto de partida es:

  1. Reintentar después de 1 segundo.
  2. Reintentar después de 2 segundos.
  3. Reintentar después de 4 segundos.
  4. Detenerse y emitir una alerta si la operación sigue fallando.

En los errores de validación, como 400 o 422, corrige la solicitud antes de reintentar.

Usa la idempotencia donde se admita

El endpoint de desbloqueo del controlador de puertas y portones admite una idempotency_key opcional. Si reutilizas la misma clave para el mismo socio, la misma instalación y la misma puerta, se devuelve el resultado existente cuando hay uno disponible.

Usa una clave estable para la acción que se realiza, por ejemplo, un ID de registro de entrada o un ID de evento de acceso de tu sistema.

No supongas que todos los endpoints de escritura admiten la idempotencia, a menos que esté documentado para ese endpoint.

Mantén limpios los datos de origen

Envía valores estables y normalizados siempre que sea posible:

  • Usa ID coherentes de miembros, planes, instalaciones y registros de entrada de tu sistema de origen.
  • Usa marcas de tiempo ISO 8601 para las fechas y horas.
  • Envía los números de teléfono en formato internacional, si están disponibles.
  • Envía las monedas con los campos documentados para cada endpoint.
  • Evita sobrecargar los campos de texto libre con datos que corresponden a campos estructurados.

Diseña para sincronizaciones incrementales y completas

La mayoría de las integraciones de socios necesitan ambas:

  • Sincronizaciones incrementales para los cambios del día a día.
  • Sincronizaciones completas de conciliación para corregir eventos perdidos, importaciones históricas o desviaciones de datos.

Tu integración debe poder reenviar el estado actual de un miembro, un plan de membresía o una instantánea de informe sin depender de que una solicitud anterior se haya completado correctamente.

Publica las Access Time Windows de forma segura

Trata el valor access_time_windows de cada miembro como una instantánea completa con revisiones independientes:

  • Coordina una única secuencia de access_time_windows_revision monótonamente creciente entre los procesos incrementales y los de conciliación.
  • Reintenta una entrega incierta o transitoria con la misma revisión y la misma carga útil normalizada.
  • Omite access_time_windows cuando no lo estés actualizando.
  • Envía [] solo después de que una consulta correcta a la fuente autorizada demuestre que no queda ninguna ventana. Nunca conviertas un tiempo de espera agotado, un resultado parcial o un error de análisis de la fuente en una revocación.
  • Mantén estables external_id y scope_key, y certifica cada asignación de ámbito antes de pasar a producción.
  • Supervisa la antigüedad de la fuente con respecto a la política de actualización acordada para esa integración.

Consulta la guía oficial para productores de Access Time Windows para conocer las instantáneas completas, las zonas horarias, el horario de verano, la cancelación y los vectores de prueba.

Trata el control de acceso como algo crítico para la seguridad

En los desbloqueos de controladores de puertas y portones:

  • Tu sistema debe decidir si la persona puede entrar antes de llamar al Performance Hub.
  • El Performance Hub devuelve 200 solo después de que el controlador del sitio confirma que el relé se desbloqueó físicamente.
  • La mayoría de las confirmaciones se completan en 3-5 segundos.
  • Un tiempo de espera agotado es un desbloqueo fallido explícito, no un éxito en segundo plano.
  • Reintenta solo según tus propias reglas de acceso y seguridad.

Registra siempre el event_id y el command_id que devuelve el endpoint de desbloqueo.

Supervisa tu integración

Usa los registros de solicitudes de la Partner Console durante el desarrollo y el lanzamiento. En producción, mantén también tus propios registros con:

  • Marca de tiempo de la solicitud.
  • Endpoint.
  • ID del registro de origen.
  • Identificador de instalación.
  • Código de estado HTTP.
  • Cuerpo de la respuesta o mensaje de error del Performance Hub.

Estos campos agilizan mucho el soporte y la conciliación cuando un cliente pregunta qué ocurrió.

Organizaciones

Representa la entidad comercial de nivel superior que opera una o varias instalaciones integradas con la plataforma del Performance Hub.

Endpoints

GET /partner/v1/organisations - List all organisations

El objeto de organización

Atributos

  • org_id string obligatorio

    Identificador único de la organización.

  • name string obligatorio

    Nombre de la organización.

El objeto de organización

{
  "org_id": "00000000-0000-0000-0000-000000000050",
  "name": "Harbourside Group"
}

Enumerar todas las organizaciones

Devuelve una lista de las organizaciones a las que tiene acceso tu cuenta de socio.

Valor devuelto

Devuelve un objeto JSON con una propiedad data que contiene una matriz de objetos de organización.

Solicitud

curl https://partner-api.performancehub.co/partner/v1/organisations \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Respuesta

{
  "data": [
    {
      "org_id": "00000000-0000-0000-0000-000000000050",
      "name": "Harbourside Group"
    },
    {
      "org_id": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
      "name": "Wellness Studios Network"
    }
  ]
}

Instalaciones

Representa una ubicación física, como una oficina, una tienda, un local, un campus, una clínica o un gimnasio, donde los miembros pueden acceder a servicios.

Endpoints

GET /partner/v1/facilities - List all facilities

El objeto de instalación

Atributos

  • facility_id string obligatorio

    Identificador único de la instalación.

  • org_id string obligatorio

    Identificador único de la organización principal.

  • name string obligatorio

    Nombre de la instalación.

  • brand string opcional

    Nombre de la marca que usa la instalación.

  • website_url string opcional

    URL del sitio web de la instalación.

  • place_data object opcional

    Datos de ubicación de la Google Places API que contienen el país, la dirección con formato, el Google Place ID, la provincia y la ciudad.

  • social_links object opcional

    Enlaces a las redes sociales de la instalación.

  • timezone string opcional

    Identificador de zona horaria IANA (por ejemplo, "Australia/Sydney" o "America/New_York").

El objeto de instalación

{
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "org_id": "00000000-0000-0000-0000-000000000050",
  "name": "Harbourside Central",
  "brand": "Harbourside",
  "website_url": "https://example.com/central",
  "social_links": {
    "instagram": {
      "handle": "@harbourside.central"
    },
    "facebook": {
      "handle": "HarboursideCentral"
    }
  },
  "place_data": {
    "country": {
      "iso_code": "AU",
      "full_name": "Australia"
    },
    "formatted_address": "123 Main Street, Suite 100, Sydney NSW 2000, Australia",
    "google_place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
    "province": {
      "abbreviation": "NSW",
      "full_name": "New South Wales"
    },
    "city": {
      "short_name": "Sydney",
      "full_name": "Sydney"
    }
  },
  "timezone": "Australia/Sydney"
}

Enumerar todas las instalaciones

Devuelve una lista de las instalaciones a las que tiene acceso tu cuenta de socio.

Valor devuelto

Devuelve un objeto JSON con una propiedad data que contiene una matriz de objetos de instalación.

Solicitud

curl https://partner-api.performancehub.co/partner/v1/facilities \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Respuesta

{
  "data": [
    {
      "facility_id": "550e8400-e29b-41d4-a716-446655440000",
      "org_id": "00000000-0000-0000-0000-000000000050",
      "name": "Harbourside Central",
      "brand": "Harbourside",
      "website_url": "https://example.com/central",
      "place_data": {
        "country": {
          "iso_code": "AU",
          "full_name": "Australia"
        },
        "formatted_address": "123 Main Street, Sydney NSW 2000, Australia",
        "google_place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
        "province": {
          "abbreviation": "NSW",
          "full_name": "New South Wales"
        },
        "city": {
          "short_name": "Sydney",
          "full_name": "Sydney"
        }
      },
      "timezone": "Australia/Sydney"
    }
  ]
}

Planes de membresía

Define una oferta que se puede comprar a una organización o instalación, incluidos los servicios, los derechos, el horario y los precios.

Endpoints

POST /partner/v1/membership-plans - Save a membership plan

El objeto de plan de membresía

Atributos

  • membership_plan_id string obligatorio

    Identificador único del plan de membresía.

  • facility_id string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Identificador único de la instalación en el Performance Hub.

  • linking_identifier string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Valor del identificador único que el socio usa para cada ubicación (por ejemplo, "Branch ID", "Location Code" o "Store Number"). Más información

  • name string obligatorio

    Nombre legible del plan (por ejemplo, "Office tenant – business hours", "Student – term access", "Hotel guest" o "10 Class Pack").

  • billing_cycle string opcional

    Frecuencia de facturación. Uno de estos valores: weekly, fortnightly, monthly, annually o one_time.

  • price integer opcional

    Costo base en la unidad monetaria más pequeña (centavos para USD/AUD).

  • currency string opcional

    Código de moneda ISO 4217 (por ejemplo, "AUD" o "USD").

  • description string opcional

    Descripción comercial o interna opcional.

  • active_members integer opcional

    Número de miembros activos que usan este plan de membresía

  • is_recurring boolean opcional

    Indica si el plan se renueva automáticamente.

  • is_trial boolean opcional

    Indica si se trata de una oferta de prueba.

  • visible_to_public boolean opcional

    Indica si el plan está disponible para comprarse mediante autoservicio.

  • duration_days integer opcional

    Número de días durante los que es válido el plan de membresía.

  • access_zones array opcional

    Matriz de zonas de acceso incluidas en el plan de membresía. Cada zona puede definir sus propios horarios de acceso. Consulta Zonas de acceso para obtener más detalles.

  • class_limit integer opcional

    Número máximo de clases permitidas (null para ilimitadas).

El objeto de plan de membresía

Este ejemplo usa facility_id. En una integración con identificador de vinculación, envía "linking_identifier": "branch_downtown" en su lugar.

{
  "membership_plan_id": "plan_99999",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Office tenant – business hours",
  "description": "Weekday access to the level 3 tenancy and the end-of-trip facilities",
  "billing_cycle": "monthly",
  "price": 8900,
  "currency": "AUD",
  "duration_days": 30,
  "is_recurring": true,
  "is_trial": false,
  "visible_to_public": false,
  "active_members": 245,
  "access_zones": [
    {
      "name": "Level 3 Tenancy",
      "description": "Lift lobby, offices and meeting rooms on level 3",
      "access_hours": {
        "mon": [["07:00", "19:00"]],
        "tue": [["07:00", "19:00"]],
        "wed": [["07:00", "19:00"]],
        "thu": [["07:00", "19:00"]],
        "fri": [["07:00", "19:00"]]
      }
    },
    {
      "name": "End-of-trip Facilities",
      "description": "Bike storage, lockers and showers",
      "access_hours": {
        "mon": [["06:00", "20:00"]],
        "tue": [["06:00", "20:00"]],
        "wed": [["06:00", "20:00"]],
        "thu": [["06:00", "20:00"]],
        "fri": [["06:00", "20:00"]]
      }
    }
  ],
  "class_limit": null
}

Zonas de acceso

Las zonas de acceso definen áreas específicas dentro de una instalación a las que un plan de membresía concede acceso. Cada zona puede tener sus propios horarios de acceso, lo que permite aplicar restricciones horarias distintas a cada área.

Estructura

Cada zona de acceso incluye:

  • name string obligatorio

    El nombre de la zona (por ejemplo, "Level 3 Tenancy", "Library", "Guest Floors" o "Main Gym Floor").

  • description string opcional

    Descripción de lo que incluye esa zona.

  • access_hours object opcional

    Horarios de acceso específicos de esta zona. Consulta Horarios de acceso para ver el formato de las franjas horarias.

Ejemplo

Un edificio de oficinas con un gimnasio para sus inquilinos: acceso a las oficinas alquiladas en horario laboral y al gimnasio desde primera hora de la mañana hasta última hora de la noche.

{
  "access_zones": [
    {
      "name": "Level 3 Tenancy",
      "description": "Lift lobby, offices and meeting rooms on level 3",
      "access_hours": {
        "mon": [["07:00", "19:00"]],
        "tue": [["07:00", "19:00"]],
        "wed": [["07:00", "19:00"]],
        "thu": [["07:00", "19:00"]],
        "fri": [["07:00", "19:00"]]
      }
    },
    {
      "name": "Tenant Gym",
      "description": "Ground-floor gym and change rooms for building tenants",
      "access_hours": {
        "mon": [["05:00", "22:00"]],
        "tue": [["05:00", "22:00"]],
        "wed": [["05:00", "22:00"]],
        "thu": [["05:00", "22:00"]],
        "fri": [["05:00", "22:00"]],
        "sat": [["07:00", "18:00"]],
        "sun": [["07:00", "18:00"]]
      }
    }
  ]
}

Horarios de acceso

Los horarios de acceso especifican cuándo pueden acceder los miembros a una zona concreta cada día de la semana. Los horarios de acceso se definen por zona de acceso, lo que permite aplicar restricciones horarias distintas a diferentes áreas de una instalación.

Estructura

{
  "mon": [["start_time", "end_time"]],
  "tue": [["start_time", "end_time"]],
  "wed": [["start_time", "end_time"]],
  "thu": [["start_time", "end_time"]],
  "fri": [["start_time", "end_time"]],
  "sat": [["start_time", "end_time"]],
  "sun": [["start_time", "end_time"]]
}

Cada día es una matriz de franjas horarias en formato HH:MM (reloj de 24 horas). Una matriz vacía [] significa que no hay acceso ese día. Los días que se omiten se tratan igual que una matriz vacía.

Casos de uso de ejemplo

Inquilino de oficina – horario laboral: acceso en horario laboral solo los días de semana.

{
  "access_hours": {
    "mon": [["07:00", "19:00"]],
    "tue": [["07:00", "19:00"]],
    "wed": [["07:00", "19:00"]],
    "thu": [["07:00", "19:00"]],
    "fri": [["07:00", "19:00"]]
  }
}

Estudiante – acceso durante el período lectivo: una biblioteca del campus abierta los días de semana, con una pausa a mediodía, y los sábados por la mañana.

{
  "access_hours": {
    "mon": [["08:00", "12:30"], ["13:30", "21:00"]],
    "tue": [["08:00", "12:30"], ["13:30", "21:00"]],
    "wed": [["08:00", "12:30"], ["13:30", "21:00"]],
    "thu": [["08:00", "12:30"], ["13:30", "21:00"]],
    "fri": [["08:00", "12:30"], ["13:30", "17:00"]],
    "sat": [["09:00", "13:00"]]
  }
}

Gimnasio – madrugadores: acceso solo por la mañana los días de semana.

{
  "access_hours": {
    "mon": [["04:00", "12:00"]],
    "tue": [["04:00", "12:00"]],
    "wed": [["04:00", "12:00"]],
    "thu": [["04:00", "12:00"]],
    "fri": [["04:00", "12:00"]]
  }
}

Huésped de hotel – 24/7: acceso permanente, el caso de uso más habitual.

{
  "access_hours": {
    "mon": [["00:00", "23:59"]],
    "tue": [["00:00", "23:59"]],
    "wed": [["00:00", "23:59"]],
    "thu": [["00:00", "23:59"]],
    "fri": [["00:00", "23:59"]],
    "sat": [["00:00", "23:59"]],
    "sun": [["00:00", "23:59"]]
  }
}

Ejemplo por zona

Un plan para huéspedes de hotel con acceso las 24 horas a las plantas de huéspedes y un horario más reducido para la piscina:

{
  "access_zones": [
    {
      "name": "Guest Floors",
      "description": "Lifts and corridors on the guest room levels",
      "access_hours": {
        "mon": [["00:00", "23:59"]],
        "tue": [["00:00", "23:59"]],
        "wed": [["00:00", "23:59"]],
        "thu": [["00:00", "23:59"]],
        "fri": [["00:00", "23:59"]],
        "sat": [["00:00", "23:59"]],
        "sun": [["00:00", "23:59"]]
      }
    },
    {
      "name": "Swimming Pool",
      "description": "Access to the swimming pool and change rooms",
      "access_hours": {
        "mon": [["06:00", "20:00"]],
        "tue": [["06:00", "20:00"]],
        "wed": [["06:00", "20:00"]],
        "thu": [["06:00", "20:00"]],
        "fri": [["06:00", "20:00"]],
        "sat": [["08:00", "18:00"]],
        "sun": [["08:00", "18:00"]]
      }
    }
  ]
}

Guardar un plan de membresía

Crea o actualiza registros de planes de membresía. La API determina si debe crear o actualizar según el membership_plan_id.

Parámetros

  • membership_plans array obligatorio

    Matriz de objetos de plan de membresía que se van a guardar. Máximo recomendado: 1000 elementos por solicitud para un rendimiento óptimo. La API agrupa automáticamente los elementos en lotes para procesarlos. Cada elemento debe incluir facility_id (obligatorio si no se usa linking_identifier) o linking_identifier (obligatorio si no se usa facility_id).

Valor devuelto

Devuelve un mensaje sencillo que confirma la operación de sincronización.

Solicitud

Este ejemplo usa facility_id. En una integración con identificador de vinculación, envía "linking_identifier": "branch_downtown" en su lugar.

curl -X POST https://partner-api.performancehub.co/partner/v1/membership-plans \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "membership_plans": [
      {
        "membership_plan_id": "plan_99999",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "Student – term access",
        "description": "Library and student hub access for one teaching term",
        "billing_cycle": "one_time",
        "price": 4500,
        "currency": "AUD",
        "duration_days": 84,
        "is_recurring": false,
        "is_trial": false,
        "visible_to_public": true,
        "active_members": 245,
        "access_zones": [
          {
            "name": "Library",
            "description": "Reading rooms, study spaces and bookable rooms",
            "access_hours": {
              "mon": [["08:00", "21:00"]],
              "tue": [["08:00", "21:00"]],
              "wed": [["08:00", "21:00"]],
              "thu": [["08:00", "21:00"]],
              "fri": [["08:00", "17:00"]],
              "sat": [["09:00", "13:00"]]
            }
          },
          {
            "name": "Student Hub",
            "description": "Common room, kitchen and lockers",
            "access_hours": {
              "mon": [["07:00", "22:00"]],
              "tue": [["07:00", "22:00"]],
              "wed": [["07:00", "22:00"]],
              "thu": [["07:00", "22:00"]],
              "fri": [["07:00", "22:00"]]
            }
          }
        ],
        "class_limit": null
      }
    ]
  }'

Respuesta

Devuelve un mensaje de éxito con metadatos sobre la operación de sincronización.

{
  "message": "Membership plan sync successful.",
  "metadata": {
    "success": 98,
    "skipped": 2,
    "skipped_items": [
      {
        "membership_plan_id": "plan_456",
        "facility_id": null,
        "reason": "Missing facility_id"
      }
    ]
  }
}

Campos de metadatos:

  • success: número de planes de membresía procesados correctamente
  • skipped: número de planes omitidos (si los hay)
  • skipped_items: matriz de planes omitidos con los motivos (si los hay)
  • dry-run: indicador booleano si se usa el tipo de clave dryrun (si corresponde)

Miembros

Representa a un cliente individual de una instalación. Puede ser un cliente potencial, un prospecto, un cliente habitual, un miembro vencido o un usuario bloqueado.

Las operaciones de inserción o actualización de miembros también pueden incluir una instantánea access_time_windows completa y con revisiones, que contiene accesos absolutos y semanales recurrentes. Consulta Access Time Windows antes de generar estos campos. Son permisos adicionales y no reemplazan las reglas habituales ni los permisos permanentes de la instalación.

Endpoints

POST /partner/v1/members - Save a member

El objeto de miembro

Atributos

  • member_id string obligatorio

    Identificador único del miembro.

  • facility_id string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Identificador único de la instalación en el Performance Hub.

  • linking_identifier string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Valor del identificador único que el socio usa para cada ubicación (por ejemplo, "Branch ID", "Location Code" o "Store Number"). Más información

  • first_name string obligatorio

    Nombre del miembro.

  • last_name string obligatorio

    Apellido del miembro.

  • email string opcional

    Dirección de correo electrónico.

  • mobile_phone string opcional

    Número de teléfono móvil en formato E.123 (por ejemplo, "+1 415 555 2671").

  • address object opcional

    Objeto de dirección física con las siguientes propiedades:

    • address_line_1 (string): dirección principal
    • address_line_2 (string, opcional): línea de dirección secundaria
    • city (string): nombre de la ciudad
    • state (string): código del estado o la provincia
    • postal_code (string): código postal
    • country (string): código de país ISO 3166-1 alfa-2 (por ejemplo, "AU" o "US")
    • country_name (string, opcional): nombre completo del país
  • date_of_birth string opcional

    Fecha de nacimiento en formato YYYY-MM-DD.

  • gender string opcional

    Uno de estos valores: male, female, non_binary, prefer_not_to_say o unknown.

  • type string opcional

    Tipo de miembro (por ejemplo, staff, member o prospect).

  • tags array opcional

    Cadenas o textos auxiliares para clasificar e identificar rápidamente a miembros específicos (por ejemplo, ["vip", "personal-training", "student"]).

  • membership_status string opcional

    Estado actual de la membresía (por ejemplo, active, expired u on_hold).

  • membership_plans array opcional

    Matriz de planes de membresía asociados al miembro.

  • profile_picture string opcional

    Foto de perfil codificada en Base64 (opcional).

  • created string opcional

    Marca de tiempo ISO 8601 del momento en que se creó el miembro.

  • updated string opcional

    Marca de tiempo ISO 8601 de la última actualización del miembro.

  • access_time_windows array opcional

    Instantánea completa, perteneciente a la fuente, de las Access Time Windows absolutas o semanales recurrentes. Omite el campo para no modificar la instantánea; envía una matriz vacía con una revisión más reciente para revocarla. Consulta Access Time Windows para conocer las formas, la validación, la asignación de ámbitos y la semántica de reemplazo.

  • access_time_windows_revision integer obligatorio con access_time_windows

    Entero no negativo, monótonamente creciente y seguro para JSON, correspondiente a la secuencia de este miembro y esta fuente. Es obligatorio siempre que access_time_windows esté presente.

El objeto de miembro

{
  "member_id": "member_11111",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  // "linking_identifier": "branch_downtown",  // If using linking identifier
  "first_name": "John",
  "last_name": "Smith",
  "email": "john.smith@example.com",
  "mobile_phone": "+61 412 345 678",
  "date_of_birth": "1985-06-15",
  "gender": "male",
  "type": "member",
  "tags": ["vip", "personal-training"],
  "profile_picture": "/9j/4AAQSkZJRgABAQAAAQ...",
  "membership_status": "current",
  "created": "2024-01-15T10:30:00Z",
  "updated": "2024-01-20T14:45:00Z",
  "access_time_windows_revision": 1842,
  "access_time_windows": [
    {
      "external_id": "access-4b1782",
      "kind": "absolute",
      "from": 1792053000,
      "to": 1792058400,
      "timezone": "Australia/Perth",
      "scope_key": "after_hours_entry",
      "label": "Temporary site access"
    }
  ],
  "address": {
    "address_line_1": "456 Bourke Street",
    "address_line_2": "Apt 12",
    "city": "Melbourne",
    "state": "VIC",
    "postal_code": "3000",
    "country": "AU",
    "country_name": "Australia"
  },
  "membership_plans": [
    {
      "membership_plan_id": "plan_99999",
      "name": "Unlimited Monthly",
      "start_date": "2024-01-01T00:00:00Z",
      "status": "current",
      "is_current": true,
      "end_date": null
    }
  ]
}

Ventanas de tiempo de acceso

Las Access Time Windows permiten que un miembro de socio tenga acceso temporal o recurrente proporcionado por un sistema externo. Esta página es la guía oficial para productores de access_time_windows y access_time_windows_revision.

Las Access Time Windows son permisos adicionales que solo permiten. Una ventana activa puede permitir el acceso, pero una ventana inactiva, vencida, obsoleta o sin asignar no deniega el acceso que ya permite una regla habitual o un permiso permanente. La desactivación del usuario, el bloqueo explícito de puertas, el modo de mantenimiento, la geovalla, los límites de frecuencia y la disponibilidad del controlador siguen aplicándose.

Las implementaciones para sistemas de origen concretos son adaptadores independientes. Deben traducir sus datos de origen a este contrato independiente del proveedor sin cambiar el significado de sus campos.

Campos de la instantánea del miembro

  • access_time_windows array opcional

    La instantánea completa de Access Time Windows para este miembro y esta fuente del socio. Una instantánea puede combinar ventanas absolute y weekly. Omite el campo para no modificar la instantánea guardada; envía [] para revocar todas las ventanas que pertenecen a esta fuente.

  • access_time_windows_revision integer obligatorio con access_time_windows

    Un entero no negativo, monótonamente creciente y seguro para JSON, correspondiente a la secuencia de revisiones de este miembro y esta fuente. Es obligatorio siempre que access_time_windows esté presente y no puede superar 9007199254740991.

Cada instantánea acepta como máximo 50 ventanas. external_id, scope_key y label aceptan como máximo 120 caracteres. Las ventanas absolutas pueden abarcar como máximo 90 días. Un día semanal acepta como máximo ocho bloques que no se superpongan. Los datos no válidos se rechazan en lugar de truncarse o interpretarse.

Formas de las ventanas

Una ventana absoluta identifica un intervalo exacto:

Solicitud combinada completa

Esta solicitud reemplaza la instantánea anterior del miembro que pertenece a la fuente por una ventana absoluta y una semanal:

Reglas de hora y límites

from, to, active_from y active_until son segundos Unix como enteros JSON que identifican instantes UTC:

  • Envía un entero JSON sin comillas. Se rechazan las cadenas numéricas, los números de coma flotante, las cadenas RFC 3339 y los milisegundos Unix.
  • Todos los intervalos son semiabiertos: [from, to). El acceso puede empezar exactamente en from; deja de estar activo exactamente en to.
  • from debe ser menor que to. Cuando están presentes los dos límites semanales, active_from debe ser menor que active_until.
  • No obtengas las épocas a partir de una fecha y hora local sin zona horaria. Primero resuelve la hora de origen a un instante UTC, luego divide los milisegundos Unix entre 1000 y verifica que el resultado sea un entero.

Zonas horarias y horario de verano

timezone debe ser una zona horaria IANA válida, como UTC, Australia/Perth o America/New_York. Si se omite, el valor predeterminado es UTC.

  • Ventanas absolutas: from y to ya identifican instantes UTC exactos. timezone es solo un metadato de visualización y auditoría; cambiarlo nunca desplaza ninguno de los dos instantes.
  • Ventanas semanales: timezone define la hora local del reloj y las reglas de horario de verano que se usan para evaluar access_hours. No conviertas previamente los bloques semanales a UTC.
  • Cuando se adelanta la hora, una hora local que la zona horaria omite nunca ocurre.
  • Cuando se atrasa la hora, los dos instantes reales que tienen la hora local repetida coinciden con el bloque semanal.
  • active_from y active_until siguen siendo instantes UTC incluso cuando una ventana semanal usa una zona horaria distinta de UTC.

access_hours usa los valores en minúsculas de sun a sat. Cada valor es una matriz de pares [start, end] en formato HH:mm de 24 horas con ceros a la izquierda. Los bloques no pueden estar vacíos, deben estar ordenados y no pueden superponerse. end es exclusivo. Un bloque no puede cruzar la medianoche; divide un intervalo nocturno de origen en un bloque tardío el primer día y un bloque temprano el día siguiente.

ID estables y asignación de ámbitos

external_id debe ser estable durante toda la vida de una ventana lógica y único dentro de la instantánea del miembro. Mantenlo estable cuando cambien las horas o las etiquetas para que los operadores y los registros de auditoría puedan relacionar las revisiones. No lo reutilices para una ventana no relacionada.

scope_key es tu destino de acceso lógico estable. Su valor predeterminado es default. Un administrador de la instalación asigna cada clave permitida a destinos del Performance Hub que abarcan toda la instalación, una puerta o un Alcance de acceso:

Instantáneas completas y revisiones

Trata los dos campos como una partición con versiones independientes dentro de la inserción o actualización del miembro:

Entrada Resultado
Se omite access_time_windows La instantánea existente no cambia; no se requiere una revisión
Presente con una revisión más reciente Se reemplaza toda la instantánea guardada para este miembro y esta fuente
Misma revisión y misma carga útil normalizada Repetición idempotente; la instantánea no cambia
Misma revisión y carga útil normalizada diferente Conflicto; asigna una nueva revisión después de conciliar
Revisión anterior Se omite la instantánea obsoleta; no puede sobrescribir un estado más reciente
access_time_windows: [] con una revisión más reciente Revoca explícitamente todas las ventanas que pertenecen a la fuente

Una instantánea es completa, no un parche. Si la revisión 1842 tiene las ventanas A y B, la revisión 1843, que solo contiene B, elimina A.

Mantén una única secuencia de revisiones coordinada por socio y miembro entre los procesos de webhooks, el sondeo, las repeticiones y la conciliación completa. Es preferible usar una secuencia duradera de base de datos. Un valor en milisegundos Unix solo puede usarse como revisión cuando todos los procesos que escriben se coordinan y garantizan un orden estricto y valores únicos; es un valor de revisión, no un campo de época.

Conserva la solicitud y la revisión exactas hasta conocer la respuesta de la API. Después de un tiempo de espera agotado o un error transitorio, reintenta la misma instantánea normalizada con la misma revisión. No asignes una nueva revisión solo porque la entrega sea incierta.

Cancelación, vencimiento y errores de la fuente de origen

  • Cancelar una ventana: consulta correctamente el estado autorizado de la fuente, quita esa ventana y envía la instantánea completa restante con una revisión más reciente.
  • Cancelar todas las ventanas: envía access_time_windows: [] con una revisión más reciente.
  • Dejar que venza una ventana absoluta: deja de permitir el acceso en to; envía una conciliación posterior sin la entrada vencida para mantener limpias las instantáneas.
  • Finalizar una ventana semanal: quítala en una instantánea más reciente o usa active_until cuando la fuente tenga un instante de fin conocido.
  • La consulta a la fuente falla o está incompleta: no envíes [] ni publiques una instantánea parcial. Emite una alerta y reintenta la consulta. Convertir un error de la fuente de origen en una instantánea vacía supone una revocación de acceso no deseada.
  • La solicitud a la Partner API no supera la validación: corrige los datos y envía una revisión más reciente solo si cambia la instantánea normalizada. Reintenta los errores transitorios con la revisión original.

La actualización de la fuente se configura para cada integración según la frecuencia de entrega y de conciliación comprometida. Antes de la activación, acuerda la antigüedad máxima de la fuente, qué ocurre cuando se supera, los umbrales de alerta y si los operadores pueden aceptar basarse solo en los límites propios de cada ventana. Una ventana de una fuente obsoleta nunca se convierte en una regla de denegación; las reglas habituales y los permisos permanentes siguen siendo vías alternativas.

Algoritmo del productor

Usa este flujo de trabajo independiente del lenguaje en cada actualización de miembro:

Lista de comprobación de certificación

Completa estas comprobaciones en una instalación de pruebas con la asignación final de scope_key:

  • Se acepta una ventana absoluta sin zona horaria y se evalúa como UTC.
  • Una ventana absoluta con una zona IANA personalizada conserva los mismos instantes from/to.
  • Una ventana semanal con una zona IANA personalizada sigue la hora local del reloj en los cambios de adelanto y atraso de la hora.
  • Una instantánea combinada absoluta y semanal reemplaza por completo la instantánea anterior.
  • El acceso empieza exactamente en from y se detiene exactamente en to; los finales de los bloques semanales también son exclusivos.
  • Actualizar las horas con el mismo external_id y una revisión más reciente surte efecto.
  • Omitir access_time_windows modifica otros campos del miembro sin cambiar las ventanas.
  • Repetir la misma revisión y carga útil es idempotente.
  • La misma revisión con una carga útil diferente devuelve un conflicto y no cambia la instantánea.
  • Una revisión anterior recibida fuera de orden se notifica como obsoleta y no puede revertir el estado.
  • Un [] más reciente revoca las ventanas que pertenecen a la fuente; un error en la consulta a la fuente de origen no envía nada.
  • Un scope_key desconocido o sin asignar deniega el acceso y genera una advertencia visible para el operador.
  • Las alertas de antigüedad de la fuente y la política configurada para fuentes obsoletas funcionan con el umbral acordado.
  • Las vías de webhook y de conciliación completa convergen en la misma instantánea y el mismo orden de revisiones.
  • La entrega de la secuencia llega a Door & Gate Access dentro del objetivo acordado.
  • Una ventana activa puede permitir el acceso a la puerta física asignada, pero no puede omitir la desactivación del usuario, blockAllAccess, el mantenimiento ni la geovalla.
  • Antes, fuera y después de una ventana, las reglas habituales y los permisos permanentes siguen permitiendo el acceso a los usuarios que cumplen los requisitos.

Pautas relacionadas

{
  "external_id": "access-4b1782",
  "kind": "absolute",
  "from": 1792053000,
  "to": 1792058400,
  "timezone": "Australia/Perth",
  "scope_key": "after_hours_entry",
  "label": "Temporary site access"
}

Los campos obligatorios son external_id, kind, from y to. timezone, scope_key y label son opcionales.

Una ventana semanal identifica intervalos recurrentes según la hora local del reloj, opcionalmente acotados por instantes UTC:

{
  "external_id": "weekly-early-access",
  "kind": "weekly",
  "timezone": "America/New_York",
  "access_hours": {
    "sun": [],
    "mon": [["06:00", "08:30"]],
    "tue": [["06:00", "08:30"]],
    "wed": [["06:00", "08:30"]],
    "thu": [["06:00", "08:30"]],
    "fri": [["06:00", "08:30"]],
    "sat": []
  },
  "active_from": 1790812800,
  "active_until": 1796083200,
  "scope_key": "main_entry",
  "label": "Weekday early access"
}

Los campos obligatorios son external_id, kind y access_hours. timezone, active_from, active_until, scope_key y label son opcionales.

curl -X POST https://partner-api.performancehub.co/partner/v1/members \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "members": [
      {
        "member_id": "member_11111",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        "first_name": "John",
        "last_name": "Smith",
        "access_time_windows_revision": 1842,
        "access_time_windows": [
          {
            "external_id": "access-4b1782",
            "kind": "absolute",
            "from": 1792053000,
            "to": 1792058400,
            "timezone": "Australia/Perth",
            "scope_key": "after_hours_entry",
            "label": "Temporary site access"
          },
          {
            "external_id": "weekly-early-access",
            "kind": "weekly",
            "timezone": "America/New_York",
            "access_hours": {
              "sun": [],
              "mon": [["06:00", "08:30"]],
              "tue": [["06:00", "08:30"]],
              "wed": [["06:00", "08:30"]],
              "thu": [["06:00", "08:30"]],
              "fri": [["06:00", "08:30"]],
              "sat": []
            },
            "active_from": 1790812800,
            "active_until": 1796083200,
            "scope_key": "main_entry",
            "label": "Weekday early access"
          }
        ]
      }
    ]
  }'

Usa facility_id o linking_identifier según el método de vinculación configurado. No envíes ambos.

Conversión de épocas

2026-10-15T08:30:00Z se convierte en 1792053000:

UTC instant                 Unix milliseconds   Unix seconds sent
2026-10-15T08:30:00Z        1792053000000        1792053000

Conversión independiente del lenguaje:

instant = parse_source_timestamp_with_explicit_zone(source_timestamp)
milliseconds = instant.to_unix_milliseconds()
assert milliseconds modulo 1000 equals 0
seconds = milliseconds / 1000
assert seconds is a JSON-safe nonnegative integer

Si la fuente tiene precisión inferior al segundo, define una política deliberada de redondeo del inicio y el fin antes de las pruebas de integración. Nunca pases milisegundos esperando que la API deduzca la unidad.

Partner scope_key           Performance Hub mapping
default                     Facility's configured default target
main_entry                  Access Scope "Main entrances"
after_hours_entry           Doors approved for after-hours entry

Los socios no envían ID de instalación, de puerta ni de Alcance de acceso del Performance Hub dentro de una ventana. Un scope_key desconocido, deshabilitado o sin asignar deniega el acceso para esa ventana; no amplía el acceso. Acuerda y prueba las asignaciones antes del lanzamiento.

function publish_member(member_key):
    source_result = fetch_authoritative_access_state(member_key)

    if source_result.failed or source_result.incomplete:
        record_failure(member_key)
        schedule_retry(member_key)
        return without sending access_time_windows

    windows = []
    for source_window in source_result.current_windows:
        if source_window.is_absolute:
            windows.append({
                external_id: stable_window_id(source_window),
                kind: "absolute",
                from: to_integer_unix_seconds(source_window.start_instant),
                to: to_integer_unix_seconds(source_window.end_instant),
                timezone: source_window.display_timezone or "UTC",
                scope_key: stable_scope_key(source_window) or "default",
                label: safe_label(source_window)
            })
        else:
            windows.append({
                external_id: stable_window_id(source_window),
                kind: "weekly",
                timezone: valid_iana_zone(source_window.timezone) or "UTC",
                access_hours: split_validate_and_sort_weekly_blocks(source_window),
                active_from: optional_integer_unix_seconds(source_window.active_start),
                active_until: optional_integer_unix_seconds(source_window.active_end),
                scope_key: stable_scope_key(source_window) or "default",
                label: safe_label(source_window)
            })

    normalized_snapshot = validate_sort_and_deduplicate(windows)
    revision = next_durable_member_revision(member_key)
    request = member_upsert_with(normalized_snapshot, revision)
    persist_for_retry(member_key, request)

    response = post_request(request)
    if response.is_transient_or_unknown:
        retry_exact_request_with_same_revision(request)
    else if response.is_revision_conflict:
        reconcile_with_latest_committed_source_state(member_key)
    else if response.is_stale_skip:
        stop_replaying_this_revision_and_reconcile(member_key)

Vectores de prueba mínimos

[
  {
    "name": "absolute-half-open",
    "window": {
      "external_id": "tv-absolute",
      "kind": "absolute",
      "from": 1792053000,
      "to": 1792058400
    },
    "expect": {
      "1792052999": "inactive",
      "1792053000": "active",
      "1792058399": "active",
      "1792058400": "inactive"
    }
  },
  {
    "name": "weekly-dst",
    "window": {
      "external_id": "tv-weekly-dst",
      "kind": "weekly",
      "timezone": "America/New_York",
      "access_hours": {
        "sun": [["01:00", "03:30"]],
        "mon": [],
        "tue": [],
        "wed": [],
        "thu": [],
        "fri": [],
        "sat": []
      }
    },
    "expect": "Evaluate local wall time: skipped times do not occur; both repeated 01:30 instants qualify."
  }
]

Envía también vectores negativos para milisegundos Unix, cadenas numéricas, números de coma flotante, zonas IANA no válidas, from >= to, external_id duplicados, bloques superpuestos, bloques nocturnos, más de ocho bloques en un día, más de 50 ventanas y claves de ámbito sin asignar.

Guardar un miembro

Crea o actualiza registros de miembros. La API determina si debe crear o actualizar según el member_id.

Parámetros

  • members array obligatorio

    Matriz de objetos de miembro que se van a guardar. Máximo recomendado: 1000 elementos por solicitud para un rendimiento óptimo. La API agrupa automáticamente los elementos en lotes para procesarlos. Cada elemento debe incluir facility_id (obligatorio si no se usa linking_identifier) o linking_identifier (obligatorio si no se usa facility_id).

    Cuando un miembro incluye access_time_windows, también debe incluir access_time_windows_revision. La matriz es una instantánea completa de la fuente, no un parche. Omítela para conservar la instantánea existente o envía [] con una revisión más reciente para revocar todas las ventanas que pertenecen a la fuente. Lee la guía de Access Time Windows antes de habilitar este campo.

Valor devuelto

Devuelve un mensaje sencillo que confirma la operación de sincronización.

Los campos del perfil del miembro siguen siendo inserciones o actualizaciones normales incluso cuando una instantánea de ventanas se notifica como repetición idempotente u omisión por obsoleta. Una instantánea en conflicto (misma revisión con una carga útil diferente) no se puede reintentar sin cambios; concilia el estado de la fuente y envía una revisión más reciente.

Solicitud

curl -X POST https://partner-api.performancehub.co/partner/v1/members \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "members": [
      {
        "member_id": "member_11111",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        // "linking_identifier": "branch_downtown",  // If using linking identifier
        "first_name": "John",
        "last_name": "Smith",
        "email": "john.smith@example.com",
        "mobile_phone": "+61 412 345 678",
        "date_of_birth": "1985-06-15",
        "gender": "male",
        "type": "member",
        "tags": ["vip", "personal-training"],
        "profile_picture": "/9j/4AAQSkZJRgABAQAAAQ...",
        "membership_status": "current",
        "created": "2024-01-15T10:30:00Z",
        "updated": "2024-01-20T14:45:00Z",
        "access_time_windows_revision": 1842,
        "access_time_windows": [
          {
            "external_id": "access-4b1782",
            "kind": "absolute",
            "from": 1792053000,
            "to": 1792058400,
            "timezone": "Australia/Perth",
            "scope_key": "after_hours_entry",
            "label": "Temporary site access"
          }
        ],
        "address": {
          "address_line_1": "456 Bourke Street",
          "address_line_2": "Apt 12",
          "city": "Melbourne",
          "state": "VIC",
          "postal_code": "3000",
          "country": "AU",
          "country_name": "Australia"
        },
        "membership_plans": [
          {
            "membership_plan_id": "plan_99999",
            "name": "Unlimited Monthly",
            "start_date": "2024-01-01T00:00:00Z",
            "status": "current",
            "is_current": true,
            "end_date": null
          }
        ]
      }
    ]
  }'

Respuesta

Devuelve un mensaje de éxito con metadatos sobre la operación de sincronización.

{
  "message": "Member sync successful.",
  "metadata": {
    "success": 245,
    "skipped": 5,
    "skipped_items": [
      {
        "member_id": "member_123",
        "facility_id": null,
        "reason": "Facility integration is disabled in facility-partner-config"
      }
    ]
  }
}

Campos de metadatos:

  • success: número de miembros procesados correctamente
  • skipped: número de miembros omitidos (si los hay)
  • skipped_items: matriz de miembros omitidos con los motivos (si los hay)
  • dry-run: indicador booleano si se usa el tipo de clave dryrun (si corresponde)

Registros de entrada

Representa el registro de la presencia de una persona en una instalación, una clase o una actividad. Se usa para hacer un seguimiento de la asistencia, analizar el uso y mejorar la precisión de la detección visual.

Endpoints

POST /partner/v1/check-ins - Save check-ins

El objeto de registro de entrada

Atributos

  • check_in_id string opcional

    Identificador único del registro de entrada. Opcional: si no se proporciona, se genera automáticamente a partir del par member_id y timestamp.

  • member_id string obligatorio

    Identificador único del miembro.

  • facility_id string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Identificador único de la instalación en el Performance Hub.

  • linking_identifier string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Valor del identificador único que el socio usa para cada ubicación (por ejemplo, "Branch ID", "Location Code" o "Store Number"). Más información

  • check_in_type string opcional

    Tipo de visita. Uno de estos valores: member, class, staff, guest o trial.

  • source string opcional

    Cómo se capturó el registro de entrada. Los valores habituales son manual, tag, rfid, kiosk y app. También se pueden usar otros valores, como door_reader o booking.

  • class_id string opcional

    Opcional. Se usa si el registro está vinculado a la reserva o la asistencia a una clase.

  • timestamp string obligatorio

    Marca de tiempo en formato ISO 8601 del momento en que se produjo el registro de entrada.

El objeto de registro de entrada

{
  // "check_in_id": "checkin_abc123",  // Optional - auto-generated from member_id + timestamp if not provided
  "member_id": "mem_12345",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  // "linking_identifier": "branch_downtown",  // If using linking identifier
  "check_in_type": "member",
  "source": "rfid",
  "timestamp": "2025-01-20T08:45:30Z"
}

Guardar registros de entrada

Crea registros de entrada. La API elimina automáticamente los duplicados según el miembro, la instalación y la marca de tiempo.

Parámetros

  • check_ins array obligatorio

    Matriz de objetos de registro de entrada que se van a guardar. Máximo recomendado: 1000 elementos por solicitud para un rendimiento óptimo. La API agrupa automáticamente los elementos en lotes para procesarlos. Cada elemento debe incluir facility_id (obligatorio si no se usa linking_identifier) o linking_identifier (obligatorio si no se usa facility_id).

Valor devuelto

Devuelve un mensaje sencillo que confirma la operación de sincronización.

Solicitud

curl -X POST https://partner-api.performancehub.co/partner/v1/check-ins \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "check_ins": [
      {
        // "check_in_id": "checkin_abc123",  // Optional - auto-generated from member_id + timestamp if not provided
        "member_id": "mem_12345",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        // "linking_identifier": "branch_downtown",  // If using linking identifier
        "check_in_type": "member",
        "source": "rfid",
        "timestamp": "2025-01-20T08:45:30Z"
      }
    ]
  }'

Respuesta

Devuelve un mensaje de éxito con metadatos sobre la operación de sincronización.

{
  "message": "Check-in sync successful.",
  "metadata": {
    "success": 523,
    "skipped": 3,
    "skipped_items": [
      {
        "member_id": "member_789",
        "facility_id": null,
        "reason": "No matching facility_id for the linking_identifier"
      }
    ]
  }
}

Campos de metadatos:

  • success: número de registros de entrada procesados correctamente
  • skipped: número de registros de entrada omitidos (si los hay)
  • skipped_items: matriz de registros de entrada omitidos con los motivos (si los hay)
  • dry-run: indicador booleano si se usa el tipo de clave dryrun (si corresponde)

Control de acceso

La Partner API puede activar el hardware del controlador de puertas y portones del Performance Hub en las instalaciones donde tu integración está habilitada.

Usa esta API cuando tu sistema de gestión de miembros ya haya decidido que una persona puede entrar. El Performance Hub no evalúa el estado de la membresía, los horarios de acceso, las reglas de zonas de puertas, las comprobaciones antifraude ni la lógica de suspensión. Tu sistema sigue siendo la autoridad para esas decisiones.

La solicitud de desbloqueo es síncrona. El Performance Hub envía el comando al controlador del sitio en tiempo real y devuelve 200 solo después de que el dispositivo confirma que el relé se desbloqueó físicamente. La mayoría de las confirmaciones deberían completarse en 3-5 segundos. Si no se recibe ninguna confirmación dentro del tiempo de espera, la API devuelve un error explícito.

También puedes registrar un intento de acceso o una denegación que nunca llegó al controlador. Esa llamada no desbloquea la puerta. Escribe un evento en los registros de acceso de Door & Gate Access.

Endpoints

GET /partner/v1/access-control/doors - List available Door/Gate Controllers
GET /partner/v1/access-control/doors/{door_id} - Get Door/Gate Controller status
POST /partner/v1/access-control/doors/{door_id}/unlock - Unlock a Door/Gate Controller
POST /partner/v1/access-control/doors/{door_id}/access-events - Record an access attempt or denial

El objeto de controlador de puertas y portones

Atributos

  • door_id string obligatorio

    Identificador único del controlador de puertas y portones. Guárdalo en tu sistema después de detectarlo y úsalo al llamar al endpoint de desbloqueo.

  • facility_id string obligatorio

    ID de instalación del Performance Hub.

  • linking_identifier string opcional

    Identificador de instalación del socio cuando tu integración usa identificadores de vinculación. Más información

  • name string obligatorio

    Nombre legible del dispositivo configurado en el Performance Hub.

  • zone string opcional

    Zona o ubicación de la puerta, como Entrance.

  • status string obligatorio

    online u offline.

  • relay_state string opcional

    Último estado conocido del relé, como locked o unlocked.

  • maintenance_mode string obligatorio

    Modo de mantenimiento actual. Uno de estos valores: off, force-open o force-closed.

  • hold_time_seconds integer obligatorio

    Tiempo de apertura predeterminado configurado para la puerta.

  • last_seen string opcional

    Marca de tiempo ISO de la actualización más reciente de los metadatos del dispositivo.

El objeto de controlador de puertas y portones

{
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "linking_identifier": "branch_downtown",
  "name": "Front Door",
  "zone": "Entrance",
  "status": "online",
  "online": true,
  "relay_state": "locked",
  "maintenance_mode": "off",
  "hold_time_seconds": 10,
  "last_seen": "2026-05-01T04:30:00.000Z"
}

Enumerar los controladores de puertas y portones

Devuelve los controladores de puertas y portones disponibles para tu integración.

Si no se proporciona facility_id ni linking_identifier, la API devuelve los controladores de puertas y portones de todas las instalaciones vinculadas a tu cuenta de socio.

Recommended: Include a facility identifier whenever possible. Requests without `facility_id` or `linking_identifier` may take longer to load for partners with hundreds or thousands of Door/Gate Controllers.

Parámetros

  • facility_id string opcional uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    ID de instalación del Performance Hub. Úsalo en las integraciones de vinculación directa.

  • linking_identifier string opcional uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Tu propio identificador de instalación o ubicación. Úsalo cuando tu integración esté configurada para usar identificadores de vinculación.

Valor devuelto

Devuelve una matriz de objetos de controlador de puertas y portones.

Solicitud

curl -X GET "https://partner-api.performancehub.co/partner/v1/access-control/doors?facility_id=550e8400-e29b-41d4-a716-446655440000" \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Respuesta

{
  "data": [
    {
      "door_id": "00000000000000000000000000000007",
      "facility_id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Front Door",
      "zone": "Entrance",
      "status": "online",
      "relay_state": "locked",
      "maintenance_mode": "off",
      "hold_time_seconds": 10,
      "last_seen": "2026-05-01T04:30:00.000Z"
    }
  ]
}

Obtener el estado de un controlador de puertas y portones

Recupera el último estado conocido y la configuración básica de un solo controlador de puertas y portones.

Proporciona un identificador de instalación para que el Performance Hub pueda verificar que la puerta pertenece a una instalación a la que tu integración tiene acceso.

Parámetros

  • door_id string obligatorio

    ID del controlador de puertas y portones que devuelve el endpoint de lista.

  • facility_id string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    ID de instalación del Performance Hub. Obligatorio en las integraciones de vinculación directa.

  • linking_identifier string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Identificador de instalación del socio. Obligatorio en las integraciones con identificador de vinculación.

Valor devuelto

Devuelve un objeto de controlador de puertas y portones.

Solicitud

curl -X GET "https://partner-api.performancehub.co/partner/v1/access-control/doors/00000000000000000000000000000007?facility_id=550e8400-e29b-41d4-a716-446655440000" \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Respuesta

{
  "data": {
    "door_id": "00000000000000000000000000000007",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Front Door",
    "zone": "Entrance",
    "status": "online",
    "relay_state": "locked",
    "maintenance_mode": "off",
    "hold_time_seconds": 10,
    "last_seen": "2026-05-01T04:30:00.000Z"
  }
}

Desbloquear un controlador de puertas y portones

Envía un comando de desbloqueo al controlador de puertas y portones y espera a que el relé físico confirme que se desbloqueó.

Tu sistema debe decidir si la persona está autorizada antes de llamar a este endpoint. El Performance Hub solo verifica la clave de socio, el acceso a la instalación, la pertenencia de la puerta y el estado del dispositivo.

Parámetros

  • door_id string obligatorio

    ID del controlador de puertas y portones que devuelve el endpoint de lista.

  • facility_id string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    ID de instalación del Performance Hub. Obligatorio en las integraciones de vinculación directa.

  • linking_identifier string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Identificador de instalación del socio. Obligatorio en las integraciones con identificador de vinculación.

  • member_id string obligatorio

    ID del miembro en el sistema del socio. Se usa para los registros de auditoría y para vincular datos más adelante.

  • first_name string obligatorio

    Nombre de la persona que abre la puerta.

  • last_name string obligatorio

    Apellido de la persona que abre la puerta.

  • full_name string opcional

    Opcional. Si se omite, el Performance Hub combina first_name y last_name.

  • check_in_id string opcional

    ID opcional del registro de entrada en tu sistema, para relacionar los datos.

  • idempotency_key string opcional

    Clave opcional de protección contra repeticiones. Si reutilizas la misma clave para el mismo socio, la misma instalación y la misma puerta, se devuelve el resultado existente cuando está disponible.

Valor devuelto

Devuelve 200 solo cuando el dispositivo confirma que el relé se desbloqueó físicamente. La puerta usa el tiempo de apertura configurado en Gestión de dispositivos del Performance Hub; los socios no pueden anular la temporización del relé en cada solicitud. La mayoría de las confirmaciones deberían completarse en 3-5 segundos. Trata el tiempo de espera documentado como un desbloqueo fallido explícito y reintenta solo según tus propias reglas de seguridad.

Errores comunes:

  • 403 integration_not_enabled: tu integración no está habilitada para la instalación.
  • 409 maintenance_mode_active: el personal de la instalación activó el modo de mantenimiento para la puerta.
  • 503 device_offline: el controlador de puertas y portones está desconectado o sus datos están desactualizados.
  • 504 unlock_confirmation_timeout: el comando se envió, pero no se recibió una confirmación correspondiente antes del tiempo de espera.

Solicitud

curl -X POST https://partner-api.performancehub.co/partner/v1/access-control/doors/00000000000000000000000000000007/unlock \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "member_id": "mem_12345",
    "first_name": "Jane",
    "last_name": "S.",
    "full_name": "Jane S.",
    "source": "door_reader",
    "idempotency_key": "unlock_20260501_0001"
  }'

Respuesta

{
  "status": "unlocked",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_id": "00000000-0000-0000-0000-000000000045",
  "command_id": "00000000-0000-0000-0000-000000000049",
  "hold_time_seconds": 10,
  "confirmed_at": "2026-05-01T04:30:00.000Z"
}

Respuesta de error

{
  "status": "failed",
  "reason": "device_offline",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_id": "00000000-0000-0000-0000-000000000045"
}

Registrar un intento de acceso o una denegación

Registra un intento de acceso o una denegación que tu sistema ya decidió. No se contacta con el controlador de puertas y portones y la puerta no se desbloquea.

Usa este endpoint cuando tu sistema rechace la entrada o cuando un intento deba aparecer en los registros de acceso de Door & Gate Access sin un desbloqueo. El Performance Hub no evalúa el estado de la membresía, los horarios de acceso ni otras reglas de acceso.

Un evento denegado aparece en los registros de acceso de Door & Gate Access con el resultado Denied, el nombre de tu empresa asociada, la puerta, el identificador del miembro si lo envías y el código de motivo en formato legible. Por ejemplo, membership_expired se muestra como "Membership Expired". reason_display_text y user_email se guardan con el evento.

Parámetros

  • door_id string obligatorio

    ID del controlador de puertas y portones que devuelve el endpoint de lista.

  • facility_id string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    ID de instalación del Performance Hub. Obligatorio en las integraciones de vinculación directa.

  • linking_identifier string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Identificador de instalación del socio. Obligatorio en las integraciones con identificador de vinculación.

  • outcome string obligatorio

    denied o attempted.

  • reason string opcional

    Código de motivo en snake_case y minúsculas, de hasta 64 caracteres. Obligatorio cuando outcome es denied. Ejemplo: membership_expired.

  • reason_display_text string opcional

    Motivo legible, de hasta 256 caracteres. Ejemplo: Membership expired on 2026-04-01.

  • member_id string opcional

    ID del miembro en el sistema del socio. Omítelo cuando la credencial no coincidió con ningún miembro, por ejemplo, una tarjeta desconocida.

  • user_email string opcional

    Correo electrónico de la persona que intentó acceder.

  • timestamp string opcional

    Momento en que ocurrió el intento, en formato ISO 8601 con zona horaria. Ejemplo: 2026-05-18T10:15:30Z. Si se omite, se usa la hora en que se recibe la solicitud. No puede estar más de 5 minutos en el futuro ni tener más de 30 días de antigüedad.

  • idempotency_key string opcional

    Clave de protección contra repeticiones, de hasta 128 caracteres. Si reutilizas la misma clave para el mismo socio, la misma instalación y la misma puerta, se devuelve el resultado original.

Valor devuelto

Devuelve 201 cuando se registra el evento. Si repites la misma idempotency_key, se devuelve 200 con idempotent establecido en true y no se crea otro evento.

Una clave de prueba (dry-run) devuelve 200 con dry_run establecido en true. No se registra nada.

Errores comunes:

  • 400: el cuerpo no es válido, una denegación no tiene reason, la marca de tiempo está fuera del rango o facility_id / linking_identifier no coincide con una instalación vinculada.
  • 403: la clave es de solo lectura.
  • 403 integration_not_enabled: tu integración no está habilitada para la instalación. message indica el motivo.
  • 404: no se encontró el controlador de puertas y portones en la instalación vinculada.

Solicitud

curl -X POST https://partner-api.performancehub.co/partner/v1/access-control/doors/00000000000000000000000000000007/access-events \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "outcome": "denied",
    "reason": "membership_expired",
    "reason_display_text": "Membership expired on 2026-04-01",
    "member_id": "mem_12345",
    "user_email": "member@example.com",
    "timestamp": "2026-05-18T10:15:30Z",
    "idempotency_key": "evt_abc12345"
  }'

Respuesta

{
  "status": "recorded",
  "event_id": "00000000-0000-0000-0000-000000000045",
  "outcome": "denied",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-05-18T10:15:30.000Z"
}

Repetición idempotente

{
  "status": "recorded",
  "event_id": "00000000-0000-0000-0000-000000000045",
  "outcome": "denied",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-05-18T10:15:30.000Z",
  "idempotent": true
}

Informes de las instalaciones

Un registro en un momento dado que recoge las métricas operativas y financieras clave de una instalación durante un período específico.

Endpoints

POST /partner/v1/report-snapshots - Save report snapshots

El objeto de instantánea de informe

Atributos

  • facility_id string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Identificador único de la instalación en el Performance Hub.

  • linking_identifier string uno u otroIndica el tipo de identificador de instalación configurado para tu integración: usa facility_id en las integraciones de vinculación directa o linking_identifier en las integraciones con identificador de vinculación. No envíes ambos; la API usa el tipo de identificador configurado para tu cuenta de socio e ignora el otro. Más información

    Valor del identificador único que el socio usa para cada ubicación (por ejemplo, "Branch ID", "Location Code" o "Store Number"). Más información

  • start_date string obligatorio

    Fecha de inicio del período de la instantánea en formato YYYY-MM-DD.

  • end_date string obligatorio

    Fecha de finalización del período de la instantánea en formato YYYY-MM-DD.

  • metrics object obligatorio

    Objeto de métricas que contiene los datos de miembros e ingresos del período.

El objeto de instantánea de informe

{
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  // "linking_identifier": "branch_downtown",  // If using linking identifier
  "start_date": "2025-01-01",
  "end_date": "2025-01-31",
  "metrics": {
    "members": {
      "active": 1200,
      "new": 45,
      "cancelled": 12
    },
    "revenue": {
      "total_payments": 289000.00,
      "total_payments_count": 1200,
      "currency": "AUD"
    }
  }
}

Guardar instantáneas de informes

Envía las métricas operativas y financieras de una instalación durante un período específico.

Parámetros

  • snapshots array obligatorio

    Matriz de objetos de instantánea de informe que se van a guardar. Máximo de 25 elementos por solicitud. Cada elemento debe incluir facility_id (obligatorio si no se usa linking_identifier) o linking_identifier (obligatorio si no se usa facility_id).

Valor devuelto

Devuelve un mensaje sencillo que confirma la operación de sincronización.

Solicitud

curl -X POST https://partner-api.performancehub.co/partner/v1/report-snapshots \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "snapshots": [
      {
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        // "linking_identifier": "branch_downtown",  // If using linking identifier
        "start_date": "2025-01-01",
        "end_date": "2025-01-31",
        "metrics": {
          "members": {
            "active": 1200,
            "new": 45,
            "cancelled": 12
          },
          "revenue": {
            "total_payments": 289000.00,
            "currency": "AUD"
          }
        }
      }
    ]
  }'

Respuesta

{
  "message": "Report snapshot sync successful."
}

Errores

La Partner API usa códigos de estado HTTP estándar y cuerpos de respuesta JSON para explicar por qué falló una solicitud.

Estructura de las respuestas de error

La mayoría de los errores de la API devuelven un cuerpo JSON con un mensaje y, cuando están disponibles, detalles estructurados.

Códigos de estado

Errores de Access Time Windows

La validación de las ventanas falla antes de que se escriba la instantánea no válida. Las causas habituales que no admiten reintento son:

  • Falta access_time_windows_revision cuando access_time_windows está presente.
  • Valores de época como cadena, de coma flotante o que probablemente estén en milisegundos.
  • Una zona horaria IANA no válida, un intervalo invertido, un external_id duplicado, bloques semanales superpuestos o un bloque nocturno que no se dividió.
  • Un valor fuera de los límites documentados de cantidad, longitud o duración.

Una revisión repetida con contenido normalizado diferente genera un 409 Conflict. Concilia con el último estado autorizado y asigna una revisión más reciente; no sigas reintentando el par en conflicto. Una revisión anterior se notifica como una instantánea omitida por obsoleta, en lugar de permitir que sobrescriba un estado más reciente. Un scope_key desconocido o sin asignar deniega la autorización y debe tratarse como una alerta de configuración.

Si se agota el tiempo de espera de la entrega o se recibe un 5xx transitorio, reintenta exactamente la misma instantánea normalizada con la misma revisión. Si falló la consulta a la fuente de origen, omite por completo el campo de ventanas; nunca lo sustituyas por una matriz vacía.

Pautas de reintento

Reintenta estos errores con un retroceso exponencial acotado:

  • 429
  • 500
  • 502
  • 503
  • 504

No reintentes estos errores a ciegas:

  • 400
  • 401
  • 403
  • 404
  • 409
  • 422

En el control de acceso, trata siempre las respuestas de tiempo de espera agotado y de dispositivo desconectado como desbloqueos fallidos, a menos que tus propias reglas de acceso y procesos de seguridad indiquen lo contrario.

Datos que debes incluir al solicitar soporte

Cuando te comuniques con soporte, incluye:

  • Endpoint y método HTTP.
  • Marca de tiempo y zona horaria.
  • ID de la clave de socio, no la clave secreta.
  • Identificador de instalación usado.
  • ID del registro de origen en tu sistema.
  • Estado y cuerpo de la respuesta.
  • event_id o command_id, si están disponibles.
{
  "success": false,
  "message": "Request body.members[0].member_id is required"
}

Algunos endpoints específicos de un dominio devuelven un estado y un motivo explícitos. Por ejemplo, los errores de control de acceso incluyen campos como reason, door_id, facility_id y event_id.

{
  "status": "failed",
  "reason": "device_offline",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_id": "00000000-0000-0000-0000-000000000045"
}

400 Bad Request

La solicitud tiene un formato incorrecto o le faltan campos obligatorios. Corrige la solicitud antes de reintentar.

401 Unauthorized

Falló la autenticación. Comprueba que usas HTTP Basic Auth con tu clave secreta de API como nombre de usuario y una contraseña vacía.

403 Forbidden

La clave es válida, pero la operación no está permitida. Las causas habituales son usar una clave de solo lectura para una operación de escritura o intentar acceder a una instalación donde tu integración no está habilitada.

404 Not Found

No se encontró el recurso solicitado o no está disponible para tu integración.

409 Conflict

La solicitud entra en conflicto con el estado actual del recurso. En el control de acceso, puede deberse, por ejemplo, a que un controlador de puertas y portones está en modo de mantenimiento.

422 Unprocessable Entity

La solicitud es un JSON válido, pero no supera la validación semántica. Corrige los datos antes de reintentar.

429 Too Many Requests

La integración superó el límite de frecuencia documentado. Reintenta con retroceso exponencial.

500 Internal Server Error

El Performance Hub no pudo completar la solicitud debido a un error interno. Reintenta con retroceso. Si el problema continúa, comunícate con soporte e indica el endpoint, la marca de tiempo y el cuerpo de la respuesta.

503 Service Unavailable

Un servicio o dispositivo del que depende la operación no está disponible. En los desbloqueos de controladores de puertas y portones, puede significar que el controlador está desconectado.

504 Gateway Timeout

Se agotó el tiempo de espera de la operación. En los desbloqueos de controladores de puertas y portones, significa que el desbloqueo no se confirmó antes de que terminara el tiempo de espera.

Control de versiones

La versión de la Partner API se indica en la URL. La versión actual es:

Política de cambios

El Performance Hub procura hacer cambios aditivos y compatibles con versiones anteriores siempre que sea posible.

Ejemplos de cambios compatibles con versiones anteriores:

  • Agregar un nuevo campo opcional a una solicitud.
  • Agregar un nuevo campo a una respuesta.
  • Agregar un nuevo endpoint.
  • Agregar un nuevo valor de enumeración cuando se espera que los clientes gestionen valores desconocidos.
  • Mejorar los mensajes de validación sin cambiar el contrato de códigos de estado.

access_time_windows y access_time_windows_revision son campos adicionales de la solicitud de miembros. Los clientes existentes que los omiten mantienen sin cambios la instantánea guardada de Access Time Windows. Esta regla de omisión preserva la compatibilidad con las inserciones o actualizaciones parciales; omitirlos no equivale a enviar una matriz vacía.

Ejemplos de cambios incompatibles:

  • Eliminar o cambiar el nombre de un campo.
  • Cambiar el tipo de un campo.
  • Hacer obligatorio un campo de solicitud opcional.
  • Eliminar un endpoint.
  • Cambiar el significado de un código de estado existente o de un reason específico de un dominio.

Elementos obsoletos

Cuando sea necesario un cambio incompatible, el Performance Hub evitará, siempre que sea posible, modificar la versión existente. En su lugar, introduciremos una nueva versión o una ruta de migración y comunicaremos el cambio a los socios afectados.

Los avisos de obsolescencia pueden incluir:

  • Una entrada en el registro de cambios.
  • Una comunicación directa con los socios.
  • Notas en la Partner Console.
  • Pautas de migración en la documentación.

Recomendaciones para los clientes

Crea clientes que toleren los cambios aditivos:

  • Ignora los campos de respuesta que no uses.
  • Trata los valores de enumeración desconocidos como no admitidos en lugar de provocar un error.
  • Evita las comprobaciones estrictas de igualdad de las respuestas.
  • Registra los valores no reconocidos para poder actualizar tu integración de forma deliberada.

En las particiones de miembros con revisiones, como Access Time Windows, conserva la revisión enviada y la carga útil normalizada hasta conocer el resultado. Reutilizar una revisión con contenido modificado genera un conflicto, mientras que repetir el mismo contenido es idempotente. Consulta Access Time Windows.

Especificaciones OpenAPI

Usa las especificaciones OpenAPI publicadas para generar clientes, validar solicitudes y hacer un seguimiento de los cambios en la estructura de la API a lo largo del tiempo.

Consulta Especificaciones OpenAPI.

https://partner-api.performancehub.co/partner/v1/

Registro de cambios

Este registro de cambios recoge los cambios importantes de la Partner API y la Partner Console que afectan al comportamiento de las integraciones.

2026-09-09

2026-05-06

2026-05-01

Categorías de cambios

Las entradas futuras usan estas categorías:

  • Agregado: nuevo endpoint, campo, guía o capacidad.
  • Modificado: cambió el comportamiento o la documentación sin retirar la compatibilidad.
  • Obsoleto: la función sigue disponible, pero tiene prevista una ruta de migración.
  • Eliminado: se eliminó la función o el endpoint.
  • Corregido: corrección de errores o de la documentación.
  • Seguridad: cambio en la autenticación, la autorización, el tratamiento de datos o la administración de claves.

Agregado

  • Se agregaron instantáneas access_time_windows de miembros, independientes del proveedor, con ventanas absolutas y semanales recurrentes combinadas.
  • Se agregó la semántica de ordenación por access_time_windows_revision, repetición idempotente, conflicto, omisión de datos obsoletos y revocación explícita.
  • Se agregaron pautas sobre zonas horarias IANA, horario de verano, asignación lógica de scope_key, actualización de la fuente, implementación del productor y certificación.

Agregado

  • Se agregó documentación del programa de socios sobre los tipos de socios, la incorporación, las prácticas recomendadas, la preparación para la puesta en producción, los errores, el control de versiones y el soporte.
  • Se agregó un flujo específico de consulta Conviértete en socio para posibles socios técnicos y comerciales.
  • Se agregó documentación sobre cómo aparecen las integraciones de socios aprobadas en el directorio de socios del Performance Hub, dentro de la plataforma principal del Performance Hub.

Agregado

  • Se agregó documentación de control de acceso para el controlador de puertas y portones, incluidas las operaciones de lista, estado y desbloqueo.
  • Se agregó documentación del comportamiento síncrono del desbloqueo: la API devuelve un resultado correcto solo después de que el controlador del sitio confirma que el relé se desbloqueó físicamente.
  • Se agregó documentación de la compatibilidad con la idempotency_key opcional en las solicitudes de desbloqueo del controlador de puertas y portones.