Centro de ayuda›Desarrolladores›Operaciones de clientes

Operaciones de clientes

Lista, consulta, crea, edita, borra e importa fichas de cliente por API v1 o MCP.

Un «cliente» es la ficha de cada persona que reserva contigo: nombre, contacto, documento, dirección, etiquetas y notas internas. Es distinto del usuario del panel: aquí hablamos de quien compra, no de quien administra la cuenta. Para ver esta ficha desde el panel, consulta Ver el perfil y el historial de un cliente.

Operaciones de esta página: list-clients, get-client, create-client, update-client, delete-client, import-clients (solo lectura: list-clients, get-client; escritura: las otras cuatro).

Las bases comunes (autenticación, GET frente a POST, prueba en seco, errores HTTP, límites) están en API v1 — Introducción y primeros pasos. La página API pública — Clientes (customerClients) documenta la consulta de estas mismas fichas por la API anterior de Buky; esta página es la de la API v1 actual, con más operaciones (alta, edición, borrado e importación).

En todas las operaciones, customer_id es opcional: se toma de tu token salvo que uses un token multicuenta.

list-clients: lista los clientes de tu cuenta

Es una operación de solo lectura. Devuelve la lista completa de clientes (pagina internamente hasta agotar la colección) en formato compacto, con filtros opcionales.

Cómo llamarla

curl "https://api.bukyapp.com/v1/ops/list-clients?q=garcia&limit=20" \
  -H "Authorization: Bearer bk_TU_TOKEN"

Por MCP: «Lista mis clientes cuyo nombre o email contenga García».

Parámetros

ParámetroTipoNivelQué hace
qtextoopcionalFiltro por nombre+apellido o email (contiene, sin tildes). Se aplica tras traer toda la lista.
emailtextoopcionalFiltro solo por email (contiene, sin tildes). Combinable con q.
dnitextoopcionalFiltro por número de documento (contiene). Es el mismo filtro que el documento en el panel.
marketingbooleanoopcionaltrue para ver solo los clientes que han dado su consentimiento de marketing.
tagtextoopcionalFiltro por etiqueta (contiene, sin tildes).
created_from, created_tofechaopcionalRango sobre la fecha de alta (ISO).
fullbooleanoopcionaltrue devuelve la ficha completa de cada cliente en vez de la vista compacta. Por defecto false.
limitnúmeroopcionalRecorta el resultado a los N primeros (orden alfabético), después de aplicar los filtros.

Qué devuelve

Ejemplo real, recortado y con datos anonimizados:

{
  "success": true,
  "customer_id": "5a55fff67e9fe0036a541d15",
  "count": 5,
  "total": 12,
  "items": [
    {
      "_id": "69a6cbb1afbedf1dee60bd06",
      "name": "Laura",
      "surname": "Gómez",
      "email": "laura@example.com",
      "phone": "+34600000000",
      "dni": null,
      "lang": "es",
      "createdAt": "2026-03-03T11:53:21.052Z"
    },
    "..."
  ]
}
CampoSignificado
countClientes devueltos en esta respuesta (tras filtros y limit).
totalTotal de clientes que casan los filtros de la llamada, antes de aplicar limit.
itemsVista compacta por defecto (_id, name, surname, email, phone, dni, lang, createdAt); ficha completa con full:true.

Consejos

  • Un filtro sin coincidencias devuelve count: 0 y items: [], no un error.
  • Para la ficha completa de un solo cliente es mejor get-client: aquí full:true trae la ficha completa de todos, más pesado.

get-client: ficha completa de un cliente

Es una operación de solo lectura. Resuelve un cliente por nombre o _id y devuelve el documento completo y fresco del servidor: es la forma de comprobar cómo quedó una ficha tras crearla o editarla.

Cómo llamarla

curl "https://api.bukyapp.com/v1/ops/get-client?client=Laura%20G%C3%B3mez" \
  -H "Authorization: Bearer bk_TU_TOKEN"

Por MCP: «Enséñame la ficha del cliente Laura Gómez».

Parámetros

ParámetroTipoNivelQué hace
clienttextoobligatorioNombre o _id del cliente. El manual lo marca como «recomendado», pero en la práctica es obligatorio: sin él, la operación devuelve error (client_intent_required). Acepta los alias id y client_id.

Qué devuelve

Ejemplo real, recortado y con datos anonimizados:

