API pública · v1

Lleva los datos de tu obra a tus propios sistemas

Una API REST de solo lectura para leer incidencias, RFIs, órdenes de cambio, no conformidades, reuniones y formularios de un proyecto desde tu BI, ERP o scripts.

Introducción

Cada credencial pertenece a un solo proyecto y la crea un owner o admin en Configuración del proyecto › API. Tiene un client ID público, un client secret que se muestra una sola vez y una lista de permisos elegidos por módulo.

Tu servidor cambia la credencial por un token de acceso de corta duración y lo usa en cada petición. La API es de solo lectura: ningún endpoint crea, modifica ni borra datos.

Autenticación

OAuth 2.0 client credentials

Formato

JSON, UTF-8

Vida del token

1 hora, sin refresh token

Acceso

Solo lectura, un proyecto por credencial

URL base: https://api.wayki.app

Autenticación

Usamos el flujo client credentials de OAuth 2.0 (RFC 6749 §4.4). El secreto viaja solo al endpoint de tokens; cada petición de datos lleva un token que expira solo.

  1. 1. Crea una credencial

    En Wayki, abre el proyecto › Configuración › API › Nueva credencial. Elige solo los permisos que necesitas y, si puedes, restringe por IP y pon fecha de expiración. Copia el client secret: no se volverá a mostrar. Si no ves la pestaña API, pide a Wayki que active el módulo de API para tu proyecto.

  2. 2. Pide un token

    Envía client_id y client_secret con HTTP Basic (recomendado) o en el cuerpo, con grant_type=client_credentials. Opcionalmente pide menos permisos con scope.

  3. 3. Llama a la API

    Manda el token en la cabecera Authorization: Bearer. Reutilízalo hasta poco antes de expires_in y luego pide otro.

Obtener un token
Shell
curl -X POST https://api.wayki.app/v1/oauth/token -u 'CLIENT_ID:CLIENT_SECRET' -d grant_type=client_credentials
Respuesta
JSON
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "issues:read rfis:read"
}
Llamar a un endpoint
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/issues?page=1&limit=50' -H 'Authorization: Bearer ACCESS_TOKEN'
200 OK
JSON
{
  "data": [
    { "_id": "66f1…", "issueNumber": 128, "title": "Fisura en losa N3", "statusKey": "open", … }
  ],
  "meta": { "page": 1, "limit": 50, "total": 312, "totalPages": 7 }
}
Node.js (con caché del token)
JavaScript
const BASE = "https://api.wayki.app";
const PROJECT = process.env.WAYKI_PROJECT_ID;
let cached = { token: null, expiresAt: 0 };

async function getToken() {
  // Reuse the token until one minute before it expires.
  if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;
  const basic = Buffer.from(
    `${process.env.WAYKI_CLIENT_ID}:${process.env.WAYKI_CLIENT_SECRET}`,
  ).toString("base64");
  const res = await fetch(`${BASE}/v1/oauth/token`, {
    method: "POST",
    headers: {
      Authorization: `Basic ${basic}`,
      "Content-Type": "application/x-www-form-urlencoded",
    },
    body: "grant_type=client_credentials",
  });
  if (!res.ok) throw new Error(`Token request failed: ${res.status}`);
  const body = await res.json();
  cached = { token: body.access_token, expiresAt: Date.now() + body.expires_in * 1000 };
  return cached.token;
}

async function listAllRfis() {
  const all = [];
  for (let page = 1; ; page++) {
    const res = await fetch(
      `${BASE}/v1/projects/${PROJECT}/rfis?page=${page}&limit=100`,
      { headers: { Authorization: `Bearer ${await getToken()}` } },
    );
    if (!res.ok) throw new Error(`RFIs request failed: ${res.status}`);
    const { data, meta } = await res.json();
    all.push(...data);
    if (page >= meta.totalPages) return all;
  }
}
Python
Python
import os, requests

BASE = "https://api.wayki.app"
token = requests.post(
    f"{BASE}/v1/oauth/token",
    auth=(os.environ["WAYKI_CLIENT_ID"], os.environ["WAYKI_CLIENT_SECRET"]),
    data={"grant_type": "client_credentials", "scope": "meetings:read"},
    timeout=10,
).json()["access_token"]

meetings = requests.get(
    f"{BASE}/v1/projects/{os.environ['WAYKI_PROJECT_ID']}/meetings",
    headers={"Authorization": f"Bearer {token}"},
    params={"from": "2026-09-01", "to": "2026-09-30"},
    timeout=10,
).json()["data"]
  • Cambia CLIENT_ID, CLIENT_SECRET y ACCESS_TOKEN por tus valores. Los comandos van en una sola línea y funcionan igual en bash y en PowerShell; en Windows PowerShell 5.1 escribe curl.exe en lugar de curl.
  • No hay refresh token: cuando el token expira, vuelve a pedir uno con la credencial.
  • El token solo sirve para el proyecto de la credencial. Otro projectId responde 403.
  • Revocar la credencial, rotar su secreto, quitarle un permiso o archivar el proyecto corta los tokens vivos al instante.
  • El endpoint de tokens admite 10 peticiones por minuto por IP: guarda el token en memoria en vez de pedir uno por llamada.

