Documentación

La API de Bookit

Conecta tu propia web o app a la agenda de tu negocio: consulta servicios, equipo y horarios libres, y crea, reprograma o cancela citas. Incluida en el plan Business Pro.

Petición
GET /api/v1/services
Host: tu-negocio.bookit.com.pe
x-api-key: bk_live_…
Respuesta 200, resumida
{
  "services": [
    {
      "slug": string,
      "name": string,
      "durationMin": number,
      "price": number | null
    }
  ]
}

Primeros pasos

Tu primera llamada

Qué puedes hacer

Con la API REST de Bookit, tu propia web o app trabaja sobre la agenda de tu negocio: muestra tus servicios y tu equipo, busca horarios libres, reserva y deja que el cliente reprograme o cancele su cita.

Las reservas pasan por el mismo motor que tu página de reservas. Se aplican tus reglas (antelación mínima, días hacia adelante, pago obligatorio) y el bloqueo que impide dos citas a la misma hora: por la API no se agenda nada que tu web no agendaría.

La API está incluida en el plan Business Pro.

Ver precios

Crea tu key

  1. 1En el panel de tu negocio, entra a Ajustes → API Keys. Solo los administradores del negocio pueden crear keys.
  2. 2Ponle un nombre y elige si será de solo lectura o de lectura y escritura. Si quieres, dale una fecha de vencimiento.
  3. 3Cópiala en ese momento. Bookit guarda solo una huella de la key y no puede volver a mostrártela.

Cada negocio puede tener hasta 10 keys activas. Para comprobar que la tuya funciona, pide el índice de la API: responde con tu negocio, los permisos de la key y la lista de recursos.

Comprueba tu key
curl https://tu-negocio.bookit.com.pe/api/v1 \
  -H "x-api-key: bk_live_…"
Respuesta 200
{
  "object": "api",
  "version": "v1",
  "tenant": {
    "name": string | null,
    "subdomain": string | null,
    "plan": "STARTER" | "BUSINESS" | "BUSINESS_PRO" | "WHITE_LABEL" | null
  },
  "authentication": { "type": "api_key", "scopes": string[] },
  "rate_limit": { "limit": 100, "window": "1m" },
  "resources": string[],
  "docs": string
}

URL base y formato

  • Usa la dirección de tu negocio: https://tu-negocio.bookit.com.pe/api/v1, o tu dominio propio si lo tienes. La key ya indica de qué negocio se trata.
  • Peticiones y respuestas en JSON. Fechas y horas en ISO 8601, en UTC.
  • Cada respuesta lleva la cabecera X-API-Version: v1.
  • La API acepta llamadas desde el navegador, pero una key escrita en el código de una página queda a la vista de cualquiera. Llámala desde tu servidor.

Reglas de uso

Autenticación, límites y errores

Autenticación

Manda la key en la cabecera x-api-key. Si tu cliente HTTP solo admite Authorization, también vale Authorization: Bearer bk_live_….

Petición autenticada
GET /api/v1/locations
Host: tu-negocio.bookit.com.pe
x-api-key: bk_live_…

Las keys empiezan por bk_live_ y siguen con 64 caracteres. Si la key no existe, está desactivada o venció, la respuesta es 401. Guárdala como una contraseña: cualquier key activa de tu negocio puede crear y cancelar citas.

Límites

  • Negocio, sedes, servicios, profesionales, horarios y citas: 100 peticiones por minuto por key.
  • Índice, métricas y contenido: 120 lecturas y 20 escrituras por minuto por key, en una cuenta aparte.
  • Si te pasas, la respuesta es 429 con el código RATE_LIMIT_EXCEEDED. Espera un minuto y vuelve a intentarlo.
  • No hay paginación. /services y /providers aceptan limit (hasta 60; 24 si no lo indicas) y el resto de listas devuelve todo lo publicado.

Errores

Todos los errores tienen la misma forma. En las reglas de reserva, code y message traen la misma clave estable, pensada para que tu código decida qué hacer sin interpretar frases.

