v1 · vista previa

Prueba con webhook firma, alert.created, location_withheld o 429.

↑ ↓ moverseIntro abrirEsc cerrar

Referencia

Webhooks

Destinos y el formato de lo que se les envía.

Listar destinos

GET/v1/webhooks

Scope webhooks:manage

Respuestas

  • 200

    Destinos.

    application/json WebhookEndpointList

  • 401

    Falta el token, ha caducado o se ha revocado.

    application/problem+json Problem

  • 403

    Al token le falta el scope que pide la ruta, o el centro no es del cliente.

    application/problem+json Problem

  • 429

    Demasiadas peticiones, o demasiado tiempo de consulta: cada cliente tiene un número de peticiones por minuto (600 de serie) y un tiempo de consulta por minuto (30 s de serie), y cada petición gasta lo que tarda, así que una lista larga cuenta más que una alerta suelta. Retry-After dice cuándo volver.

    application/problem+json Problem

Petición · sandbox

curl "https://sandbox.api.safeonuba.com/v1/webhooks" \
  -H "Authorization: Bearer $SAFEONUBA_TOKEN"

Respuesta 200

JSON
{
  "data": [
    {
      "id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
      "url": "string",
      "event_types": [
        "alert.created"
      ],
      "filters": {
        "site_ids": [
          "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90"
        ],
        "min_severity": "low",
        "contractors": [
          "string"
        ]
      },
      "is_active": false,
      "failing_since": "2026-09-24T11:04:12Z",
      "created_at": "2026-09-24T11:04:12Z"
    }
  ]
}

Crear un destino

POST/v1/webhooks

Scope webhooks:manage

Cuerpo application/json WebhookEndpointCreate

  • urlstringobligatorio
  • event_typesarray<EventType | "alert.*" | "muster.*">obligatorio
  • filtersobject
    Campos3
    • site_idsarray<string (uuid)>
    • min_severitySeverity

      Valores posibles: lowmediumhighcritical

    • contractorsarray<string>

Respuestas

  • 201

    Destino creado, con su secreto de firma (solo esta vez).

    application/json WebhookEndpointCreated

  • 401

    Falta el token, ha caducado o se ha revocado.

    application/problem+json Problem

  • 403

    Al token le falta el scope que pide la ruta, o el centro no es del cliente.

    application/problem+json Problem

  • 422

    El cuerpo no es válido (la URL tiene que ser https).

    application/problem+json Problem

  • 429

    Demasiadas peticiones, o demasiado tiempo de consulta: cada cliente tiene un número de peticiones por minuto (600 de serie) y un tiempo de consulta por minuto (30 s de serie), y cada petición gasta lo que tarda, así que una lista larga cuenta más que una alerta suelta. Retry-After dice cuándo volver.

    application/problem+json Problem

Petición · sandbox

curl -X POST "https://sandbox.api.safeonuba.com/v1/webhooks" \
  -H "Authorization: Bearer $SAFEONUBA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://sala.cliente.example/safeonuba",
  "event_types": [
    "alert.*",
    "muster.*"
  ]
}'

Respuesta 201

JSON
{
  "id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "url": "string",
  "event_types": [
    "alert.created"
  ],
  "filters": {
    "site_ids": [
      "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90"
    ],
    "min_severity": "low",
    "contractors": [
      "string"
    ]
  },
  "is_active": false,
  "failing_since": "2026-09-24T11:04:12Z",
  "created_at": "2026-09-24T11:04:12Z",
  "secret": "whsec_6f1c0d9e2b7a4c3f8e5d1a0b9c8e7f6a"
}

Borrar un destino

DEL/v1/webhooks/{id}

Scope webhooks:manage

Parámetros de ruta

  • idstring (uuid)obligatorio

    Id del destino.

Respuestas

  • 204

    Borrado.

  • 401

    Falta el token, ha caducado o se ha revocado.

    application/problem+json Problem

  • 403

    Al token le falta el scope que pide la ruta, o el centro no es del cliente.

    application/problem+json Problem

  • 404

    No existe.

    application/problem+json Problem

  • 429

    Demasiadas peticiones, o demasiado tiempo de consulta: cada cliente tiene un número de peticiones por minuto (600 de serie) y un tiempo de consulta por minuto (30 s de serie), y cada petición gasta lo que tarda, así que una lista larga cuenta más que una alerta suelta. Retry-After dice cuándo volver.

    application/problem+json Problem