Probar con Postman

La colección trae todos los endpoints organizados por módulo y pide el token por ti: solo completa tus credenciales.

  1. 1. Importa la colección

    Descárgala y en Postman usa Import › File. Aparece como «Wayki Project API (v1)».

  2. 2. Completa las variables

    Abre la colección › Variables y escribe en Current value tu clientId, clientSecret y projectId. Cambia baseUrl si usas otro servidor.

  3. 3. Envía cualquier petición

    Un script de la colección obtiene el token, lo guarda y lo renueva antes de que expire. Los filtros de las listas vienen desactivados para que los actives.

Guarda el client secret solo como Current value: Postman no lo sincroniza ni lo incluye al exportar. No compartas la colección con valores reales.

Descargar colección

Permisos (scopes)

Cada endpoint exige exactamente un permiso. Una credencial solo ve los módulos que tiene concedidos y, dentro de ellos, todo lo que vería un owner del proyecto.

ScopeQué permite leer
project:readProyecto — Nombre, código, estado, ubicación y empresa del proyecto.
members:readMiembros — Miembros y roles, con correo. También deja ver correos de personas en el resto de recursos.
issues:readIncidencias — Incidencias, configuración y respuestas.
rfis:readRFIs — RFIs, configuración y respuestas.
change-orders:readÓrdenes de cambio — Órdenes de cambio, configuración y respuestas.
non-conformances:readNo conformidades — No conformidades, configuración y respuestas.
meetings:readReuniones — Reuniones, acuerdos y actas congeladas.
forms:readFormularios — Formularios llenados y su configuración.

Paginación y errores

Formato de respuesta

Las listas devuelven { data, meta } y los recursos individuales { data }. Los identificadores son ObjectId de 24 caracteres hexadecimales y las fechas, ISO 8601 en UTC. Sin members:read, las personas aparecen sin correo; los teléfonos nunca se exponen.

Parámetros de las listas

page
Página, desde 1. Por defecto 1.
limit
Elementos por página, 1 a 100. Por defecto 20.
sort
Campo de orden. Cada recurso tiene su lista permitida; otro valor responde 400.
order
asc o desc. Por defecto desc.
q
Búsqueda de texto libre.
from / to
Rango de fechas ISO 8601, inclusivo.

Errores de la API de datos

Los errores devuelven { statusCode, message, error }. Un parámetro desconocido en la query es un 400, no se ignora.

  • 400Parámetro inválido o desconocido.
  • 401Token ausente, vencido o credencial revocada. Pide un token nuevo.
  • 403Falta el permiso, o el token es de otro proyecto.
  • 404El recurso no existe en este proyecto.
  • 429Límite de peticiones. Reintenta tras Retry-After.

Errores del endpoint de tokens (RFC 6749)

  • invalid_client (401)

    Client ID o secreto incorrectos, o credencial revocada o vencida.

  • invalid_scope (400)

    Pediste un scope que la credencial no tiene.

  • unauthorized_client (400)

    Proyecto archivado o IP fuera de la lista permitida.

  • invalid_request (400)

    Faltan parámetros o enviaste la credencial dos veces.

  • unsupported_grant_type (400)

    Solo se admite client_credentials.

Referencia

Todas las rutas empiezan por /v1/projects/{projectId}. El OpenAPI descargable describe los mismos endpoints.

Proyecto y miembros

Permiso: project:read · members:read

Datos generales del proyecto y la lista de miembros con su rol.

  • GET/v1/projects/{projectId}El proyecto (project:read).
  • GET/v1/projects/{projectId}/membersMiembros y roles, sin paginar (members:read).
Ejemplo
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6' -H 'Authorization: Bearer ACCESS_TOKEN'

Incidencias

Permiso: issues:read

Lista paginada, detalle, respuestas y configuración (estados, prioridades, tipos) de incidencias.

  • GET/v1/projects/{projectId}/issuesLista paginada.
  • GET/v1/projects/{projectId}/issues/{issueId}Detalle.
  • GET/v1/projects/{projectId}/issues/{issueId}/repliesRespuestas, de la más antigua a la más reciente (order=desc invierte).
  • GET/v1/projects/{projectId}/issues/settingsConfiguración del módulo: catálogos para interpretar los campos.

Orden permitido: createdAt, updatedAt, number, title, dueDate, priority. from / to filtran por fecha de creación.

Ejemplo
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/issues?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'

RFIs

Permiso: rfis:read

Lista paginada, detalle, respuestas y configuración (estados, prioridades, tipos) de RFIs.

  • GET/v1/projects/{projectId}/rfisLista paginada.
  • GET/v1/projects/{projectId}/rfis/{rfiId}Detalle.
  • GET/v1/projects/{projectId}/rfis/{rfiId}/repliesRespuestas, de la más antigua a la más reciente (order=desc invierte).
  • GET/v1/projects/{projectId}/rfis/settingsConfiguración del módulo: catálogos para interpretar los campos.

