Los sitios publicados y en vista previa reciben claves internas automáticamente. Para conectar otra integración, abre Configuración → Desarrolladores → Administrar credenciales en el negocio.
Crea una clave con nombre y los permisos que necesita la integración. Cópiala antes de cerrar el diálogo de creación; la lista no vuelve a mostrarla.
1
Abre Configuración → Desarrolladores
Elige el negocio dueño del sitio y abre Configuración → Desarrolladores → Administrar credenciales. Debes ser propietario o administrador de esa organización, con membresía para toda la organización. Un rol en otra organización o acceso limitado a negocios seleccionados no habilita esta pantalla.
2
Crear clave API
En Claves de la API, elige Crear clave API. Escribe un Nombre (1–60 caracteres) y selecciona al menos una opción en Permisos. Crea una clave por integración y selecciona solo lo que necesita.
3
Copia una vez y cierra
En Clave API creada, elige Copiar credencial, guárdala de forma segura y pulsa Listo. Cerrar el diálogo borra el valor mostrado. Nimlio guarda solo un hash de las claves que creas aquí; no puedes volver a revelar la clave.
4
Revisa y revoca
La lista muestra nombre, prefijo, permisos, estado, último uso y creación. Elige Revocar y confirma para detener el acceso de inmediato. Para cambiar permisos o reemplazar una clave perdida, crea otra y revoca la anterior.
Desarrolladores reúne las claves de integraciones y las conexiones MCP del sitio.
Requisitos de sitio y plan
Primero crea un sitio web. Crear claves API requiere Pro o Enterprise; Starter muestra un diálogo para mejorar el plan que abre la facturación de la organización del sitio. Puedes seguir listando y revocando tus claves después de bajar de plan. Las conexiones MCP también requieren modo código.
Permisos API disponibles: content:read, catalog:read, booking:read, booking:write, leads:write, orders:write, events:write. Las claves de autoservicio empiezan por nk_pub_; solo las publicables autentican /api/v1.
Administrada por Nimlio
Nimlio crea automáticamente claves internas para previsualizar y publicar el sitio. Las filas marcadas Administrada por Nimlio no tienen acción Revocar. El servidor entrega el booleano managed; el nombre de una clave por sí solo no la convierte en administrada. Las claves de autoservicio siguen siendo revocables aunque su nombre se parezca al de una interna. El aprovisionamiento interno conserva el material que necesita para el sitio; el autoservicio no lo conserva.
Para scripts, usa tu sesión iniciada con los endpoints de gestión de abajo. Crear acepta solo name y scopes opcional (un arreglo no vacío); omitir scopes concede los siete, así que defínelos explícitamente. Devuelve 201, con data.key solo en esa respuesta. Listar devuelve un arreglo de metadatos en data, incluido managed, nunca la clave ni su hash. Revocar devuelve 200; intentar revocar una clave administrada devuelve 409 conflict, con motivo managed_api_key. Crear, revocar y reactivar una clave suspendida se auditan junto con la mutación. La suspensión es un estado del servidor; Desarrolladores permite crear, listar y revocar.
Los límites se aplican por llave y dirección IP cada minuto. Al superarlos recibes 429 rate_limited, salvo en POST /api/v1/events: los eventos en exceso se descartan en silencio y la respuesta sigue siendo 204.
Lecturas: 120 por minuto.
Horarios, estado de pedidos y eventos: 60 por minuto.
Cotizaciones y carritos: 30 por minuto.
Escrituras de reservas y pedidos: 10 por minuto.
Leads y newsletter: 5 por minuto.
Subida de fotos y comprobantes: 3 por minuto.
Además, las suscripciones al newsletter se limitan a 100 por negocio por hora y las escrituras de carritos a 2.000 por negocio por hora.
Cada llave también tiene una cuota diaria, de 50.000 solicitudes por defecto (puede variar según el plan o el despliegue). Los días se cuentan en la zona horaria America/Bogota.
Recetas
Ejemplos para copiar y pegar en las tareas de integración más comunes. Usan la llave de ejemplo nk_pub_xxxxxxxx y el origen de tu propio sitio; reemplaza ambos por tus valores.
Autentícate con una llave publicable
Envía la llave en UNO de los dos headers: Authorization con valor Bearer, o X-Nimlio-Key. Si envías ambos con valores distintos, la solicitud se rechaza con 401 invalid_api_key, y sin llave la respuesta es 401 missing_api_key. Las llaves secretas que empiezan por nk_sec_ no se aceptan en /api/v1. Una llave suspendida responde 403 api_key_suspended, y un sitio protegido con contraseña responde 403 site_locked en las lecturas de visitantes. Las llaves publicables son seguras para código del navegador: solo leen datos publicados y escriben registros originados por visitantes.
Cada endpoint de la referencia declara exactamente un scope, que se muestra como una etiqueta, y tu llave debe tener ese mismo valor. Los scopes son content:read, catalog:read, booking:read, booking:write, leads:write, orders:write y events:write. Si a la llave le falta el scope requerido, recibes la respuesta 403 de abajo.
Las listas del catálogo aceptan limit (por defecto 50, máximo 100) y además offset o el cursor del meta.nextCursor anterior. Si envías ambos, gana offset, y un cursor mal formado responde 400 invalid_cursor. Nunca interpretes un cursor: devuélvelo tal cual.
Los items del CMS son distintos: ese endpoint usa limit (por defecto 25, máximo 100) y un cursor opaco, y devuelve data.items, data.nextCursor y data.hasMore en lugar de un meta de primer nivel.
El éxito siempre es ok true con data, y las listas agregan meta. El fallo siempre es ok false con un objeto error que trae code, message y, opcionalmente, reason, fieldErrors, values, details y requestId. El code es un vocabulario pequeño y estable: invalid_input 400, unauthenticated 401, forbidden 403, not_found 404, conflict 409, limit_reached 409 o 402, payload_too_large 413, unsupported_media 415, rate_limited 429, unavailable 503, internal 500. El reason da la causa específica, como missing_scope o invalid_cursor.
async function nimlioFetch(path, init = {}) { const res = await fetch(`https://your-site.example/api/v1${path}`, { ...init, headers: { Authorization: "Bearer nk_pub_xxxxxxxx", "Content-Type": "application/json", ...init.headers }, }); if (res.status === 204) return null; // e.g. POST /events has no body const body = await res.json(); if (body.ok) return body.data; const { code, reason, message, fieldErrors, requestId } = body.error; switch (code) { case "invalid_input": // 400 — fieldErrors maps field -> message throw new Error(`Fix the form: ${JSON.stringify(fieldErrors)}`); case "unauthenticated": // 401 — reason: missing_api_key | invalid_api_key case "forbidden": // 403 — reason: missing_scope | api_key_suspended | site_locked throw new Error(`Key problem (${reason})`); case "not_found": // 404 return null; case "rate_limited": // 429 — back off and retry await new Promise((r) => setTimeout(r, 1000)); return nimlioFetch(path, init); default: // conflict 409, limit_reached 409/402, internal 500, ... throw new Error(`${code}: ${message} (request ${requestId ?? "n/a"})`); } }
Cita el requestId cuando escribas a soporte. Los beacons de analítica (POST /api/v1/events) pueden responder 204 sin cuerpo.
Cotiza un pedido: los precios los define el servidor
El cuerpo de la cotización está cerrado a selecciones: items, ubicación del cliente, códigos de descuento o de tarjeta de regalo, y la tarifa de envío. Cualquier campo price, total, discount, currency o businessId se rechaza con 400 client_order_fields_not_allowed. Los montos de la respuesta están en centavos de COP.