Petición · sandbox

curl -X DELETE "https://sandbox.api.safeonuba.com/v1/webhooks/0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90" \
  -H "Authorization: Bearer $SAFEONUBA_TOKEN"

Respuesta 204

JSON
HTTP 204

Rotar el secreto de firma

POST/v1/webhooks/{id}/rotate-secret

Scope webhooks:manage

Da un secreto nuevo. El anterior sigue firmando 24 h: durante ese tiempo cada envío lleva las dos firmas en X-SafeOnuba-Signature, separadas por coma, así que el receptor puede cambiar de secreto sin cortar. Una segunda rotación retira el primero: nunca hay más de dos.

Parámetros de ruta

  • idstring (uuid)obligatorio

    Id del destino.

Respuestas

  • 200

    El secreto nuevo (solo esta vez) y hasta cuándo firma el anterior.

    application/json WebhookSecretRotated

  • 401

    Falta el token, ha caducado o se ha revocado.

    application/problem+json Problem

  • 403

    Al token le falta el scope que pide la ruta, o el centro no es del cliente.

    application/problem+json Problem

  • 404

    No existe.

    application/problem+json Problem

  • 429

    Demasiadas peticiones, o demasiado tiempo de consulta: cada cliente tiene un número de peticiones por minuto (600 de serie) y un tiempo de consulta por minuto (30 s de serie), y cada petición gasta lo que tarda, así que una lista larga cuenta más que una alerta suelta. Retry-After dice cuándo volver.

    application/problem+json Problem

Petición · sandbox

curl -X POST "https://sandbox.api.safeonuba.com/v1/webhooks/0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90/rotate-secret" \
  -H "Authorization: Bearer $SAFEONUBA_TOKEN"

Respuesta 200

JSON
{
  "secret": "whsec_6f1c0d9e2b7a4c3f8e5d1a0b9c8e7f6a",
  "previous_valid_until": "2026-09-24T11:04:12Z"
}

Enviar un evento de prueba

POST/v1/webhooks/{id}/test

Scope webhooks:manage

Manda un alert.created marcado simulated: true, firmado como uno real.

Parámetros de ruta

  • idstring (uuid)obligatorio

    Id del destino.

Respuestas

  • 202

    En cola: el resultado se ve en el destino (failing_since).

  • 401

    Falta el token, ha caducado o se ha revocado.

    application/problem+json Problem

  • 403

    Al token le falta el scope que pide la ruta, o el centro no es del cliente.

    application/problem+json Problem

  • 404

    No existe.

    application/problem+json Problem

  • 429

    Demasiadas peticiones, o demasiado tiempo de consulta: cada cliente tiene un número de peticiones por minuto (600 de serie) y un tiempo de consulta por minuto (30 s de serie), y cada petición gasta lo que tarda, así que una lista larga cuenta más que una alerta suelta. Retry-After dice cuándo volver.

    application/problem+json Problem

Petición · sandbox

curl -X POST "https://sandbox.api.safeonuba.com/v1/webhooks/0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90/test" \
  -H "Authorization: Bearer $SAFEONUBA_TOKEN"

Respuesta 202

JSON
HTTP 202

Lo que recibe tu destino

Cada evento llega a tu URL como un POST con este cuerpo. Los dos grupos comparten formato: cambia lo que va dentro de data.

Cambios en una alerta

POSTTu destino · alert.*

Lo recibe tu destino; va firmado, no lleva token.

Un POST por evento a cada destino suscrito, con el objeto completo.

Cabeceras: X-SafeOnuba-Event-Id, X-SafeOnuba-Timestamp (segundos Unix) y X-SafeOnuba-Signature: v1=<hex(HMAC_SHA256(secreto, timestamp + "." + cuerpo))>. Rechaza más de 5 min de desfase. Durante una rotación llegan dos firmas separadas por coma.

Acuse: cualquier 2xx en menos de 5 s. Reintentos a los 10 s, 30 s, 2 min, 10 min, 30 min, 1 h y cada hora hasta 24 h. Entrega «al menos una vez» (deduplica por id) y sin orden garantizado (usa date_last_modified). SOS, caídas, «no puedo evacuar» y evacuaciones salen antes que el resto.