{
  "success": true,
  "_id": "60b09285dac98f1b2514856d",
  "resolved": { "id": "60b09285dac98f1b2514856d", "reason": "match por _id" },
  "item": {
    "_id": "60b09285dac98f1b2514856d",
    "name": "Laura",
    "surname": "Gómez",
    "email": "laura@example.com",
    "phone": "+34600000000",
    "country": "ES",
    "state": "M",
    "city": "Madrid",
    "street_address": "Calle Mayor 1",
    "zip": "28013",
    "tags": [],
    "check_marketing": false,
    "lang": "es",
    "createdAt": "2021-05-28T06:49:41.493Z"
  }
}
CampoSignificado
resolvedQué cliente se eligió a partir de lo que diste y por qué. Compruébalo si el nombre era ambiguo.
itemFicha completa: además de los campos de contacto, incluye documento, dirección, nacionalidad, notas internas y etiquetas cuando los tiene.

Errores propios

SituaciónRespuesta
Falta clientsuccess: false, error: "client_intent_required".
Nombre que no coincide con ningún clientesuccess: false, error: "client_unresolved" y client_candidates con toda tu lista de clientes para que elijas.

create-client: da de alta un cliente

Es una operación de escritura. Crea una ficha nueva con los datos básicos y, opcionalmente, el resto de la ficha completa (documento, dirección, notas, etiquetas). El script de esta guía fuerza siempre dry_run:true: no hay forma de crear un cliente de verdad con él.

Cómo llamarla

curl -X POST https://api.bukyapp.com/v1/ops/create-client \
  -H "Authorization: Bearer bk_TU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Laura", "surname": "Gómez", "email": "laura@example.com", "phone": "+34 600 00 00 00", "profile": "contactable", "dry_run": true}'

Por MCP: «Da de alta un cliente nuevo: Laura Gómez, laura@example.com, 600 00 00 00».

Parámetros

ParámetroTipoNivelQué hace
nametextoobligatorioNombre del cliente.
surnametextoopcionalApellidos.
emailtextorecomendadoEmail. Obligatorio si `profile` es `"contactable"`: sin él, la operación devuelve error email_required.
phonetextoopcionalTeléfono. Se normaliza a formato internacional (+34600000000).
langtextorecomendadoIdioma de la ficha y de los emails ("es", "en"…). Por defecto "es".
profiletextorecomendado"lead" (por defecto, captura mínima) o "contactable" (cliente operativo para reservas, exige email).
origintextoopcionalProcedencia: manual (por defecto), checkin, import, booker, migration.
formsarrayopcionalFormularios a vincular, por nombre o identificador.
document_type, dnitextoopcionalTipo (ID Card, Passport, Driver license, Other) y número de documento.
birthdayfechaopcionalFecha de nacimiento (AAAA-MM-DD).
gendertextoopcionalGénero.
street_address, country, state, city, ziptextoopcionalDirección. country y nationality aceptan nombre o código; se guarda el código.
nationalitytextoopcionalNacionalidad.
check_marketingbooleanoopcionalConsentimiento de marketing.
customer_notestextoopcionalNotas internas, no visibles para el cliente.
tagsarrayopcionalEtiquetas del cliente.

Qué devuelve

Respuesta real de la prueba en seco, para un alta mínima con perfil operativo:

{
  "success": true,
  "dry_run": true,
  "resolved_profile": { "profile": "contactable", "requiresEmail": true, "reason": "match exacto 'contactable'" },
  "resolved_lang": { "lang": "es", "reason": "default (es)" },
  "payload_preview": {
    "name": "Laura",
    "surname": "Gómez",
    "email": "laura@example.com",
    "phone": "+34600000000",
    "origin": "manual",
    "lang": "es"
  },
  "warnings": []
}
CampoSignificado
resolved_profilePerfil aplicado (lead o contactable) y por qué.
resolved_langIdioma aplicado; si no coincide con los idiomas activos de tu cuenta, aparece un aviso informativo en warnings, no un error.
payload_previewLo que se enviaría a crear, ya normalizado (teléfono, país…).

Errores propios

SituaciónRespuesta
profile: "contactable" sin emailsuccess: false, error: "email_required".
Sin name400, error: "invalid_params" con el campo que falta.

Consejos

  • Si vas a crear un cliente para que pueda reservar, usa profile: "contactable" y no olvides el email.
  • Para altas con ficha completa (por ejemplo, migrando datos de otra herramienta), añade origin: "import".

update-client: edita una ficha existente

Es una operación de escritura. Cambia solo los campos que le pases; el resto de la ficha queda intacta. El script fuerza dry_run:true siempre.

Cómo llamarla

curl -X POST https://api.bukyapp.com/v1/ops/update-client \
  -H "Authorization: Bearer bk_TU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client": "laura@example.com", "tags": ["VIP", "buceador"], "customer_notes": "Cliente recurrente, prefiere mañanas.", "dry_run": true}'