Respuesta 409
{
  "error": {
    "code": "slotTaken",
    "message": "slotTaken"
  }
}
  • 400VALIDATION_ERROR

    Faltan datos o no tienen el formato esperado; issues trae el detalle.

  • 400Clave de la regla

    La reserva no cumple una regla del negocio: slotNotAvailable, tooEarlyToBook, outsideBookingWindow, paymentRequiredToBook, tooLateToChange, invalidToken…

  • 401UNAUTHORIZED

    Falta la key, no existe, está desactivada o venció.

  • 403FORBIDDEN

    Escribir contenido sin la sesión de un administrador del negocio.

  • 404NOT_FOUND o clave

    No existe en este negocio: serviceNotBookable, locationNotFound, appointmentNotFound…

  • 409slotTaken

    Ese horario se ocupó un instante antes, o no queda sala ni equipo libre (resourceBusy).

  • 429RATE_LIMIT_EXCEEDED

    Pasaste el límite de peticiones por minuto.

  • 500INTERNAL_ERROR

    Error del servidor. Vuelve a intentarlo más tarde.

Referencia

Endpoints

Negocio y sedes

Empieza por aquí: /business trae las reglas con las que el servidor acepta o rechaza una reserva.

GET/api/v1/business

Datos públicos del negocio y sus reglas de reserva: zona horaria, moneda, antelación mínima, días hacia adelante, plazo para cambios y si el plan permite cobrar online (onlinePayment).

Respuesta 200
{
  "business": {
    "tenantId": string,
    "displayName": string,
    "timezone": string,
    "defaultCurrency": "PEN" | "USD" | "EUR" | "GBP" | "CLP" | "MXN",
    "vertical": "MEDICAL" | "BEAUTY" | "WELLNESS" | "FITNESS" | "LEGAL" | "GENERIC",
    "logoUrl": string | null,
    "primaryColor": string | null,
    "bookingWindowDays": number,
    "bookingMinNoticeMin": number,
    "requirePaymentToBook": boolean,
    "cancellationWindowMin": number,
    "phone": string | null,
    "onlinePayment": boolean
  }
}

GET/api/v1/locations

Sedes activas. Toda reserva ocurre en una sede, y cada sede tiene su propia zona horaria.

Respuesta 200
{
  "locations": [
    {
      "id": string,
      "name": string,
      "address": string | null,
      "city": string | null,
      "timezone": string
    }
  ]
}

Horarios libres

Los horarios libres no se guardan: se calculan en cada consulta con la agenda, las citas y los bloqueos del negocio.

GET/api/v1/availability

Horarios libres de un servicio en una sede, dentro de un rango de fechas. Ya descuenta la antelación mínima del negocio.

Parámetros de la URL

locationIdobligatorio
Id de la sede.
serviceIdobligatorio
Id del servicio.
providerId
Solo los de esa profesional. Sin él, llegan los de todas.
fromobligatorio
Inicio del rango, en ISO 8601.
toobligatorio
Fin del rango. Tiene que ser posterior a from.
Petición
GET /api/v1/availability?locationId=…&serviceId=…&from=2026-09-15&to=2026-09-22
Respuesta 200
{
  "service": { "id": string, "name": string, "durationMin": number },
  "timezone": string,
  "slots": [
    {
      "providerId": string,
      "start": string,
      "end": string,
      "remaining"?: number
    }
  ]
}

start y end van en UTC y timezone es la zona de la sede: conviértelas antes de mostrarlas. remaining solo aparece en clases grupales y dice cuántos cupos quedan.

Reservar

Una reserva necesita sede, servicio, profesional, un horario de /availability y los datos del cliente.

POST/api/v1/appointments

Crea la cita con las reglas de tu negocio. Si dos personas piden el mismo horario a la vez, solo una lo consigue.

Cuerpo JSON

locationIdobligatorio
Id de la sede.
serviceIdobligatorio
Id del servicio.
providerIdobligatorio
Id de la profesional.
startAtobligatorio
Inicio en ISO 8601 UTC. Tiene que coincidir con un start de /availability.
customerobligatorio
firstName obligatorio; lastName, email y phone, opcionales. Hace falta email o teléfono.
customerNotes
Nota del cliente, hasta 1000 caracteres.
payOnline
true para cobrar al reservar, solo en servicios de precio cerrado. Si el negocio exige pago (requirePaymentToBook) y no lo envías, responde paymentRequiredToBook.
returnUrl
Dirección a la que vuelve el cliente después de pagar.
Petición
POST /api/v1/appointments
x-api-key: bk_live_…
Content-Type: application/json

{
  "locationId": "…",
  "serviceId": "…",
  "providerId": "…",
  "startAt": "2026-09-17T21:30:00.000Z",
  "customer": { "firstName": "Andrea", "email": "andrea@correo.com" }
}
Respuesta 201
{
  "appointmentId": string,
  "startAt": string,
  "endAt": string,
  "checkoutUrl": string | null,
  "manageToken": string
}