Cuerpo application/json Event

  • idstring (uuid)obligatorio

    Para deduplicar: la entrega es «al menos una vez».

  • typeEventTypeobligatorio

    Valores posibles: alert.createdalert.acknowledgedalert.resolvedalert.reopenedalert.worker_acknowledgedmuster.startedmuster.kind_changedmuster.phase_changedmuster.targets_changedmuster.updatedmuster.worker_missingmuster.ended

  • api_versionstringobligatorio

    Valores posibles: 2026-09-24

  • created_atstring (date-time)obligatorio
  • organization_idstring (uuid) | nullobligatorio

    La empresa del centro. null en los eventos de prueba.

  • site_idstring (uuid)obligatorio
  • data{ alert } | { muster }obligatorio

    El objeto completo tal como lo devolvería el GET en ese instante.

    Una de 2 formas
    • variante 1
      • alertAlertobligatorio
        Campos de Alert22
        • idstring (uuid)obligatorio
        • typeAlertTypeobligatorio

          Valores posibles: sosfall_detectedrestricted_zone_entryforbidden_zone_entrypermit_expired_insidepermit_closed_insideheat_stressevacuation_helpworker_call_requestdevice_offlinelow_batteryearthquaketsunami_risk

        • severitySeverityobligatorio

          Valores posibles: lowmediumhighcritical

        • statusAlertStatusobligatorio

          Valores posibles: unacknowledgedacknowledgedresolved

        • titlestringobligatorio

          Con include_worker_names, el título que lee la sala (lleva el nombre de la persona). Sin él, uno compuesto con el tipo, la zona y el external_id, sin nombre.

        • date_createdstring (date-time)obligatorio
        • date_last_modifiedstring (date-time)obligatorio

          Para ordenar: los webhooks no garantizan el orden, y lo más viejo que lo que ya se tiene se descarta.

        • siteSiteRefobligatorio
          Campos de SiteRef2
          • idstring (uuid)obligatorio
          • namestringobligatorio
        • zoneZoneRefobligatorio
          Campos de ZoneRef2
          • idstring (uuid)obligatorio
          • namestringobligatorio
        • workerWorkerRefobligatorio
          Campos de WorkerRef4
          • idstring (uuid)obligatorio
          • external_idstring | nullobligatorio

            Código del trabajador en la empresa (el de su sistema de personal). null si no se ha dado.

          • namestring

            Nombre y apellidos. Solo si el contrato lo incluye; si no, la propiedad no aparece.

          • contractorstring | nullobligatorio
        • deviceDeviceRefobligatorio
          Campos de DeviceRef4
          • idstring (uuid)obligatorio
          • serialstringobligatorio
          • batteryinteger | nullobligatorio

            de 0 a 100

          • date_last_seenstring (date-time) | nullobligatorio
        • locationLocationobligatorio
          Campos de Location7
          • latitudenumberobligatorio

            de -90 a 90

          • longitudenumberobligatorio

            de -180 a 180

          • uncertainty_mnumber | nullobligatorio

            Radio de incertidumbre en metros. null si no se conoce: no saberla no es tenerla perfecta.

            mínimo 0

          • sourcestringobligatorio

            zone: la persona estaba en una zona de privacidad y el punto es el de la zona, no el suyo.

            Valores posibles: gpsnetworkzone

          • maskedbooleanobligatorio

            El punto es el representativo de una zona de privacidad.

          • position_date_utcstring (date-time)obligatorio
          • heightobject | nullobligatorio

            Altura sobre el suelo por barómetro, cuando se puede afirmar; null si no.

        • location_withheldbooleanobligatorio

          La posición existe pero no se entrega: en «Solo en emergencia», una alerta por debajo de la gravedad que destapa no la enseña, tampoco en el panel.

        • detailsAlertDetailsobligatorio
          Una de 9 formas
            • triggerstringobligatorio

              Cómo se pidió: en la pantalla del reloj, con el botón físico, tras una caída sin respuesta o desde la sala.

              Valores posibles: watch_buttonwatch_hardware_buttonafter_fallcontrol_room

            • escalated_to_sosbooleanobligatorio

              No contestó al «¿Estás bien?» del reloj y pasó a SOS.

            • zone_typestringobligatorio

              Valores posibles: restrictedforbidden

            • permit_referencestring | nullobligatorio

              El permiso de trabajo (ATS) que regía, si lo había.

          • Sin nada que salga del pulso: las constantes vitales no salen por la API, ni agregadas.

            • actionstringobligatorio

              Lo que se le ha dicho en el reloj: parar, beber y buscar sombra. No hay niveles.

              Valores posibles: stop_and_rest

            • heat_index_cnumber | nullobligatorio

              Índice de calor de la planta (°C).

            • sun_exposure_minutesinteger | nullobligatorio
            • reasonstring | nullobligatorio

              Lo que dijo en el reloj: atrapado, herido o ayudando a otra persona.

              Valores posibles: trappedinjuredhelping

            • muster_idstring (uuid)obligatorio
            • voice_notebooleanobligatorio

              Sin cobertura, el reloj grabó un aviso de voz (se escucha en el panel).

            • minutes_silentintegerobligatorio
            • battery_pctintegerobligatorio

              de 0 a 100

            • magnitudenumber | nullobligatorio
            • distance_kmnumber | nullobligatorio
            • officialbooleanobligatorio

              false: estimación de SafeOnuba sin aviso oficial. true: boletín oficial confirmado por una persona.

            • felt_at_sitebooleanobligatorio
            • etastring (date-time) | nullobligatorio

              Llegada estimada de la ola (tsunami).

        • nearbyarray<Nearby>obligatorio
          Campos de Nearby5
          • kindstringobligatorio

            Valores posibles: personvehicle

          • workerobjectobligatorio
          • vehicle_typestring | nullobligatorio
          • distance_mintegerobligatorio
          • reported_atstring (date-time)obligatorio
        • vehicle_warningsarray<VehicleWarning>obligatorio
          Campos de VehicleWarning4
          • atstring (date-time)obligatorio
          • vehicle_typestring | nullobligatorio
          • distance_mintegerobligatorio
          • worker_acknowledged_atstring (date-time) | nullobligatorio
        • worker_acknowledged_atstring (date-time) | nullobligatorio

          El trabajador pulsó «Entendido» en su reloj (hora del reloj).

        • acknowledgedActionByobligatorio
          Campos de ActionBy2
          • atstring (date-time)obligatorio
          • bystringobligatorio

            Quién: una persona del panel, o «Cliente · Operador (vía integración)».

        • resolvedobject | nullobligatorio

          Cerrada: quién, cuándo y con qué nota.

          Campos3
          • atstring (date-time)obligatorio
          • bystringobligatorio

            Quién: una persona del panel, o «Cliente · Operador (vía integración)».

          • notestring | nullobligatorio
        • assigned_tostring | nullobligatorio
        • simulatedbooleanobligatorio

          Generada en un simulacro o con relojes simulados.

        • panel_urlstring (uri)obligatorio
    • variante 2
      • musterMusterobligatorio
        Campos de Muster13
        • idstring (uuid)obligatorio
        • siteSiteRefobligatorio
          Campos de SiteRef2
          • idstring (uuid)obligatorio
          • namestringobligatorio
        • statusstringobligatorio

          Valores posibles: activecompletedcancelled

        • phasestringobligatorio

          inspecting: recuento completo y la sala revisa la planta; los relojes dicen «no vuelvas hasta nuevo aviso».

          Valores posibles: evacuatinginspecting

        • kindMusterKindobligatorio

          Valores posibles: generaltsunamiearthquake

        • reasonstring | nullobligatorio
        • started_atstring (date-time)obligatorio
        • ended_atstring (date-time) | nullobligatorio
        • deadlineobject | nullobligatorio
          Campos2
          • atstring (date-time)obligatorio
          • sourcestringobligatorio

            Tsunami: hora de un aviso oficial, o el techo del plan de la zona. Nunca un cálculo físico.

            Valores posibles: officialplan_estimate

        • originobject | nullobligatorio

          De dónde viene la emergencia. null en una evacuación sin origen (un simulacro general).

          Campos5
          • latitudenumberobligatorio
          • longitudenumberobligatorio
          • radius_mintegerobligatorio
          • labelstring | nullobligatorio
          • zoneZoneRefobligatorio
        • targets_revisionintegerobligatorio

          Sube cada vez que cambian los destinos (descarte, rehabilitación, cambio de tipo).

        • totalsobjectobligatorio

          Las mismas cifras que el banner del panel y el cierre: las cuenta el servidor. En una evacuación cerrada queda lo que se registró al cerrar —llegados y total—, y el resto sale null.

          Campos7
          • expectedintegerobligatorio
          • safeintegerobligatorio
          • helpinteger | nullobligatorio
          • wrong_pointinteger | nullobligatorio
          • pendinginteger | nullobligatorio
          • no_signalinteger | nullobligatorio
          • not_worninteger | nullobligatorio
        • assembly_pointsarray<AssemblyPoint>obligatorio

          Los destinos del tipo, descartados incluidos.

          Campos de AssemblyPoint5
          • idstring (uuid)obligatorio
          • namestringobligatorio
          • statusstringobligatorio

            Valores posibles: availableexcluded

          • countinteger | nullobligatorio

            Personas a salvo en este punto. null en una evacuación cerrada: al cerrar solo se guarda el total.

          • excludedobject | nullobligatorio

