Saltar al contenido

Desarrolladores

API de Wislab

Conecta tu academia con tus sistemas: sincroniza personas desde tu RRHH o CRM, lee cursos, progreso, certificados, inscripciones y pagos, y lleva leads a tu CRM.

URL base
https://wislab.app/api/v1
Versión
v1 · 1.0.0
Descargar OpenAPI

La API viene en los planes Cohortes y Empresa.

Introducción

La API de Wislab es REST: URLs por recurso, JSON en las peticiones y en las respuestas, y códigos HTTP normales.

Cada petición actúa sobre una sola academia: la de la API key que uses. La academia nunca va en la URL.

El contrato completo está en OpenAPI 3.0. Impórtalo en Postman, Insomnia o tu generador de clientes.

URL base
https://wislab.app/api/v1

Autenticación

  1. 1En el panel de tu academia, entra a Ajustes > Integraciones > Claves de API. Solo el dueño de la academia o un admin pueden crearla.
  2. 2Elige los scopes que necesita tu integración. La key se muestra una sola vez: guárdala en tu gestor de secretos.
  3. 3Envía la key en el header Authorization: Bearer de cada petición.

Tu key es un secreto

Úsala solo desde tu servidor. Nunca la pongas en el navegador, en una app móvil ni en un repositorio. Si se filtra, revócala en el mismo panel y crea otra.

Petición
curl https://wislab.app/api/v1/academy \
  -H "Authorization: Bearer $WISLAB_API_KEY"

Scopes

Cada key trae solo los scopes que le diste. Usa una key por integración: así puedes revocar una sin tocar las demás.

Scopes
ScopeQué permite
users:readLeer las personas de la academia y su perfil.
users:syncDar de alta, actualizar y desactivar personas desde tu sistema.
courses:readLeer el catálogo de cursos.
progress:readLeer el avance de cada persona en sus cursos.
completions:readLeer quién terminó cada curso y cuándo.
certificates:readLeer los certificados emitidos.
bootcamps:readLeer los bootcamps: fechas, precios y cupos.
enrollments:readLeer quién está inscrito en cada bootcamp.
payments:readLeer compras de cursos y talleres, y recibos de pago.
crm:readLeer contactos y negocios del CRM.
crm:writeCrear y actualizar contactos del CRM.
fields:readLeer campos personalizados y sus valores.
fields:writeEscribir valores de campos personalizados.

GET /academy no necesita scope: cualquier key válida lo lee.

Respuesta 403
{
  "error": "FORBIDDEN",
  "message": "API key lacks required scope: users:read."
}

Paginación

Los listados reciben page (empieza en 0) y limit (20 por defecto, hasta 100).

La respuesta trae data con los resultados, total, page y pageCount. Sigue pidiendo páginas hasta que page llegue a pageCount - 1.

Petición
curl "https://wislab.app/api/v1/courses?page=1&limit=50" \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    "…"
  ],
  "total": 132,
  "page": 1,
  "pageCount": 3
}

Errores

Un error responde con un código HTTP y un JSON con error (un código estable que puedes usar en tu código), message y, a veces, details.

Errores
CódigoHTTPQué significa
VALIDATION_ERROR400Un parámetro o el body no es válido. details dice cuál.
UNKNOWN_FIELD400Escribiste un campo personalizado que no tiene definición.
LIMIT_REACHED400La academia llegó a un límite de su plan.
UNAUTHORIZED401Falta la API key, está mal formada o fue revocada.
FORBIDDEN403La key no tiene el scope, o el plan no incluye la API.
NAMESPACE_FORBIDDEN403Intentaste escribir campos de otro namespace.
NOT_FOUND404El recurso no existe en esta academia.
CONFLICT409Ya existe un recurso con esa clave.
CRM_DISABLED409La academia tiene el CRM apagado.
RATE_LIMITED429Pasaste el límite de uso. Espera Retry-After segundos.
INTERNAL500Algo falló de nuestro lado. Reintenta en unos segundos.
Respuesta 400
{
  "error": "VALIDATION_ERROR",
  "details": {
    "errors": [],
    "properties": {
      "limit": {
        "errors": [
          "Too small: expected number to be >=1"
        ]
      }
    }
  }
}

Límites de uso

Cada key puede hacer 120 peticiones por minuto. Si te pasas, recibes 429 RATE_LIMITED con el header Retry-After: espera esos segundos y reintenta.

