Provider API v1
Emperor obtiene usuarios registrados y actividad diaria de las aplicaciones con un contrato compartido. Cualquier aplicación puede implementarlo, no solo las propias. La aplicación queda como origen; las sincronizaciones posteriores actualizan los datos. La misma persona en varias apps no crea un Person duplicado.
Esta página es para equipos que implementan el contrato. El documento OpenAPI 3.1 está en la especificación de Provider API. Genere tipos de cliente desde esa ruta en el mismo origen que este sitio.
v1 es un borrador y puede cambiar hasta que Emperor lo finalice. Después de la finalización, los cambios incompatibles salen como /v2.
Recursos
La aplicación sirve tres recursos GET bajo /v1, relativos al baseUrl de la conexión Facility:
/v1/manifest— versión del contrato (1), nombre de la aplicación, zona horaria IANA para agrupar días de actividad y el catálogo de claves de actividad con etiquetas./v1/users— usuarios. Consulta:updatedSince,cursor,limit./v1/activity— agregados diarios, una fila por usuario, día y clave del catálogo. Los mismos parámetros de consulta que users.
Si contractVersion no es 1, Emperor rechaza la conexión con un error explícito.
Cursores y sobrescritura de actividad
updatedSince es un datetime ISO-8601 con desplazamiento o Z. Devuelva registros con updatedAt mayor o igual que ese valor. Sin el parámetro, exportación completa. cursor es una cadena opaca del nextCursor de la página anterior. limit vale 100 por defecto y no debe superar 100.
Las listas responden { "data": [...], "nextCursor": null | string }. nextCursor es null en la última página.
Una fila de actividad posterior para el mismo (externalUserId, day, metricKey) sustituye el recuento guardado. Las aplicaciones envían totales diarios, no eventos crudos.
Correo o teléfono
Cada usuario debe incluir email, phone (E.164, por ejemplo +79991234567) o ambos. Un registro sin ninguno lo rechaza el contrato. Emperor lo cuenta como rechazado en la sincronización y no crea un Person.
Cómo Emperor relaciona contactos
Una persona en el CRM es Person. El correo y el teléfono son filas Contact (tipos EMAIL y TELEPHONE). La identidad de la aplicación vive en un enlace aparte: una persona, varias apps.
- El correo se normaliza. El teléfono se guarda en E.164.
- Una identidad ya vinculada a un Person se actualiza.
- Una identidad nueva sin coincidencias crea un Person.
- Cualquier coincidencia con un Person existente, incluido un conflicto de correo/teléfono, va a una cola de revisión manual. No hay fusión automática.
Lista de conexión
- Publicar
/v1/manifest,/v1/usersy/v1/activitysolo por HTTPS en producción. - Emitir un token Bearer de alta entropía por par proyecto–aplicación, solo lectura de esta API. No reutilizar una clave de servicio.
- Comparar el token en tiempo constante. Una petición sin Bearer válido responde
401como RFC 7807application/problem+json. No distinguir si faltaba el token o era incorrecto. - Aceptar
User-Agent: Emperor-AppProvider/1.0yX-Request-Id(UUID). Devolver ese id en documentos problem al responder errores. - En
429, enviarRetry-After. - Rotación: aceptar el token actual y el anterior durante la ventana de rotación; después revocar el antiguo.
- En desarrollo local, Emperor permite
baseUrlHTTP en claro solo siAPP_PROVIDER_ALLOW_PLAIN_HTTP=true(lo pone el script de desarrollo del frontend). En producción solo se acepta HTTPS.
Seguridad y registro de auditoría de la aplicación
v1 es HTTPS más un token Bearer en el par proyecto–aplicación. HMAC, mTLS y OAuth2 no forman parte de esta versión.
Recomendado (no es un requisito de esquema): registrar cada petición de Provider API con hora, IP de origen, X-Request-Id, User-Agent, recurso (manifest / users / activity), updatedSince, estado HTTP y número de registros devueltos. No registrar el token, la cabecera Authorization, el correo, el teléfono ni los cuerpos de respuesta.
También: un token solo para esta API; límite de ritmo; alertas ante un ráfaga de 401, un User-Agent ajeno, una IP inesperada o un salto brusco de volumen. No exigir una allowlist de IP: el egress de Emperor en Kubernetes no es una dirección fija.