Por MCP: «Añade la etiqueta VIP a Laura Gómez y anota que prefiere las mañanas».

Parámetros

ParámetroTipoNivelQué hace
clienttextoobligatorioCliente a editar: nombre completo, email o _id.
name, surnametextorecomendado / opcionalNuevo nombre y apellidos.
email, phonetextoopcionalNuevo email y teléfono (se normaliza a formato internacional).
langtextoopcionalNuevo idioma de la ficha.
document_type, dnitextoopcionalTipo y número de documento.
birthday, genderfecha / textoopcionalFecha de nacimiento y género.
street_address, country, state, city, zip, nationalitytextoopcionalDirección y nacionalidad.
check_marketingbooleanoopcionalConsentimiento de marketing.
customer_notestextoopcionalNotas internas.
tagsarrayopcionalSustituye el conjunto entero de etiquetas, no lo añade: si quieres conservar una etiqueta previa, inclúyela en la lista.

Qué devuelve

Respuesta real de la prueba en seco:

{
  "success": true,
  "dry_run": true,
  "_id": "60b09285dac98f1b2514856d",
  "changes": {
    "customer_notes": "Cliente recurrente, prefiere mañanas.",
    "tags": ["VIP", "buceador"]
  },
  "note": "PUT parcial: solo estos campos cambian; customer/_id/__v nunca se envían."
}
CampoSignificado
changesExactamente los campos que se van a modificar, ya normalizados.

Errores propios

SituaciónRespuesta
Falta client400, error: "invalid_params", campo client marcado como required.

Consejos

  • Editar la ficha propaga los datos de contacto y dirección a las reservas ya hechas por ese cliente.
  • Como tags reemplaza la lista entera, si solo quieres añadir una etiqueta consulta antes la ficha con get-client y envía el array completo.

delete-client: elimina un cliente

Es una operación de escritura e irreversible: el cliente se borra físicamente, no hay papelera ni operación de restaurar. Al borrarlo, el servidor anonimiza su nombre en sus reservas (queda como «*Ficha borrada», las reservas siguen existiendo) y borra sus documentos y formularios subidos. El script de esta guía fuerza siempre dry_run:true, así que ni con confirm:true llega a borrar nada de verdad.

Cómo llamarla

curl -X POST https://api.bukyapp.com/v1/ops/delete-client \
  -H "Authorization: Bearer bk_TU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"client": "laura@example.com", "confirm": true}'

Por MCP: «Borra la ficha del cliente Laura Gómez» (el asistente te avisará del carácter irreversible antes de confirmar).

Parámetros

ParámetroTipoNivelQué hace
clienttextoobligatorioCliente a borrar: nombre completo, email o _id.
confirmbooleanorecomendadoDebe ser true para borrar de verdad; sin él, la operación se queda en modo de prueba.

Qué devuelve

Prueba en seco real, con confirm: true:

{
  "success": true,
  "dry_run": true,
  "would_delete": { "_id": "60b09285dac98f1b2514856d", "name": "Laura Gómez" },
  "reversible": false,
  "cascade": {
    "orders": "el pax se ANONIMIZA en sus orders → nombre \"*Ficha borrada\" (las reservas siguen)",
    "s3": "sus uploads/forms en S3 (documentos subidos, fichas de checkin) se BORRAN"
  },
  "warnings": ["IRREVERSIBLE: el cliente se borra FÍSICAMENTE; el server anonimiza su pax en orders y borra sus uploads/forms en S3."]
}
CampoSignificado
would_deleteQué cliente se borraría. Compruébalo antes de confirmar.
cascadeLo que ocurre en sus reservas y documentos al borrarlo: la cascada es tan irreversible como el borrado en sí.

Consejos

  • El borrado no se puede deshacer. Si dudas, no borres: usa update-client para vaciar campos o quitar etiquetas.

import-clients: importación masiva de clientes

Es una operación de escritura, pensada para volcar de golpe clientes de otra herramienta (una hoja de cálculo, un CSV exportado). Necesita un token de administrador de la cuenta. La entrada son siempre filas en memoria (rows, un array de objetos): no se acepta una ruta de fichero del disco, ni por API ni por MCP. El proceso tiene siempre dos pasos: una prueba en seco que genera un informe y una «firma» (manifest_hash), y una ejecución posterior que repite exactamente lo firmado. El script de esta guía se queda siempre en el primer paso.

Cómo llamarla

Por API, primero la prueba en seco (sin confirm_hash):