Respuesta 429
HTTP/1.1 429 Too Many Requests
Retry-After: 18

{ "error": "RATE_LIMITED", "message": "Rate limit exceeded." }

Referencia

Academia

La academia detrás de la key o del token.

GET/v1/academy

Obtener la academia

No necesita scope: cualquier API key o token de instalación válido la lee. Nombre, slug, dominio, idiomas, moneda, plan y marca; nunca personas.

Scope:Sin scope

Respuestas

  • 200La academia.
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/academy \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "name": "Academia Ejemplo",
    "slug": "fundamentos-de-fotografia",
    "domain": "string",
    "url": "https://academia.example.com",
    "defaultLocale": "string",
    "supportedLocales": [
      "string"
    ],
    "currency": "USD",
    "package": "string",
    "logoUrl": "https://academia.example.com",
    "primaryColor": "string"
  }
}

Referencia

Usuarios

Las personas de la academia y la sincronización desde tus sistemas.

GET/v1/users

Listar usuarios

Requiere el scope users:read.

Scope:users:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • rolestringopcional

    Filtra por rol.

    Uno de: owner, admin, manager, teacher, moderator, student

  • searchstringopcional

    Busca en nombre, apellido y email.

Respuestas

  • 200Una página de usuarios.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/users \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "email": "ana@example.com",
      "firstName": "Ana",
      "lastName": "García",
      "username": "anagarcia",
      "role": "owner",
      "isBanned": false,
      "createdAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}
GET/v1/users/{id}

Obtener un usuario

Requiere el scope users:read.

Scope:users:read

Parámetros de ruta

  • idstringobligatorio

    El ID del usuario.

Respuestas

  • 200El usuario.
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay un usuario con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/users/clx8k2m0p0001 \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "email": "ana@example.com",
    "firstName": "Ana",
    "lastName": "García",
    "username": "anagarcia",
    "role": "owner",
    "isBanned": false,
    "createdAt": "2026-10-27T15:00:00.000Z"
  }
}
POST/v1/users/sync

Sincronizar usuarios

Da de alta, actualiza y desactiva estudiantes desde tu sistema de RRHH o CRM, hasta 500 por petición. Idempotente por email. status: inactive desactiva (se puede revertir). Solo maneja estudiantes: un email del equipo se reporta como omitido. Requiere el scope users:sync.

Scope:users:sync

Body

  • usersobject[]obligatorio
    • emailstringobligatorio
    • externalIdstringopcional

      El ID en tu sistema de origen (número de empleado, RFC). Se guarda en los metadatos de la persona.

    • firstNamestringopcional
    • lastNamestringopcional
    • rolestringopcional

      Uno de: student

    • statusstringopcional

      inactive desactiva a la persona (se puede revertir) y conserva su historial.

      Uno de: active, inactive

  • optionsobjectopcional
    • dryRunbooleanopcional

      Valida y reporta sin escribir nada.

    • sendWelcomeEmailbooleanopcional

Respuestas

  • 200El resultado de la sincronización.
  • 400Body inválido (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl -X POST https://wislab.app/api/v1/users/sync \
  -H "Authorization: Bearer $WISLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "users": [
    {
      "email": "ana@example.com",
      "externalId": "EMP-1042",
      "firstName": "Ana",
      "lastName": "García",
      "role": "student",
      "status": "active"
    }
  ],
  "options": {
    "dryRun": false,
    "sendWelcomeEmail": false
  }
}'
Respuesta 200
{
  "data": {
    "processed": 1,
    "created": 1,
    "updated": 1,
    "deactivated": 1,
    "skipped": 1,
    "dryRun": false,
    "errors": [
      {
        "index": 1,
        "email": "ana@example.com",
        "reason": "Invalid email."
      }
    ],
    "importLogId": "clx8k2m0p0002"
  }
}

Referencia

Cursos

El catálogo de cursos.

GET/v1/courses

Listar cursos

Requiere el scope courses:read.

Scope:courses:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • isPublishedstringopcional

    Filtra por estado de publicación.

    Uno de: true, false

Respuestas

  • 200Una página de cursos.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/courses \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "title": "Fundamentos de fotografía",
      "slug": "fundamentos-de-fotografia",
      "description": null,
      "courseType": "course",
      "level": "basic",
      "monetizationType": "free",
      "priceInCents": 4900,
      "currency": "USD",
      "isPublished": true,
      "totalCapsules": 1,
      "createdAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}