Respuestas

  • 200

    Recibido. Cualquier 2xx vale.

Cuerpo que recibe tu destino

Event
{
  "id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "type": "alert.created",
  "api_version": "2026-09-24",
  "created_at": "2026-09-24T11:04:12Z",
  "organization_id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "site_id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "data": {
    "alert": {
      "id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
      "type": "sos",
      "severity": "critical",
      "status": "unacknowledged",
      "title": "SOS activado — Ana Ejemplo",
      "date_created": "2026-09-24T11:04:12Z",
      "date_last_modified": "2026-09-24T11:04:12Z",
      "site": {
        "id": "11111111-1111-1111-1111-111111111111",
        "name": "Planta Ejemplo — simulación"
      },
      "zone": null,
      "worker": {
        "id": "33333333-3333-3333-3333-333333333305",
        "external_id": "EMP-004512",
        "name": "Ana Ejemplo",
        "contractor": "Contrata Ejemplo A"
      },
      "device": {
        "id": "44444444-4444-4444-4444-444444444405",
        "serial": "OS-W-0005",
        "battery": 64,
        "date_last_seen": "2026-09-24T11:04:10Z"
      },
      "location": {
        "latitude": 40.00121,
        "longitude": -3.00214,
        "uncertainty_m": 8,
        "source": "gps",
        "masked": false,
        "position_date_utc": "2026-09-24T11:04:08Z",
        "height": null
      },
      "location_withheld": false,
      "details": {
        "trigger": "watch_button"
      },
      "nearby": [
        {
          "kind": "vehicle",
          "worker": {
            "id": "33333333-3333-3333-3333-333333333309",
            "external_id": "EMP-002210",
            "name": "Carlos Ejemplo",
            "contractor": "Contrata Ejemplo B"
          },
          "vehicle_type": "Grúa móvil",
          "distance_m": 18,
          "reported_at": "2026-09-24T11:04:02Z"
        },
        {
          "kind": "person",
          "worker": {
            "id": "33333333-3333-3333-3333-333333333301",
            "external_id": "EMP-000981",
            "name": "Diego Ejemplo",
            "contractor": null
          },
          "vehicle_type": null,
          "distance_m": 26,
          "reported_at": "2026-09-24T11:03:58Z"
        }
      ],
      "vehicle_warnings": [],
      "worker_acknowledged_at": null,
      "acknowledged": null,
      "resolved": null,
      "assigned_to": null,
      "simulated": false,
      "panel_url": "https://app.safeonuba.com/alertas/0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90"
    }
  }
}

