API de Mosaqo para desarrolladores
Una API REST sobre el mismo espacio de trabajo que usas en la aplicación. Todo lo de abajo funciona con una sola llave de API y cualquier cliente HTTP.
Qué puedes hacer
- Crear códigos QR a partir de tus propios registros: de uno en uno o diez mil desde un CSV.
- Cambiar a dónde apunta un código ya impreso, en una sola llamada y sin volver a imprimir nada.
- Descargar la tarjeta final en PNG, SVG o PDF y adjuntarla a un registro del CRM.
- Leer escaneos y analíticas agregadas, filtrados por las reglas de privacidad de tu espacio.
- Recibir webhooks firmados cuando se crea, publica, modifica o archiva un código.
Inicio rápido
Crea una llave en Bulk & API dentro de tu espacio, marca los scopes qr:write y qr:read y copia el secreto: solo se muestra una vez.
Verifica la llave y averigua qué espacio abre:
curl https://api.mosaqo.app/v1/public-api/me \
-H "Authorization: Bearer $MOSAQO_KEY"Crea un código QR dinámico:
curl -X POST https://api.mosaqo.app/v1/public-api/qr \
-H "Authorization: Bearer $MOSAQO_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Autumn campaign",
"mode": "dynamic",
"contentType": "url",
"content": { "targetUrl": "https://example.com/autumn" }
}'Publícalo, que es lo que hace funcionar la redirección, y luego obtén la imagen lista para imprimir:
curl -X POST https://api.mosaqo.app/v1/public-api/qr/$QR_ID/publish \
-H "Authorization: Bearer $MOSAQO_KEY"
curl https://api.mosaqo.app/v1/public-api/qr/$QR_ID/image?format=png&size=2048 \
-H "Authorization: Bearer $MOSAQO_KEY" -o campaign.pngMeses después, cuando la campaña cambie, redirige el mismo código impreso sin volver a imprimirlo:
curl -X POST https://api.mosaqo.app/v1/public-api/qr/$QR_ID/destination \
-H "Authorization: Bearer $MOSAQO_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com/winter" }'Autenticación
Envía tu secreto de cualquiera de las dos formas. Ambas valen durante toda la v1.
Authorization: Bearer mosaqo_xxx
X-Mosaqo-API-Key: mosaqo_xxxUna llave pertenece exactamente a un espacio de trabajo, así que las rutas no necesitan su identificador: basta con /v1/public-api/qr. La forma anterior /v1/public-api/workspaces/{workspaceId}/qr sigue funcionando.
| Scope | Permite |
|---|---|
qr:read | Listar y leer códigos QR, carpetas y plantillas |
qr:write | Crear, modificar, redirigir, publicar, archivar y eliminar |
exports:read | Descargar tarjetas renderizadas |
analytics:read | Analíticas agregadas y escaneos individuales |
bulk:write | Crear y leer trabajos por lotes |
webhooks:write | Administrar suscripciones de webhooks |
Las llaves se pueden revocar, darles fecha de vencimiento y restringirlas a una lista de IP permitidas. Si es esa lista la que rechaza la llave, lo decimos de forma explícita en lugar de hacerla parecer inválida.
Paginación
Las listas usan paginación por llave. Devuelve pagination.nextCursor sin modificarlo: las filas nunca se repiten ni desaparecen porque algo se haya editado a media sincronización, lo cual importa en una sincronización nocturna.
curl "https://api.mosaqo.app/v1/public-api/qr?limit=50&cursor=$CURSOR" \
-H "Authorization: Bearer $MOSAQO_KEY"Para consultar cambios en lugar de recorrerlo todo, agrega updatedSince=2026-08-05T00:00:00Z.
Errores
Cada falla lleva un code estable sobre el cual ramificar, un message legible y un requestId que conviene citar al soporte.
{
"error": "This API key does not have the qr:write scope.",
"message": "This API key does not have the qr:write scope.",
"code": "insufficient_scope",
"details": { "required": "qr:write", "granted": ["qr:read"] },
"requestId": "req-42"
}| Estado | Códigos | Qué hacer |
|---|---|---|
| 401 | invalid_api_key | Falta la llave, se revocó o venció. Pide a la persona que se vuelva a conectar. |
| 403 | insufficient_scope, ip_not_allowed, workspace_mismatch, quota_exceeded | La llave es válida pero no tiene ese permiso. Volver a conectarse no ayuda. |
| 404 | not_found | No existe ese registro en este espacio. |
| 409 | idempotency_conflict, idempotency_in_progress | Se reutilizó una llave con datos distintos, o el primer intento sigue en curso. |
| 422 | validation_failed, invalid_cursor, approval_required, contrast_check_failed | Corrige la entrada. Nunca reintentes sin cambios. |
| 429 | rate_limited | Espera los segundos que indique Retry-After. |
Límites de uso
Cada respuesta lleva tu presupuesto actual, no solo las que se rechazan:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 574
X-RateLimit-Reset: 1785942718El límite es una protección contra abusos, no un plan: no implica cuota, facturación ni cambio de suscripción.
Idempotencia
Idempotency-Key es opcional. Envía una —cualquier cadena única— y reintentar la misma petición dentro de 24 horas reproduce la respuesta original en lugar de actuar dos veces. La misma llave con datos distintos devuelve 409. Sin llave la petición simplemente se ejecuta, sin protección contra repeticiones.
Siguiente
- Webhooks: el catálogo de eventos y cómo verificar una entrega.
- Recetas: patrones para Make, Zapier, n8n y CRM.
- Referencia de la API: cada endpoint, con consola en vivo.