Referencia

Progreso

El progreso de cada estudiante.

GET/v1/users/{id}/progress

Obtener el progreso de un usuario

Progreso por curso. Requiere el scope progress:read.

Scope:progress:read

Parámetros de ruta

  • idstringobligatorio

    El ID del usuario.

Respuestas

  • 200El progreso del usuario por curso.
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay un usuario con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/users/clx8k2m0p0001/progress \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": {
    "userId": "clx8k2m0p0002",
    "lessonsCompletedTotal": 1,
    "courses": [
      {
        "courseId": "clx8k2m0p0002",
        "percentageProgress": 60,
        "isEnrolled": true,
        "updatedAt": "2026-10-27T15:00:00.000Z"
      }
    ]
  }
}

Referencia

Cursos completados

Cursos completados.

GET/v1/completions

Listar cursos completados

Cursos que un estudiante terminó al 100%. Requiere el scope completions:read.

Scope:completions:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • fromdatetimeopcional

    Fecha ISO 8601 inclusiva, contra la fecha de completado.

  • todatetimeopcional

    Fecha ISO 8601 inclusiva.

Respuestas

  • 200Una página de cursos completados.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/completions \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "userId": "clx8k2m0p0002",
      "courseId": "clx8k2m0p0002",
      "completedAt": "2026-10-27T15:00:00.000Z",
      "certificateId": "clx8k2m0p0002"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}

Referencia

Certificados

Certificados emitidos.

GET/v1/certificates

Listar certificados

Requiere el scope certificates:read.

Scope:certificates:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • statusstringopcional

    Filtra por estado.

    Uno de: active, revoked

  • userIdstringopcional

    Filtra por usuario.

Respuestas

  • 200Una página de certificados.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/certificates \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "userId": "clx8k2m0p0002",
      "courseId": "clx8k2m0p0002",
      "pathId": "clx8k2m0p0002",
      "bootcampId": "clx8k2m0p0002",
      "programId": "clx8k2m0p0002",
      "credentialCode": "WSL-7F3K-2Q9P",
      "issuedAt": "2026-10-27T15:00:00.000Z",
      "expiresAt": "2026-10-27T15:00:00.000Z",
      "status": "active",
      "certificateUrl": "https://academia.example.com/certificates/WSL-7F3K-2Q9P",
      "recipientName": "Ana García"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}

Referencia

Bootcamps

Los bootcamps de la academia.

GET/v1/bootcamps

Listar bootcamps

Requiere el scope bootcamps:read.

Scope:bootcamps:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • isListedstringopcional

    Filtra por visibilidad en el catálogo.

    Uno de: true, false

  • isActivestringopcional

    Filtra por estado activo.

    Uno de: true, false

Respuestas

  • 200Una página de bootcamps.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/bootcamps \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "title": "Fundamentos de fotografía",
      "slug": "fundamentos-de-fotografia",
      "cohortStartDate": "2026-10-27T15:00:00.000Z",
      "cohortEndDate": "2026-10-27T15:00:00.000Z",
      "enrollmentDeadline": null,
      "isFree": false,
      "regularPrice": 1,
      "earlyBirdPrice": 1,
      "currency": "USD",
      "maxStudents": 1,
      "isActive": true,
      "isEnrollmentOpen": false,
      "isListed": true,
      "createdAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}

Referencia

Inscripciones

Inscripciones a bootcamps.

GET/v1/enrollments

Listar inscripciones a bootcamps

Requiere el scope enrollments:read.

Scope:enrollments:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • bootcampIdstringopcional

    Filtra por bootcamp.

  • userIdstringopcional

    Filtra por usuario.

  • statusstringopcional

    Filtra por estado.

    Uno de: active, expired, completed, refunded, removed

Respuestas

  • 200Una página de inscripciones.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/enrollments \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "userId": "clx8k2m0p0002",
      "bootcampId": "clx8k2m0p0002",
      "status": "active",
      "enrollmentDate": "2026-10-27T15:00:00.000Z",
      "amount": 490,
      "currency": "USD",
      "isManualAssignment": false,
      "createdAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}

Referencia

Pagos

Compras de cursos y talleres, y recibos de pago.

GET/v1/payments

Listar compras de cursos y talleres

Requiere el scope payments:read.