Orden permitido: createdAt, updatedAt, number, title, dueDate, status, priority. from / to filtran por fecha de creación.

Ejemplo
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/rfis?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'

Órdenes de cambio

Permiso: change-orders:read

Lista paginada, detalle, respuestas y configuración (estados, prioridades, tipos) de órdenes de cambio.

  • GET/v1/projects/{projectId}/change-ordersLista paginada.
  • GET/v1/projects/{projectId}/change-orders/{changeOrderId}Detalle.
  • GET/v1/projects/{projectId}/change-orders/{changeOrderId}/repliesRespuestas, de la más antigua a la más reciente (order=desc invierte).
  • GET/v1/projects/{projectId}/change-orders/settingsConfiguración del módulo: catálogos para interpretar los campos.

Orden permitido: createdAt, updatedAt, number, title, dueDate, status, priority. from / to filtran por fecha de creación.

Ejemplo
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/change-orders?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'

No conformidades

Permiso: non-conformances:read

Lista paginada, detalle, respuestas y configuración (estados, prioridades, tipos) de no conformidades.

  • GET/v1/projects/{projectId}/non-conformancesLista paginada.
  • GET/v1/projects/{projectId}/non-conformances/{nonConformanceId}Detalle.
  • GET/v1/projects/{projectId}/non-conformances/{nonConformanceId}/repliesRespuestas, de la más antigua a la más reciente (order=desc invierte).
  • GET/v1/projects/{projectId}/non-conformances/settingsConfiguración del módulo: catálogos para interpretar los campos.

Orden permitido: createdAt, updatedAt, number, title, dueDate, status, priority. from / to filtran por fecha de creación.

Ejemplo
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/non-conformances?limit=50&sort=updatedAt' -H 'Authorization: Bearer ACCESS_TOKEN'

Reuniones

Permiso: meetings:read

Reuniones con agenda, participantes y acuerdos, y las actas congeladas de cada sesión cerrada.

  • GET/v1/projects/{projectId}/meetingsLista paginada.
  • GET/v1/projects/{projectId}/meetings/{meetingId}Detalle con acuerdos y participantes.
  • GET/v1/projects/{projectId}/meetings/{meetingId}/minutesActas congeladas (una por sesión cerrada).
  • GET/v1/projects/{projectId}/meetings/{meetingId}/minutes/{versionId}Un acta.
  • GET/v1/projects/{projectId}/meetings/settingsEstados y prioridades de acuerdos.

Orden permitido: startPlannedDate, createdAt, title, number. from / to filtran por fecha planificada de inicio.

Ejemplo
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/meetings?from=2026-09-01&to=2026-09-30' -H 'Authorization: Bearer ACCESS_TOKEN'

Formularios

Permiso: forms:read

Formularios llenados (inspecciones, checklists, permisos) y su configuración.

  • GET/v1/projects/{projectId}/formsLista paginada.
  • GET/v1/projects/{projectId}/forms/{formId}Detalle.
  • GET/v1/projects/{projectId}/forms/settingsEstados, prioridades y tipos.

Orden permitido: createdAt, updatedAt, number, name. from / to filtran por fecha de creación.

Ejemplo
Shell
curl 'https://api.wayki.app/v1/projects/64b7f0c2e4b0a1b2c3d4e5f6/forms?q=concreto' -H 'Authorization: Bearer ACCESS_TOKEN'

Límites

Peticiones de datos
100 por minuto por credencial y endpoint
Endpoint de tokens
10 por minuto por IP
Tamaño de página
100 elementos como máximo
Credenciales activas
10 por proyecto
Vida del token
3600 segundos

Seguridad

Una credencial da acceso a datos reales de una obra. Estas reglas evitan la mayoría de los incidentes.

Haz

  • Guarda el client secret en un gestor de secretos o en variables de entorno del servidor.
  • Crea una credencial por integración, con el mínimo de permisos.
  • Restringe por IP cuando tu integración salga desde direcciones fijas.
  • Pon fecha de expiración a credenciales de terceros o proyectos temporales.
  • Rota el secreto si alguien que lo conocía deja el equipo.

No hagas

  • No uses la API desde un navegador ni una app móvil: el secreto quedaría expuesto. La API no admite CORS.
  • No pongas credenciales en la URL ni en repositorios de código.
  • No compartas una credencial entre varias integraciones: no sabrás cuál revocar.
  • No registres (log) el secreto ni la cabecera Authorization.

Cómo protegemos los datos

  • El secreto se guarda como hash SHA-256: ni Wayki puede volver a mostrarlo.
  • Los tokens están firmados con una clave exclusiva de esta API y ligados a un proyecto.
  • Cada petición vuelve a comprobar la credencial, el proyecto y la IP: revocar corta el acceso en el acto.
  • Las credenciales solo pueden llegar a las rutas /v1 de solo lectura; el resto de la API las rechaza.
  • Cada alta, cambio, rotación, revocación y eliminación queda registrada con su autor.

Cambios

  • v1 · 2026-09

    Primera versión: proyecto, miembros, incidencias, RFIs, órdenes de cambio, no conformidades, reuniones y formularios en solo lectura.