Referencia de API
Conecta tu taller con herramientas externas usando la API REST de Nofacto, recibe notificaciones vía webhooks, embebe el cotizador en tu sitio web y configura nuestro servidor MCP para agentes de IA.
Autenticación
Todas las llamadas a la API se autentican con una API key en formato nk_live_…. La clave va en el header Authorization como token Bearer.
Cómo generar tu API key
Ve a Ajustes → Integraciones en tu panel de Nofacto. Haz clic en Crear API key, escribe una etiqueta descriptiva (por ejemplo: mi-integracion) y confirma. La clave completa se muestra una sola vez — guárdala en un lugar seguro porque no podrás verla de nuevo.
Header de autenticación
Authorization: Bearer nk_live_xxxxxxxxxxxxxxxxxxxxEjemplo con curl
curl https://nofacto.com/api/v1/workshop \
-H "Authorization: Bearer nk_live_xxxxxxxxxxxxxxxxxxxx"Endpoints REST
Base URL: https://nofacto.com/api/v1
Todas las respuestas son JSON. Los errores siguen la forma {"error":"mensaje","code":"ERROR_CODE"}.
/workshopDevuelve la configuración pública del taller: nombre, slug, país, moneda, idioma y plan activo.
curl https://nofacto.com/api/v1/workshop \
-H "Authorization: Bearer nk_live_xxxx"
# Respuesta
{
"id": "wshop_abc123",
"name": "Taller Láser Bogotá",
"slug": "taller-laser-bogota",
"country": "CO",
"currency": "COP",
"plan": "multi"
}/materialsLista los materiales del catálogo del taller con su precio base, stock disponible y unidad de medida.
curl https://nofacto.com/api/v1/materials \
-H "Authorization: Bearer nk_live_xxxx"
# Respuesta
[
{
"id": "mat_001",
"name": "MDF 3mm",
"pricePerSheet": 25000,
"currency": "COP",
"stockSheets": 12,
"sheetWidthMm": 1220,
"sheetHeightMm": 2440
}
]/machinesLista las máquinas del taller con sus tarifas de corte (por minuto o por hora).
curl https://nofacto.com/api/v1/machines \
-H "Authorization: Bearer nk_live_xxxx"
# Respuesta
[
{
"id": "mach_001",
"name": "CO2 80W",
"ratePerMinute": 1200,
"currency": "COP"
}
]/catalogLista las piezas del catálogo del taller (solo las habilitadas) con sus renders y su modelo 3D, tal como los exporta Nofacto Studio. Es lo que una tienda externa usa para publicar una pieza sin volver a dibujar nada.
curl https://nofacto.com/api/v1/catalog -H "Authorization: Bearer nk_live_xxxx"
# Respuesta
[
{
"id": "prod_001",
"codigo": "N-001",
"name": "Souvenir Restrepo",
"categoria": "souvenirs",
"imagenUrl": null,
"renders": [
{ "url": "https://.../renders/N-001-frontal.jpg", "vista": "frontal", "w": 1600, "h": 1200 },
{ "url": "https://.../renders/N-001-tres-cuartos.jpg", "vista": "tres-cuartos", "w": 1600, "h": 1200 }
],
"modelo3d": { "glb": "https://.../ar/N-001.glb", "usdz": "https://.../ar/N-001.usdz", "actualizadoEn": 1789660000000 },
"dimensionsW": 90,
"dimensionsH": 120,
"suggestedPrice": 15000
}
]/models3dLista los modelos 3D que el taller compartió en realidad aumentada desde Nofacto Studio (los del enlace «ver en tu mesa»), aunque todavía no estén enlazados a una pieza del catálogo. Los más recientes primero.
curl https://nofacto.com/api/v1/models3d -H "Authorization: Bearer nk_live_xxxx"
# Respuesta
[
{
"id": "mfz1abc-souvenir-restrepo",
"nombre": "souvenir restrepo",
"glb": "https://.../ar/mfz1abc-souvenir-restrepo.glb",
"usdz": "https://.../ar/mfz1abc-souvenir-restrepo.usdz",
"bytesGlb": 412000,
"actualizadoEn": 1789660000000
}
]/quoteCalcula el precio estimado de un trabajo sin crear un pedido. Útil para mostrar precios en tiempo real.
Cuerpo de la solicitud
machineId string · requeridomaterialId string · requeridoproductSpec object · requerido — dimensiones y detalles del trabajo.curl -X POST https://nofacto.com/api/v1/quote \
-H "Authorization: Bearer nk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"machineId": "mach_001",
"materialId": "mat_001",
"productSpec": {
"widthMm": 200,
"heightMm": 150,
"quantity": 10,
"cutMinutes": 3.5
}
}'
# Respuesta
{
"subtotal": 85000,
"currency": "COP",
"breakdown": {
"material": 35000,
"machine": 42000,
"overhead": 8000
}
}/ordersCrea un nuevo pedido (en estado borrador). El taller lo recibe en su panel para procesar.
curl -X POST https://nofacto.com/api/v1/orders \
-H "Authorization: Bearer nk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"name": "María García",
"email": "[email protected]",
"phone": "+573001234567"
},
"lines": [
{
"kind": "simple",
"description": "Llaveros MDF 3mm",
"quantity": 50,
"pricePerUnit": 3500
}
],
"paymentMode": "cash"
}'
# Respuesta
{
"id": "ord_xyz789",
"status": "quote",
"total": 175000,
"currency": "COP",
"createdAt": "2026-07-02T10:00:00Z"
}Pedido completo (tiendas en línea). Si tu tienda ya trae el trabajo hecho —el cliente personálizó su pieza y hay un archivo de corte listo— puedes mandarlo todo y el taller produce sin volver a dibujar nada. Todos estos campos son opcionales: si ya usabas la API, nada cambia.
curl -X POST https://nofacto.com/api/v1/orders \
-H "Authorization: Bearer nk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"externalId": "TIENDA-A1B2C3",
"customer": {
"name": "Ana María Rincón",
"phone": "+573107999230",
"nit": "1.049.657.235"
},
"delivery": {
"method": "national",
"address": "Calle 20 # 12-45",
"city": "Villavicencio",
"cost": 21000
},
"notes": "La placa de Julián va empacada aparte, es sorpresa.",
"lines": [
{
"description": "Placa de reconocimiento — MDF negro 90×60 mm",
"referencia": "PLACA-MDF-90x60",
"quantity": 2,
"total": 37000,
"pricePerUnit": 18500,
"service": "grabado",
"dimensionsW": 90,
"dimensionsH": 60,
"file": {
"url": "https://tu-tienda.com/pedidos/A1B2C3/corte.svg",
"name": "corte.svg",
"type": "image/svg+xml",
"sizeBytes": 4096
},
"svgString": "<svg …/>"
}
]
}'
# Respuesta (201; 200 si el externalId ya existía)
{
"orderId": "aB3dE5fG7hJ9",
"status": "pending",
"total": 37000,
"publicUrl": "https://nofacto.com/tu-taller/order/aB3dE5fG7hJ9/review",
"customerId": "kL2mN4pQ6rS8"
}externalId — el identificador del pedido en TU sistema. Con él, reintentar es seguro: si se te cae la red después de crear el pedido, vuelves a llamar con el mismo externalId y recibes el que ya existe (con 200 en vez de 201) en lugar de crear un duplicado. Sin esto, un tiempo de espera agotado deja al taller cortando dos veces lo mismo.
file — el archivo de corte, con su nombre y tipo. El taller lo abre directo. svgString deja ver el corte sin descargarlo (máximo 200.000 caracteres). service es corte, grabado, delineado o ambos, y las dimensiones van en mm.
delivery.method es pickup, local o national. Antes se asumía siempre que el cliente recogía en el taller. Las URLs de archivo deben ser http o https.
customer.nit — NIT o cédula del cliente, como lo escriba (con puntos, guion o dígito de verificación; máximo 32 caracteres). Si el cliente ya está en el Directorio del taller —por ese NIT o, si no, por su teléfono— el pedido queda enlazado a su ficha, lleva el nombre con el que el taller lo conoce y la respuesta trae su customerId. Si no está, el pedido se crea con los datos que mandaste y la respuesta no trae customerId: la API no crea ni modifica fichas, eso lo decide el taller.
lines[].referencia — la referencia interna del producto (p. ej. CAL-IMAN-2027, máximo 64 caracteres). El taller la ve en la línea, la encuentra con el buscador de pedidos y sale en la factura electrónica como código del ítem.
/ordersLista los pedidos del taller. Parámetros opcionales: status (quote, pending, accepted, completed, cancelled), limit (máx 100, default 20), cursor (paginación).
/orders/:idDevuelve el detalle completo de un pedido incluyendo líneas, cliente, historial de pagos y etapa del kanban.
/orders/:idActualiza campos del pedido. Campos actualizables: status, stageId, specs, deliveryDate.
curl -X PATCH https://nofacto.com/api/v1/orders/ord_xyz789 \
-H "Authorization: Bearer nk_live_xxxx" \
-H "Content-Type: application/json" \
-d '{"status": "accepted", "specs": "Diseño aprobado por cliente"}'/orders/:id/payRegistra un pago contra el pedido. Usa el header Idempotency-Key para evitar pagos duplicados ante reintentos.
Headers
Idempotency-Key string · recomendado — UUID único por intento de pago. Si el servidor ya procesó esta clave, devuelve la respuesta original sin duplicar el cobro.curl -X POST https://nofacto.com/api/v1/orders/ord_xyz789/pay \
-H "Authorization: Bearer nk_live_xxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-d '{
"amount": 87500,
"reference": "TRANSF-2026-0702"
}'
# Respuesta
{
"paymentId": "pay_abc001",
"amountPaid": 87500,
"balance": 87500,
"order": { "id": "ord_xyz789", "status": "pending" }
}Webhooks
Los webhooks envían notificaciones HTTP POST a tu servidor cuando ocurren eventos en el taller. Registra tus endpoints en Ajustes → Integraciones.
Eventos disponibles
Payload de ejemplo
POST https://tu-servidor.com/webhook/nofacto
Content-Type: application/json
X-Nofacto-Signature: sha256=a3f8b2c1d4e5...
{
"event": "order.status_changed",
"workshopId": "wshop_abc123",
"data": {
"orderId": "ord_xyz789",
"previousStatus": "quote",
"currentStatus": "accepted",
"updatedAt": "2026-07-02T10:05:00Z"
}
}Verificar la firma HMAC
Cada llamada incluye el header X-Nofacto-Signature con un HMAC-SHA256 del cuerpo firmado con tu webhook secret (visible en Ajustes → Integraciones al crear el endpoint). Verifica la firma antes de procesar el evento para descartar llamadas fraudulentas.
// Node.js — verificación de firma
const crypto = require('crypto');
function verifySignature(rawBody, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// En tu handler Express:
app.post('/webhook/nofacto', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-nofacto-signature'];
if (!verifySignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Firma inválida');
}
const payload = JSON.parse(req.body);
// Procesar payload.event ...
res.sendStatus(200);
});Widget embebible
El widget de Nofacto te permite incrustar el cotizador de tu taller directamente en tu sitio web con una sola línea de código. El cliente final cotiza y hace su pedido sin salir de tu página.
Snippet de instalación
<script
async
src="https://nofacto.com/embed.js"
data-slug="tu-slug-de-taller"
data-accent="#FF4A1C"
data-layout="stepper"
data-hide="location"
data-lang="es"
></script>Atributos disponibles
Ejemplo en una página HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Mi Taller</title>
</head>
<body>
<h1>¿Cuánto cuesta tu proyecto?</h1>
<!-- El botón "Cotizar ahora" aparece aquí automáticamente -->
<script
async
src="https://nofacto.com/embed.js"
data-slug="mi-taller-laser"
data-accent="#2D3748"
></script>
</body>
</html>El widget es responsive y funciona en móvil. No requiere configuración adicional — el script detecta el slug y carga la configuración del taller desde los servidores de Nofacto.
Servidor MCP
Nofacto expone un servidor Model Context Protocol (MCP) que puedes conectar a tu agente o cliente de IA (Claude, Cursor, Copilot Chat, etc.) para que interactúe directamente con tu taller.
Configuración
Configuración en claude_desktop_config.json
{
"mcpServers": {
"nofacto": {
"url": "https://nofacto.com/mcp",
"headers": {
"Authorization": "Bearer nk_live_xxxxxxxxxxxxxxxxxxxx"
}
}
}
}Tools disponibles
Ejemplo de uso con Claude
Una vez configurado el servidor MCP, puedes hablar con tu taller en lenguaje natural: