Apariencia
Convenciones
Lo que se describe en esta página vale para todos los recursos.
Dirección
La API responde en el subdominio de la cuenta, bajo /api/v1/:
https://<subdominio>.safetypanel.com.ar/api/v1/El subdominio es la parte inicial de la dirección con la que se ingresa al panel (por ejemplo, para tuempresa.safetypanel.com.ar es tuempresa). La dirección exacta de la cuenta aparece en Configuración → API.
Todas las respuestas son JSON. Los recursos solo se leen con GET: cualquier otro método, o una ruta que no existe, responde 404 con el código not_found.
Autenticación
Cada llamada lleva la key en el encabezado Authorization, con el esquema Bearer:
Authorization: Bearer spk_…No se acepta la key en la dirección ni en otro esquema. Una llamada sin key, con una key revocada, con una key de otra cuenta o con una key que nunca existió responde lo mismo: 401 con el código unauthorized. La respuesta no distingue entre esos casos a propósito.
Para comprobar que una key funciona antes de integrar nada, pedí la cuenta:
sh
curl https://tuempresa.safetypanel.com.ar/api/v1/account \
-H "Authorization: Bearer spk_…"Fechas y horas
Todos los instantes van en UTC y en formato ISO 8601, por ejemplo 2026-09-23T17:41:48Z, aunque la cuenta opere en otra zona horaria.
Errores
Todo error responde con el mismo formato: un objeto error con un code en inglés, pensado para que lo lea el sistema, y un message en español, pensado para que lo lea una persona.
json
{
"error": {
"code": "invalid_parameter",
"message": "per_page debe ser un entero entre 1 y 100."
}
}| Estado HTTP | code | Cuándo |
|---|---|---|
401 | unauthorized | Falta la key, o no es válida para esta cuenta. |
403 | module_disabled | La key es válida, pero la cuenta no tiene la API habilitada. |
404 | not_found | El registro no existe en esta cuenta, o la ruta no existe. |
422 | invalid_parameter | Un parámetro tiene un valor inválido. El mensaje dice cuál y qué valores acepta. |
429 | rate_limited | La key superó su límite de uso. |
La key se valida antes que todo lo demás: una llamada sin key válida recibe 401 aunque la ruta no exista o la cuenta no tenga el módulo habilitado.
Un registro de otra cuenta responde 404, igual que uno que no existe.
Paginación
Los listados se entregan por páginas, ordenados por id de menor a mayor. Así una página no cambia entre dos llamadas seguidas.
| Parámetro | Valor por defecto | Valores válidos |
|---|---|---|
page | 1 | Un entero desde 1. |
per_page | 25 | Un entero entre 1 y 100. |
La respuesta trae los registros en data y la información para recorrer el resto en meta:
json
{
"data": [ … ],
"meta": {
"page": 1,
"per_page": 25,
"total": 42,
"next_page": 2
}
}totales la cantidad de registros que cumplen los filtros, sumando todas las páginas.next_pagees el número de la página siguiente, onullen la última. Para recorrer un listado completo, pedí páginas hasta quenext_pageseanull.- Una página más allá de la última responde con
datavacío, no con un error.
Filtros
Los filtros se pasan como parámetros en la dirección y se combinan con la paginación. Cada recurso indica cuáles acepta.
updated_since
Devuelve solo los registros que cambiaron en o después del instante indicado. Es la forma de sincronizar sin volver a leer todo: guardá el momento de la última lectura y pedí lo que cambió desde entonces.
- Acepta un instante ISO 8601 (
2026-09-01T12:00:00Z) o una fecha sola (2026-09-01), que se toma como la medianoche UTC de ese día. - Un instante sin zona horaria se interpreta en UTC.
- Cualquier otro valor responde
422.
Un registro también cuenta como cambiado cuando cambia algo que la API muestra dentro de él, por ejemplo, un profesional que se asigna a un sitio. Cada recurso detalla qué cambios lo mueven.
status
Filtra por estado. Si no se indica, devuelve solo los registros activos, tal como los muestra el panel. Un valor que el recurso no admite responde 422 y el mensaje lista los válidos.
El filtro solo afecta a los listados: un registro pedido por su id se devuelve en cualquier estado, y el campo status indica en cuál está.
Límites de uso
Cada key tiene un cupo de 300 llamadas por minuto. El cupo es por key, no por dirección IP, así que dos sistemas con keys distintas no se afectan entre sí.
Cada respuesta informa el cupo en tres encabezados:
| Encabezado | Qué indica |
|---|---|
x-ratelimit-limit | Las llamadas permitidas por minuto. |
x-ratelimit-remaining | Las que quedan en el minuto en curso. |
x-ratelimit-reset | El instante en que se renueva el cupo, en segundos desde el 1 de enero de 1970 (UTC). |
El cupo se renueva al comienzo de cada minuto, no un minuto después de la primera llamada. Una llamada por encima del cupo responde 429 con el código rate_limited y el encabezado retry-after, que indica cuántos segundos faltan para que se renueve. Esperá ese tiempo antes de reintentar.