Cómo comprobar que viene de SafeOnuba: verificar la firma.

Cambios en una evacuación

POSTTu destino · muster.*

Lo recibe tu destino; va firmado, no lleva token.

Un POST por evento a cada destino suscrito, con el objeto completo.

Cabeceras: X-SafeOnuba-Event-Id, X-SafeOnuba-Timestamp (segundos Unix) y X-SafeOnuba-Signature: v1=<hex(HMAC_SHA256(secreto, timestamp + "." + cuerpo))>. Rechaza más de 5 min de desfase. Durante una rotación llegan dos firmas separadas por coma.

Acuse: cualquier 2xx en menos de 5 s. Reintentos a los 10 s, 30 s, 2 min, 10 min, 30 min, 1 h y cada hora hasta 24 h. Entrega «al menos una vez» (deduplica por id) y sin orden garantizado (usa date_last_modified). SOS, caídas, «no puedo evacuar» y evacuaciones salen antes que el resto.

Cuerpo application/json Event

  • idstring (uuid)obligatorio

    Para deduplicar: la entrega es «al menos una vez».

  • typeEventTypeobligatorio

    Valores posibles: alert.createdalert.acknowledgedalert.resolvedalert.reopenedalert.worker_acknowledgedmuster.startedmuster.kind_changedmuster.phase_changedmuster.targets_changedmuster.updatedmuster.worker_missingmuster.ended

  • api_versionstringobligatorio

    Valores posibles: 2026-09-24

  • created_atstring (date-time)obligatorio
  • organization_idstring (uuid) | nullobligatorio

    La empresa del centro. null en los eventos de prueba.

  • site_idstring (uuid)obligatorio
  • data{ alert } | { muster }obligatorio

    El objeto completo tal como lo devolvería el GET en ese instante.

    Una de 2 formas
    • variante 1
      • alertAlertobligatorio
        Campos de Alert22
        • idstring (uuid)obligatorio
        • typeAlertTypeobligatorio

          Valores posibles: sosfall_detectedrestricted_zone_entryforbidden_zone_entrypermit_expired_insidepermit_closed_insideheat_stressevacuation_helpworker_call_requestdevice_offlinelow_batteryearthquaketsunami_risk

        • severitySeverityobligatorio

          Valores posibles: lowmediumhighcritical

        • statusAlertStatusobligatorio

          Valores posibles: unacknowledgedacknowledgedresolved

        • titlestringobligatorio

          Con include_worker_names, el título que lee la sala (lleva el nombre de la persona). Sin él, uno compuesto con el tipo, la zona y el external_id, sin nombre.

        • date_createdstring (date-time)obligatorio
        • date_last_modifiedstring (date-time)obligatorio

          Para ordenar: los webhooks no garantizan el orden, y lo más viejo que lo que ya se tiene se descarta.

        • siteSiteRefobligatorio
          Campos de SiteRef2
          • idstring (uuid)obligatorio
          • namestringobligatorio
        • zoneZoneRefobligatorio
          Campos de ZoneRef2
          • idstring (uuid)obligatorio
          • namestringobligatorio
        • workerWorkerRefobligatorio
          Campos de WorkerRef4
          • idstring (uuid)obligatorio
          • external_idstring | nullobligatorio

            Código del trabajador en la empresa (el de su sistema de personal). null si no se ha dado.

          • namestring

            Nombre y apellidos. Solo si el contrato lo incluye; si no, la propiedad no aparece.

          • contractorstring | nullobligatorio
        • deviceDeviceRefobligatorio
          Campos de DeviceRef4
          • idstring (uuid)obligatorio
          • serialstringobligatorio
          • batteryinteger | nullobligatorio

            de 0 a 100

          • date_last_seenstring (date-time) | nullobligatorio
        • locationLocationobligatorio
          Campos de Location7
          • latitudenumberobligatorio

            de -90 a 90

          • longitudenumberobligatorio

            de -180 a 180

          • uncertainty_mnumber | nullobligatorio

            Radio de incertidumbre en metros. null si no se conoce: no saberla no es tenerla perfecta.

            mínimo 0

          • sourcestringobligatorio

            zone: la persona estaba en una zona de privacidad y el punto es el de la zona, no el suyo.

            Valores posibles: gpsnetworkzone

          • maskedbooleanobligatorio

            El punto es el representativo de una zona de privacidad.

          • position_date_utcstring (date-time)obligatorio
          • heightobject | nullobligatorio

            Altura sobre el suelo por barómetro, cuando se puede afirmar; null si no.

        • location_withheldbooleanobligatorio

          La posición existe pero no se entrega: en «Solo en emergencia», una alerta por debajo de la gravedad que destapa no la enseña, tampoco en el panel.

        • detailsAlertDetailsobligatorio
          Una de 9 formas
            • triggerstringobligatorio

              Cómo se pidió: en la pantalla del reloj, con el botón físico, tras una caída sin respuesta o desde la sala.

              Valores posibles: watch_buttonwatch_hardware_buttonafter_fallcontrol_room

            • escalated_to_sosbooleanobligatorio

              No contestó al «¿Estás bien?» del reloj y pasó a SOS.

            • zone_typestringobligatorio

              Valores posibles: restrictedforbidden

            • permit_referencestring | nullobligatorio

              El permiso de trabajo (ATS) que regía, si lo había.

          • Sin nada que salga del pulso: las constantes vitales no salen por la API, ni agregadas.

            • actionstringobligatorio

              Lo que se le ha dicho en el reloj: parar, beber y buscar sombra. No hay niveles.

              Valores posibles: stop_and_rest

            • heat_index_cnumber | nullobligatorio

              Índice de calor de la planta (°C).

            • sun_exposure_minutesinteger | nullobligatorio
            • reasonstring | nullobligatorio

              Lo que dijo en el reloj: atrapado, herido o ayudando a otra persona.

              Valores posibles: trappedinjuredhelping

            • muster_idstring (uuid)obligatorio
            • voice_notebooleanobligatorio

              Sin cobertura, el reloj grabó un aviso de voz (se escucha en el panel).

            • minutes_silentintegerobligatorio
            • battery_pctintegerobligatorio

              de 0 a 100

            • magnitudenumber | nullobligatorio
            • distance_kmnumber | nullobligatorio
            • officialbooleanobligatorio

              false: estimación de SafeOnuba sin aviso oficial. true: boletín oficial confirmado por una persona.

            • felt_at_sitebooleanobligatorio
            • etastring (date-time) | nullobligatorio

              Llegada estimada de la ola (tsunami).

        • nearbyarray<Nearby>obligatorio
          Campos de Nearby5
          • kindstringobligatorio

            Valores posibles: personvehicle

          • workerobjectobligatorio
          • vehicle_typestring | nullobligatorio
          • distance_mintegerobligatorio
          • reported_atstring (date-time)obligatorio
        • vehicle_warningsarray<VehicleWarning>obligatorio
          Campos de VehicleWarning4
          • atstring (date-time)obligatorio
          • vehicle_typestring | nullobligatorio
          • distance_mintegerobligatorio
          • worker_acknowledged_atstring (date-time) | nullobligatorio
        • worker_acknowledged_atstring (date-time) | nullobligatorio

          El trabajador pulsó «Entendido» en su reloj (hora del reloj).

        • acknowledgedActionByobligatorio
          Campos de ActionBy2
          • atstring (date-time)obligatorio
          • bystringobligatorio

            Quién: una persona del panel, o «Cliente · Operador (vía integración)».

        • resolvedobject | nullobligatorio

          Cerrada: quién, cuándo y con qué nota.

          Campos3
          • atstring (date-time)obligatorio
          • bystringobligatorio

            Quién: una persona del panel, o «Cliente · Operador (vía integración)».

          • notestring | nullobligatorio
        • assigned_tostring | nullobligatorio
        • simulatedbooleanobligatorio

          Generada en un simulacro o con relojes simulados.

        • panel_urlstring (uri)obligatorio
    • variante 2
      • musterMusterobligatorio
        Campos de Muster13
        • idstring (uuid)obligatorio
        • siteSiteRefobligatorio
          Campos de SiteRef2
          • idstring (uuid)obligatorio
          • namestringobligatorio
        • statusstringobligatorio

          Valores posibles: activecompletedcancelled

        • phasestringobligatorio

          inspecting: recuento completo y la sala revisa la planta; los relojes dicen «no vuelvas hasta nuevo aviso».

          Valores posibles: evacuatinginspecting

        • kindMusterKindobligatorio

          Valores posibles: generaltsunamiearthquake

        • reasonstring | nullobligatorio
        • started_atstring (date-time)obligatorio
        • ended_atstring (date-time) | nullobligatorio
        • deadlineobject | nullobligatorio
          Campos2
          • atstring (date-time)obligatorio
          • sourcestringobligatorio

            Tsunami: hora de un aviso oficial, o el techo del plan de la zona. Nunca un cálculo físico.

            Valores posibles: officialplan_estimate

        • originobject | nullobligatorio

          De dónde viene la emergencia. null en una evacuación sin origen (un simulacro general).

          Campos5
          • latitudenumberobligatorio
          • longitudenumberobligatorio
          • radius_mintegerobligatorio
          • labelstring | nullobligatorio
          • zoneZoneRefobligatorio
        • targets_revisionintegerobligatorio

          Sube cada vez que cambian los destinos (descarte, rehabilitación, cambio de tipo).

        • totalsobjectobligatorio

          Las mismas cifras que el banner del panel y el cierre: las cuenta el servidor. En una evacuación cerrada queda lo que se registró al cerrar —llegados y total—, y el resto sale null.

          Campos7
          • expectedintegerobligatorio
          • safeintegerobligatorio
          • helpinteger | nullobligatorio
          • wrong_pointinteger | nullobligatorio
          • pendinginteger | nullobligatorio
          • no_signalinteger | nullobligatorio
          • not_worninteger | nullobligatorio
        • assembly_pointsarray<AssemblyPoint>obligatorio

          Los destinos del tipo, descartados incluidos.

          Campos de AssemblyPoint5
          • idstring (uuid)obligatorio
          • namestringobligatorio
          • statusstringobligatorio

            Valores posibles: availableexcluded

          • countinteger | nullobligatorio

            Personas a salvo en este punto. null en una evacuación cerrada: al cerrar solo se guarda el total.

          • excludedobject | nullobligatorio