curl -X POST https://api.bukyapp.com/v1/ops/import-clients \
  -H "Authorization: Bearer bk_TU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "rows": [{"Nombre": "Laura Gómez", "Email": "laura@example.com", "Teléfono": "600000000"}],
    "mapping": {"fields": {
      "name": {"column": "Nombre", "transform": "split-name", "part": "name"},
      "surname": {"column": "Nombre", "transform": "split-name", "part": "surname"},
      "email": {"column": "Email", "transform": "lower"},
      "phone": {"column": "Teléfono", "transform": "phone"}
    }},
    "dry_run": true
  }'

Y luego, tras revisar el informe, la ejecución con el hash devuelto:

{ "rows": [ "..." ], "mapping": { "...": "..." }, "confirm_hash": "<manifest_hash del paso anterior>" }

Por MCP: «Importa estos clientes desde este fichero» adjuntando el CSV o Excel; el asistente lo lee, arma las filas y el mapeo, y te enseñará el informe antes de pedirte el visto bueno para ejecutar.

Parámetros

ParámetroTipoNivelQué hace
rowsarrayobligatorioFilas de origen: un objeto por fila, con una clave por columna tal cual viene del fichero. Es la única forma de dar la entrada; no se admite una ruta de fichero. Máximo 1000 filas por llamada; un fichero mayor se trocea y se repite el proceso por trozo.
mappingobjetoobligatorioMapeo inline: un objeto fields con un elemento por cada campo de destino, indicando de qué columna sale (column, column_contains para coincidencia parcial, o un value fijo) y una transformación opcional (partir un nombre completo, pasar a minúsculas, normalizar teléfono...). También admite filters, notes, defaults y null_values para filtrar filas, guardar texto en notas, rellenar valores por defecto o tratar ciertos textos como vacío. Los campos de destino son los mismos que en create-client (name, surname, email, phone, document_type, dni, birthday, gender, street_address, country, state, city, zip, nationality, check_marketing, customer_notes, tags, lang); cualquier otro nombre se rechaza.
prevent_duplicatesbooleanoopcionalEvita duplicados dentro del fichero y contra los clientes que ya existen. Por defecto true.
confirm_hashtextorecomendadoEl manifest_hash de la prueba en seco. Obligatorio para ejecutar de verdad (no para la prueba en seco); si las filas o el mapeo cambiaron después, la operación lo detecta y rechaza el hash.
samplenúmeroopcionalCuántas filas de muestra incluir en el informe. Por defecto 10.

Qué devuelve

Prueba en seco real con tres filas ficticias, dos de ellas idénticas:

{
  "success": true,
  "dry_run": true,
  "manifest_hash": "f1032a09d934868eb80c0a4b15afa12f62dad30f70787912d4f8b9b03041ce57",
  "report": {
    "total_source": 3,
    "mapped": 3,
    "rejected_local": [],
    "intra_duplicates": 1,
    "db_existing": 12,
    "db_collisions": 0,
    "lang_distribution": { "(schema:es)": 3 },
    "sample_rows": [
      { "name": "Laura", "surname": "Gómez", "email": "laura@example.com", "phone": "600000000" },
      "..."
    ]
  },
  "next_step": "Firma este informe y ejecuta con confirm_hash='f1032a09d934868eb80c0a4b15afa12f62dad30f70787912d4f8b9b03041ce57'."
}
CampoSignificado
manifest_hashIdentifica exactamente estas filas + este mapeo. Es lo que firmas y lo que pasas como confirm_hash para ejecutar.
report.mapped / rejected_localFilas que se pudieron traducir a ficha de cliente y las que no, con el motivo.
report.intra_duplicatesFilas repetidas dentro del propio fichero (mismo criterio de deduplicación). En la prueba con dos filas idénticas, la operación lo detectó correctamente (intra_duplicates: 1).
report.db_collisionsFilas que coinciden con un cliente que ya existe en tu cuenta, con ese mismo criterio.
payload_previewSolo en la prueba en seco: la llamada exacta que se haría al confirmar.

Errores propios

SituaciónRespuesta

Consejos

  • No encadenes la prueba en seco y la ejecución en el mismo mensaje: enseña el informe y espera el visto bueno antes de pasar confirm_hash.
  • Si la ejecución responde hash_mismatch, no lo fuerces: repite la prueba en seco con las filas y el mapeo actuales y vuelve a pedir confirmación.
  • Con más de 1000 filas, trocea el fichero en el cliente (asistente o script) y repite prueba en seco + ejecución por cada trozo; la deduplicación del servidor evita que se dupliquen las filas ya subidas.

¿Te ha resultado útil este artículo?