Guarda manageToken: con él se ve, reprograma o cancela la cita sin cuenta. checkoutUrl solo llega si pediste payOnline y se pudo abrir el pago; antes de ofrecerlo, revisa onlinePayment en /business.

Ver, reprogramar o cancelar

Con el manageToken de la reserva, sin cuenta de cliente. El token va firmado, lleva el negocio dentro y vence a los 90 días.

GET/api/v1/appointments/{token}

Estado y datos de la cita.

Respuesta 200
{
  "appointment": {
    "id": string,
    "startAt": string,
    "endAt": string,
    "status": "REQUESTED" | "CONFIRMED" | "RESCHEDULED" | "COMPLETED" | "CANCELLED" | "NO_SHOW",
    "serviceId": string,
    "providerId": string,
    "locationId": string,
    "priceSnapshot": string | null,
    "currency": string | null,
    "service": { "name": string, "durationMin": number, "onlineBookable": boolean },
    "provider": { "displayName": string },
    "location": { "name": string, "timezone": string },
    "customer": { "firstName": string },
    "cancellationWindowMin": number
  }
}

PATCH/api/v1/appointments/{token}

Mueve la cita a otro horario libre y, si quieres, a otra profesional de la misma sede.

Cuerpo JSON

startAtobligatorio
Nuevo inicio en ISO 8601 UTC, dentro de la disponibilidad real.
providerId
Otra profesional que haga el servicio y atienda en esa sede.
Respuesta 200
{ "ok": true, "startAt": string }

DELETE/api/v1/appointments/{token}

Cancela la cita.

Cuerpo JSON

reason
Motivo, hasta 500 caracteres. Opcional.
Respuesta 200
{ "ok": true }

Reprogramar y cancelar respetan el plazo del negocio: con menos antelación que cancellationWindowMin responde tooLateToChange, y una cita cancelada, completada o marcada como inasistencia responde appointmentNotEditable.

Contenido del sitio

Para mostrar en otra web las páginas que el negocio arma en Bookit.

GET/api/v1/site/pages

Páginas publicadas del sitio del negocio.

Respuesta 200
{
  "pages": [
    {
      "slug": string,
      "title": string,
      "language": "ES" | "EN" | "PT" | "FR" | "DE",
      "updatedAt": string
    }
  ]
}

GET/api/v1/site/pages/{slug}

Una página lista para pintar: contenido, encabezado, pie, marca y estilos. Las imágenes llegan con su dirección completa; los enlaces del menú, relativos.

Parámetros de la URL

language
Idioma. Si el sitio no está en varios idiomas, llega en español.
sections
Solo estas secciones, por su ancla y en ese orden, separadas por comas.
exclude
Todas las secciones menos estas.
Respuesta 200
{
  "page": {
    "slug": string,
    "title": string,
    "language": string,
    "updatedAt": string,
    "content": object
  },
  "header": object | null,
  "footer": object | null,
  "branding": object | null,
  "styles": { "fontLinks": string[], "css": string },
  "origin": string
}

GET/api/v1/cms/pages

Páginas de contenido creadas para la API. No incluye las páginas del sitio.

Parámetros de la URL

language
ES, EN, PT, FR o DE. Si no lo indicas, ES.
Respuesta 200
{
  "data": [
    {
      "id": string,
      "title": string,
      "slug": string,
      "language": string,
      "content": object,
      "isPublished": boolean,
      "updatedAt": string
    }
  ],
  "meta": { "total": number, "language": string }
}

GET/api/v1/cms/pages/{slug}

Una de esas páginas por su slug, con los mismos campos. Acepta el mismo language.

Respuesta 200
{ "data": { … } }

Crear, editar o borrar páginas (POST /cms/pages, PATCH y DELETE /cms/pages/{slug}) pide, además de la key, la sesión iniciada de un administrador del negocio. Las plantillas de sección se leen en GET /cms/sections y GET /cms/sections/{id}.

Métricas

Tres totales del negocio, para un tablero propio.

GET/api/v1/stats

Cuentas de usuario activas en el negocio, pedidos y el monto de los pagos completados.

Respuesta 200
{
  "data": {
    "members": { "total": number },
    "orders": { "total": number },
    "revenue": { "completed": number }
  }
}

revenue.completed suma los montos tal como se cobraron, sin convertir entre monedas.

Webhooks

Bookit no envía webhooks. Para saber si una cita cambió, consúltala con GET /api/v1/appointments/{token}.

¿Vas a conectar tu negocio?

Crea tu cuenta gratis o cuéntanos qué necesitas integrar.

Documentación de la API | Bookit — Gestiona tus citas