Scope:payments:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • kindstringopcional

    Filtra por lo que se compró.

    Uno de: course, workshop

  • userIdstringopcional

    Filtra por usuario.

  • statusstringopcional

    Filtra por estado.

Respuestas

  • 200Una página de compras.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/payments \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "kind": "course",
      "itemId": "clx8k2m0p0002",
      "userId": "clx8k2m0p0002",
      "amount": 490,
      "currency": "USD",
      "status": "active",
      "stripeSessionId": "cs_live_a1B2c3D4",
      "refundedAt": "2026-10-27T15:00:00.000Z",
      "createdAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}
GET/v1/payments/receipts

Listar recibos de pago

Requiere el scope payments:read.

Scope:payments:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • userIdstringopcional

    Filtra por usuario.

  • enrollmentIdstringopcional

    Filtra por inscripción.

  • paymentStatusstringopcional

    Filtra por estado de pago.

Respuestas

  • 200Una página de recibos.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/payments/receipts \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "userId": "clx8k2m0p0002",
      "enrollmentId": "clx8k2m0p0002",
      "programEnrollmentId": "clx8k2m0p0002",
      "amount": 490,
      "currency": "USD",
      "paymentStatus": "paid",
      "paymentMethod": "card",
      "paidAt": "2026-10-27T15:00:00.000Z",
      "description": null,
      "isRefunded": false,
      "isCancelled": false,
      "createdAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}

Referencia

CRM

Contactos y negocios del CRM.

GET/v1/crm/contacts

Listar contactos del CRM

Requiere el scope crm:read.

Scope:crm:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • lifecycleStagestringopcional

    Filtra por etapa del embudo.

  • sourcestringopcional

    Filtra por origen.

  • updatedAfterdatetimeopcional

    Solo contactos modificados después de esta fecha ISO 8601.

Respuestas

  • 200Una página de contactos.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/crm/contacts \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "email": "ana@example.com",
      "phone": "+52 55 0000 0000",
      "firstName": "Ana",
      "lastName": "García",
      "jobTitle": null,
      "lifecycleStage": "SUBSCRIBER",
      "source": "SIGNUP",
      "sourceDetail": "Formulario del taller",
      "score": 1,
      "companyId": "clx8k2m0p0002",
      "tenantUserId": "clx8k2m0p0002",
      "lastContactedAt": "2026-10-27T15:00:00.000Z",
      "createdAt": "2026-10-27T15:00:00.000Z",
      "updatedAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}
POST/v1/crm/contacts

Crear o actualizar un contacto del CRM

Pasa por la misma entrada que los formularios de la academia: deduplica por email, la etapa del embudo solo avanza, abre un negocio si la academia los crea solos y emite lead.created cuando el contacto es nuevo. 201 si es nuevo, 200 si ya existía. 409 CRM_DISABLED si la academia tiene el CRM apagado. Requiere el scope crm:write.

Scope:crm:write

Body

  • emailstringobligatorio
  • firstNamestring | nullopcional
  • lastNamestring | nullopcional
  • phonestring | nullopcional
  • sourcestringopcional

    Cómo llegó la persona. Se conserva el de la primera vez que se vio el contacto.

    Uno de: SIGNUP, NEWSLETTER, WAITLIST, CONTACT_FORM, DEMO_REQUEST, COURSE_ENROLLMENT, MANUAL, IMPORT, OTHER

  • sourceDetailstring | nullopcional

    Texto libre sobre el origen, por ejemplo el nombre del formulario o la campaña.

  • lifecycleStagestringopcional

    Un contacto existente solo avanza en el embudo.

    Uno de: SUBSCRIBER, LEAD, MQL, SQL, OPPORTUNITY, CUSTOMER, EVANGELIST, OTHER

Respuestas

  • 200El contacto ya existía y se actualizó.
  • 201Contacto creado.
  • 400Body inválido (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 409La academia tiene el CRM apagado.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl -X POST https://wislab.app/api/v1/crm/contacts \
  -H "Authorization: Bearer $WISLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "ana@example.com",
  "firstName": "Ana",
  "lastName": "García",
  "phone": "+52 55 0000 0000",
  "source": "OTHER",
  "sourceDetail": "Formulario del taller",
  "lifecycleStage": "LEAD"
}'
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "email": "ana@example.com",
    "phone": "+52 55 0000 0000",
    "firstName": "Ana",
    "lastName": "García",
    "jobTitle": null,
    "lifecycleStage": "SUBSCRIBER",
    "source": "SIGNUP",
    "sourceDetail": "Formulario del taller",
    "score": 1,
    "companyId": "clx8k2m0p0002",
    "tenantUserId": "clx8k2m0p0002",
    "lastContactedAt": "2026-10-27T15:00:00.000Z",
    "createdAt": "2026-10-27T15:00:00.000Z",
    "updatedAt": "2026-10-27T15:00:00.000Z"
  }
}
GET/v1/crm/deals