Respuestas

  • 200

    Recibido. Cualquier 2xx vale.

Cuerpo que recibe tu destino

Event
{
  "id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "type": "alert.created",
  "api_version": "2026-09-24",
  "created_at": "2026-09-24T11:04:12Z",
  "organization_id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "site_id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
  "data": {
    "alert": {
      "id": "0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90",
      "type": "sos",
      "severity": "critical",
      "status": "unacknowledged",
      "title": "SOS activado — Ana Ejemplo",
      "date_created": "2026-09-24T11:04:12Z",
      "date_last_modified": "2026-09-24T11:04:12Z",
      "site": {
        "id": "11111111-1111-1111-1111-111111111111",
        "name": "Planta Ejemplo — simulación"
      },
      "zone": null,
      "worker": {
        "id": "33333333-3333-3333-3333-333333333305",
        "external_id": "EMP-004512",
        "name": "Ana Ejemplo",
        "contractor": "Contrata Ejemplo A"
      },
      "device": {
        "id": "44444444-4444-4444-4444-444444444405",
        "serial": "OS-W-0005",
        "battery": 64,
        "date_last_seen": "2026-09-24T11:04:10Z"
      },
      "location": {
        "latitude": 40.00121,
        "longitude": -3.00214,
        "uncertainty_m": 8,
        "source": "gps",
        "masked": false,
        "position_date_utc": "2026-09-24T11:04:08Z",
        "height": null
      },
      "location_withheld": false,
      "details": {
        "trigger": "watch_button"
      },
      "nearby": [
        {
          "kind": "vehicle",
          "worker": {
            "id": "33333333-3333-3333-3333-333333333309",
            "external_id": "EMP-002210",
            "name": "Carlos Ejemplo",
            "contractor": "Contrata Ejemplo B"
          },
          "vehicle_type": "Grúa móvil",
          "distance_m": 18,
          "reported_at": "2026-09-24T11:04:02Z"
        },
        {
          "kind": "person",
          "worker": {
            "id": "33333333-3333-3333-3333-333333333301",
            "external_id": "EMP-000981",
            "name": "Diego Ejemplo",
            "contractor": null
          },
          "vehicle_type": null,
          "distance_m": 26,
          "reported_at": "2026-09-24T11:03:58Z"
        }
      ],
      "vehicle_warnings": [],
      "worker_acknowledged_at": null,
      "acknowledged": null,
      "resolved": null,
      "assigned_to": null,
      "simulated": false,
      "panel_url": "https://app.safeonuba.com/alertas/0f6c2b7e-3a1d-4c55-9b0e-7d2f4a8c1e90"
    }
  }
}

Cómo comprobar que viene de SafeOnuba: verificar la firma.