Inicio rápido
Crea en la administración web una aplicación vinculada a la empresa de destino. Copia su App ID y App Secret y, si necesitas el resultado final, configura un Callback URL opcional.
Engine crea entradas para los usuarios elegidos por el audience opcional (toda la empresa elegible por defecto) y solo intenta el Push del sistema en dispositivos registrados válidos.
Endpoint y autenticación
Entornos de API:
- Pruebas: https://aim-api-test.proton-system.com
- Producción: https://aim-api.proton-system.com
Cada solicitud JSON de servidor a servidor debe incluir Authorization: Basic Base64(KEY:SECRET) mediante HTTP Basic Authentication, donde KEY es el App ID y SECRET es el App Secret:
Endpoint: POST /openapi/v1/notifications.
curl --request POST 'https://<your-engine-host>/openapi/v1/notifications' \
--header 'Authorization: Basic <Base64(AppID:AppSecret)>' \
--header 'Content-Type: application/json' \
--data '{"requestId":"order-20260819-001","title":"Pedido completado","body":"Tu pedido se ha completado.","imageUrls":["https://cdn.example.com/order/001-1.webp","https://cdn.example.com/order/001-2.webp"],"displayFields":[{"label":"Nombre de la tienda","value":"Fideos Xiao Han (Wangjing)"},{"value":"ORD-10086"}],"tags":["Completado","Tienda principal"]}'Contrato de solicitud
Resumen de campos
| Campo | Obligatorio | Tipo | Significado |
|---|---|---|---|
requestId | Sí | string | Identificador único del emisor y clave de idempotencia. Se recorta y no puede quedar vacío. |
title | Sí | string | Título de la notificación. Se recorta y no puede quedar vacío. |
body | Sí | string | Cuerpo de la notificación. Se recorta y no puede quedar vacío. |
imageUrls | No | string[] | Imágenes del detalle, en orden. |
displayFields | No | object[] | Campos de texto adicionales del detalle, en orden. |
tags | No | string[] | Etiquetas de plain text mostradas solo en el detalle, en orden. |
audience | No | object | Limita el envío a usuarios o roles; omitido incluye a toda la empresa elegible. |
Imágenes: imageUrls
- Omite el campo, envía
nullo[]si no hay imágenes; si las hay, envía 1-9 URL en orden. - Cada URL se recorta, debe ser única y debe ser una URL
HTTPSabsoluta sin usuario ni contraseña. - Cada URL admite hasta 2048 caracteres Unicode. Una URL no válida rechaza toda la solicitud.
- Engine guarda las URL, pero no obtiene, comprueba, sirve como proxy ni almacena las imágenes en caché.
Campos de detalle: displayFields
| Subcampo | Obligatorio | Límite | Presentación |
|---|---|---|---|
label | No | Se recorta, no puede quedar vacío y admite 32 Unicode caracteres | Nombre del campo. |
value | Sí | Se recorta, no puede quedar vacío y admite 256 Unicode caracteres | Valor del campo. |
{
"displayFields": [
{ "label": "Tienda", "value": "Little Han Noodles (Wangjing)" },
{ "value": "ORD-10086" }
]
}- Omitirlo, enviar
nullo[]significa que no hay filas adicionales; se admiten hasta 10 objetos. - Sin
labelo conlabel: null, elvalueocupa una línea completa. - El contenido siempre es plain text; no se admiten HTML, Markdown, enlaces, datos anidados, tipos ni estilos.
Etiquetas del detalle: tags
- Omite el campo, envía
nullo[]si no hay etiquetas. Si las hay, envía como máximo 8 strings en orden. - Cada etiqueta se recorta y debe tener 1-20 caracteres Unicode. Un valor vacío, no string, demasiado largo o duplicado tras recortarlo rechaza toda la solicitud con
INVALID_REQUEST. - Las etiquetas son plain text no interactivo, aparecen solo en el detalle y conservan su orden.
Destinatarios: audience
type | Selector | Significado del ID |
|---|---|---|
USERS | userIds | ID de miembro de la empresa |
ROLES | roles | CompanyRole ID; reciben los miembros válidos de cualquiera de los roles. |
Copia el ID de miembro de la empresa desde la lista de miembros de la empresa en Web Admin. El miembro debe pertenecer a la empresa vinculada a la aplicación de terceros.
{
"audience": { "type": "USERS", "userIds": ["companyMemberId"] }
}{
"audience": { "type": "ROLES", "roles": ["roleId"] }
}- Omite
audienceo envíanullpara todos los usuarios activos elegibles de la empresa vinculada. - La lista admite 1-100 strings originales; los ID se recortan, los vacíos se ignoran y el conjunto se deduplica y ordena.
- Los IDs inexistentes, inactivos, eliminados o de otra empresa se ignoran; los objetivos válidos restantes reciben el aviso.
- Un selector válido sin objetivos se acepta y termina con
recipientCount=0; nunca vuelve al envío para toda la empresa. - El selector no correspondiente puede omitirse o ser
null. Mezclas no nulas, types o campos desconocidos, listas ausentes o vacías, valores no string y más de 100 entradas producenINVALID_REQUEST.
Límites e idempotencia
- El cuerpo completo admite 256 KiB.
requestId,titleybodyadmiten 128, 100 y 1000 caracteres Unicode. - Cada App ID admite 10 solicitudes por minuto y 100 por hora.
- Repetir
requestIdcon contenido normalizado equivalente devuelve el resultado guardado. El orden importa para imágenes, campos y tags; no para el conjunto audience. - Otro contenido con el mismo
requestIddevuelveIDEMPOTENCY_CONFLICT. Un resultado terminado puede serSUCCESS,PARTIAL_SUCCESSoFAILED.
Respuesta de aceptación
Una solicitud válida devuelve HTTP 202:
{
"requestId": "order-20260819-001",
"notificationId": "00000000-0000-0000-0000-000000000001",
"status": "ACCEPTED"
}ACCEPTED solo indica que Engine guardó la solicitud para distribuirla; no confirma que APNs/FCM ni el dispositivo hayan mostrado la notificación.
Resultado del Callback
Con Callback URL configurado, Engine envía un resultado terminal:
{
"requestId": "order-20260819-001",
"status": "PARTIAL_SUCCESS",
"recipientCount": 8,
"pushAcceptedCount": 1,
"pushFailedCount": 1
}recipientCount es el número de usuarios destinatarios del centro de notificaciones. pushAcceptedCount y pushFailedCount son recuentos de lotes de Push Outbox, no recuentos de usuarios o dispositivos ni prueba de entrega del banner del sistema.
Prueba de Callback
Cada prueba de Callback del panel de administración envía una sonda distinta:
{
"requestId": "callback-test-<unique-id>",
"status": "SUCCESS",
"recipientCount": 1,
"pushAcceptedCount": 1,
"pushFailedCount": 0,
"test": true
}Cuando test sea true, valida la estructura y responde con 2xx, pero no relaciones la sonda con una solicitud de notificación ni actualices el estado de entrega del negocio. Sus recuentos son valores fijos de prueba, no destinatarios ni lotes reales de Push Outbox.
El status final es SUCCESS, PARTIAL_SUCCESS o FAILED. Responde con cualquier 2xx para confirmarlo.
Si no, Engine reintenta tras 1 minuto, 5 minutos, 30 minutos, 2 horas, 6 horas y 24 horas. Actualmente no hay firma HMAC: exige HTTPS, valida el requestId de los resultados que no sean de prueba, limita la exposición y procesa cada Callback de forma idempotente.
Referencia de errores
| HTTP | Code | Significado |
|---|---|---|
| 400 | INVALID_REQUEST | Falló Content-Type, JSON, tamaño o validación. |
| 401 | INVALID_APP_CREDENTIALS | App ID o App Secret no válidos. |
| 403 | APPLICATION_INACTIVE | La aplicación o empresa está inactiva. |
| 409 | IDEMPOTENCY_CONFLICT | requestId se reutilizó con otro contenido. |
| 429 | RATE_LIMITED | Se superó el límite de la aplicación. |
| 503 | NOTIFICATION_UNAVAILABLE | El servicio no está disponible temporalmente. |
Seguridad y ámbito de envío
- App ID y App Secret son credenciales entre servidores. No las incluyas en navegador, aplicación móvil, repositorio público, URL ni almacenamiento del cliente. Restablece App Secret si se filtra.
- Los IDs objetivo privados nunca se escriben en los logs de la aplicación. El selector privado y sus IDs tampoco aparecen en GraphQL, Push, Callback, realtime ni navigation.
- Sin
audience, se incluyen todos los usuarios activos elegibles de la empresa; con audience, solo los objetivos válidos resueltos. Cada destinatario válido recibe una entrada y se cuenta enrecipientCount. - El Push del sistema solo se intenta en dispositivos con un
PushInstallationactivo que permita la categoríaBUSINESS, sin garantizar un banner en cada dispositivo. - La lista completa de
imageUrlssolo está en el detalle autorizado. Engine puede enviar la primera URL deimageUrlsa APNs/FCM para un banner nativo.displayFieldsytagsno se incluyen en Push ni Callback y son plain text no interactivo; no incluyas secretos, tokens de acceso, datos de pago ni valores sensibles. titleybodydeben seguir siendo completos y comprensibles sin las imágenes. Un fallo al descargar o mostrar una imagen no cambia el estado de accepted, Callback ni Push.- El cliente móvil acepta como máximo 5 MiB por imagen y concede 10 segundos a toda la operación de descarga. No sigue redirecciones 3xx, por lo que cada URL debe devolver la imagen directamente.
- El cliente móvil descarga cada imagen directamente del CDN público. Usa URL sin autenticación ni cookies, mantenlas disponibles al menos 90 días y considera que el CDN recibe la IP, la hora de solicitud y el User-Agent del usuario.
- Usa URL de objetos inmutables si necesitas una visualización histórica estable.