Listar negocios del CRM

Requiere el scope crm:read.

Scope:crm:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • statusstringopcional

    Filtra por estado.

    Uno de: OPEN, WON, LOST

  • pipelineIdstringopcional

    Filtra por embudo.

  • contactIdstringopcional

    Filtra por contacto.

Respuestas

  • 200Una página de negocios.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/crm/deals \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "title": "Fundamentos de fotografía",
      "pipelineId": "clx8k2m0p0002",
      "stageId": "clx8k2m0p0003",
      "status": "OPEN",
      "valueCents": 4900,
      "currency": "USD",
      "contactId": "clx8k2m0p0002",
      "companyId": "clx8k2m0p0002",
      "expectedCloseDate": "2026-10-27T15:00:00.000Z",
      "wonAt": "2026-10-27T15:00:00.000Z",
      "lostAt": "2026-10-27T15:00:00.000Z",
      "createdAt": "2026-10-27T15:00:00.000Z",
      "updatedAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}

Referencia

Campos personalizados

Campos personalizados de cursos, bootcamps y rutas, y sus valores.

GET/v1/fields

Listar definiciones de campos personalizados

Incluye los campos de la academia (academy) y los de cada app instalada (app--<handle>). Requiere el scope fields:read.

Scope:fields:read

Parámetros de consulta

  • pageintegeropcional

    Número de página, empieza en 0.

  • limitintegeropcional

    Tamaño de página, hasta 100.

  • entitystringopcional

    Filtra por entidad.

    Uno de: course, bootcamp, path

Respuestas

  • 200Una página de definiciones.
  • 400Parámetros de consulta inválidos (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": [
    {
      "id": "clx8k2m0p0001",
      "entity": "course",
      "namespace": "academy",
      "key": "level",
      "fieldId": "academy:level",
      "type": "text",
      "label": {
        "en": "Level",
        "es": "Nivel"
      },
      "options": [
        {
          "value": "string",
          "label": "string"
        }
      ],
      "order": 1,
      "createdAt": "2026-10-27T15:00:00.000Z"
    }
  ],
  "total": 1,
  "page": 0,
  "pageCount": 1
}
POST/v1/fields

Declarar un campo de la app

Solo con el token de instalación de una app externa: el campo nace en el namespace app--<handle> de esa app. Una API key de la academia recibe 403; la academia define sus campos en Admin > Campos personalizados. Requiere el scope fields:write.

Scope:fields:write

Body

  • entitystringobligatorio

    Uno de: course, bootcamp, path

  • keystringobligatorio
  • typestringobligatorio

    Uno de: text, number, boolean, select, url, date

  • labelobjectobligatorio
  • optionsobject[]opcional
    • valuestringobligatorio
    • labelstringobligatorio
  • orderintegeropcional

Respuestas

  • 201La definición creada.
  • 400Body inválido (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 409Ya existe un campo con esa clave para esa entidad.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl -X POST https://wislab.app/api/v1/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "entity": "course",
  "key": "level",
  "type": "text",
  "label": {
    "en": "Level",
    "es": "Nivel"
  },
  "options": [
    {
      "value": "string",
      "label": "string"
    }
  ],
  "order": 1
}'
Respuesta 201
{
  "data": {
    "id": "clx8k2m0p0001",
    "entity": "course",
    "namespace": "academy",
    "key": "level",
    "fieldId": "academy:level",
    "type": "text",
    "label": {
      "en": "Level",
      "es": "Nivel"
    },
    "options": [
      {
        "value": "string",
        "label": "string"
      }
    ],
    "order": 1,
    "createdAt": "2026-10-27T15:00:00.000Z"
  }
}
GET/v1/courses/{id}/fields

Valores de los campos personalizados de un curso

Devuelve fields con claves namespace:key. Requiere el scope fields:read.

Scope:fields:read

Parámetros de ruta

  • idstringobligatorio

    El ID.

Respuestas

  • 200Los valores.
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay un curso con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/courses/clx8k2m0p0001/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "entity": "course",
    "fields": {
      "academy:level": "intermediate"
    }
  }
}
PATCH/v1/courses/{id}/fields

Escribir los campos personalizados de un curso

Una API key de la academia escribe solo el namespace academy; el token de instalación de una app escribe solo su app--<handle> (si no, 403 NAMESPACE_FORBIDDEN). null borra el valor; un campo sin definición responde 400 UNKNOWN_FIELD. Requiere el scope fields:write.

Scope:fields:write

Parámetros de ruta

  • idstringobligatorio

    El ID.

Body

  • fieldsobjectobligatorio

Respuestas

  • 200Los valores después del cambio.
  • 400Body inválido, campo desconocido o valor de otro tipo (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay un curso con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl -X PATCH https://wislab.app/api/v1/courses/clx8k2m0p0001/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fields": {
    "academy:level": "intermediate"
  }
}'
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "entity": "course",
    "fields": {
      "academy:level": "intermediate"
    }
  }
}
GET/v1/bootcamps/{id}/fields

Valores de los campos personalizados de un bootcamp

Devuelve fields con claves namespace:key. Requiere el scope fields:read.

Scope:fields:read

Parámetros de ruta

  • idstringobligatorio

    El ID.

Respuestas

  • 200Los valores.
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay un bootcamp con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/bootcamps/clx8k2m0p0001/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "entity": "course",
    "fields": {
      "academy:level": "intermediate"
    }
  }
}
PATCH/v1/bootcamps/{id}/fields

Escribir los campos personalizados de un bootcamp

Una API key de la academia escribe solo el namespace academy; el token de instalación de una app escribe solo su app--<handle> (si no, 403 NAMESPACE_FORBIDDEN). null borra el valor; un campo sin definición responde 400 UNKNOWN_FIELD. Requiere el scope fields:write.

Scope:fields:write

Parámetros de ruta

  • idstringobligatorio

    El ID.

Body

  • fieldsobjectobligatorio

Respuestas

  • 200Los valores después del cambio.
  • 400Body inválido, campo desconocido o valor de otro tipo (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay un bootcamp con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl -X PATCH https://wislab.app/api/v1/bootcamps/clx8k2m0p0001/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fields": {
    "academy:level": "intermediate"
  }
}'
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "entity": "course",
    "fields": {
      "academy:level": "intermediate"
    }
  }
}
GET/v1/paths/{id}/fields

Valores de los campos personalizados de una ruta

Devuelve fields con claves namespace:key. Requiere el scope fields:read.

Scope:fields:read

Parámetros de ruta

  • idstringobligatorio

    El ID.

Respuestas

  • 200Los valores.
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay una ruta con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl https://wislab.app/api/v1/paths/clx8k2m0p0001/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY"
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "entity": "course",
    "fields": {
      "academy:level": "intermediate"
    }
  }
}
PATCH/v1/paths/{id}/fields

Escribir los campos personalizados de una ruta

Una API key de la academia escribe solo el namespace academy; el token de instalación de una app escribe solo su app--<handle> (si no, 403 NAMESPACE_FORBIDDEN). null borra el valor; un campo sin definición responde 400 UNKNOWN_FIELD. Requiere el scope fields:write.

Scope:fields:write

Parámetros de ruta

  • idstringobligatorio

    El ID.

Body

  • fieldsobjectobligatorio

Respuestas

  • 200Los valores después del cambio.
  • 400Body inválido, campo desconocido o valor de otro tipo (ver details).
  • 401API key ausente, mal formada o revocada.
  • 403La key no tiene el scope necesario o el plan de la academia no incluye la API.
  • 404No hay una ruta con ese ID en esta academia.
  • 429Límite de uso excedido. Espera los segundos de Retry-After.
curl -X PATCH https://wislab.app/api/v1/paths/clx8k2m0p0001/fields \
  -H "Authorization: Bearer $WISLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fields": {
    "academy:level": "intermediate"
  }
}'
Respuesta 200
{
  "data": {
    "id": "clx8k2m0p0001",
    "entity": "course",
    "fields": {
      "academy:level": "intermediate"
    }
  }
}

¿Te falta un endpoint?

Cuéntanos qué quieres integrar y lo vemos contigo.

Escríbenos