Inicio rápido
- Abre Claves de API en tu panel (plan Business) y crea una clave. Cópiala: solo se muestra una vez.
- Guárdala como variable de entorno en tu servidor, p. ej. TESSERA_API_KEY. Nunca la pongas en código de navegador o de app.
- Crea un código QR dinámico. La respuesta incluye su enlace corto en url; codifica ese enlace o descarga una imagen lista desde /qr.
cURL
curl "https://scanmosaic.com/api/v1/items" \
-H "Authorization: Bearer $TESSERA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"kind": "qr", "name": "Table menu", "dest": "https://example.com/menu"}'JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/items", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"kind": "qr",
"name": "Table menu",
"dest": "https://example.com/menu"
})
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.post(
"https://scanmosaic.com/api/v1/items",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
json={
"kind": "qr",
"name": "Table menu",
"dest": "https://example.com/menu"
},
)
r.raise_for_status()
print(r.json()["data"])cURL
curl "https://scanmosaic.com/api/v1/qr?item=k3Xp9Qa&size=1024" \
-H "Authorization: Bearer $TESSERA_API_KEY" \
-o menu.pngJavaScript
import { writeFile } from "node:fs/promises";
const res = await fetch("https://scanmosaic.com/api/v1/qr?item=k3Xp9Qa&size=1024", {
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).error.message);
await writeFile("menu.png", Buffer.from(await res.arrayBuffer()));Python
import os, requests
r = requests.get(
"https://scanmosaic.com/api/v1/qr?item=k3Xp9Qa&size=1024",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
)
r.raise_for_status()
open("menu.png", "wb").write(r.content)Autenticación
Envía tu clave en el encabezado Authorization de cada solicitud. Las claves empiezan por tsk_ y pertenecen a un workspace: pueden leer y cambiar todo lo que puede un editor de ese workspace, y nada en otros workspaces.
Authorization: Bearer tsk_AbC123…
- Los propietarios y administradores crean y eliminan claves en Claves de API, dentro del panel. Al eliminar una clave, deja de funcionar al instante.
- La API forma parte del plan Business. Si el plan termina, las solicitudes reciben 402 business_required hasta que renueves; tus códigos y datos se conservan.
- Los cambios hechos con una clave aparecen en el registro de actividad del espacio de trabajo como "API key tsk_…".
- CORS está abierto para que puedas llamar a la API desde cualquier origen, pero cualquiera que abra una página web puede copiar la clave que contenga. Llama a la API desde tu servidor.
Errores
Todos los errores usan la misma estructura JSON y un estado HTTP coherente. code es estable: constrúyelo sobre él. message es texto en inglés claro para registros y personas. Algunos errores añaden detalles, como param.
{
"error": {
"code": "bad_param",
"message": "One of the parameters isn't valid.",
"status": 400,
"param": "size",
"hint": "64 to 2048"
}
}
| Estado | Código | Significado |
|---|---|---|
| 400 | bad_json | El cuerpo no es un JSON válido. |
| 400 | bad_param | Un parámetro de consulta o del cuerpo está fuera de rango. details: param, hint. |
| 400 | bad_destination | dest no es una dirección web http(s) completa. |
| 400 | bad_kind | kind no es qr, link ni barcode. |
| 400 | bad_alias | el alias no tiene entre 3 y 40 letras, números o guiones, o está reservado. |
| 400 | domain_not_verified | domain no es un dominio verificado de tu espacio de trabajo. |
| 400 | unsafe_destination | Google Web Risk marca el destino como peligroso. |
| 400 | empty / too_long / bad_format | Imágenes QR: sin datos, demasiados datos o un formato distinto de png o svg. |
| 400 | bad_cursor | Ese cursor no es uno de los que te dimos. |
| 401 | api_key_required | Falta la cabecera Authorization, o no es Bearer tsk_… |
| 401 | invalid_api_key | La clave no existe o fue eliminada. |
| 402 | business_required | El workspace no está en el plan Business (por ejemplo, porque terminó). |
| 403 | limit_reached | Has alcanzado el límite de tu plan para ese tipo de elemento. details: limit, kind. |
| 404 | not_found | No existe ese elemento en este espacio de trabajo. |
| 409 | alias_taken | Ese alias ya se usa en ese dominio. |
| 413 | too_big | El cuerpo es demasiado grande (250 KB para items). |
| 429 | rate_limited / daily_limit | Demasiadas solicitudes. Espera los segundos indicados en Retry-After. |
| 500 | server_error | Algo falló por nuestra parte. Reintenta con espera progresiva. |
Límites de uso
Cada clave puede hacer 120 solicitudes por minuto y 20,000 al día. Cada respuesta te indica cuánto llevas:
| Cabecera | Significado |
|---|---|
X-RateLimit-Limit | Solicitudes permitidas por minuto. |
X-RateLimit-Remaining | Solicitudes restantes en el minuto actual. |
X-RateLimit-Reset | Hora Unix en que se reinicia el minuto. |
Retry-After | Solo con 429: segundos que hay que esperar antes de volver a intentarlo. |
Crear elementos también está limitado a 300 por hora y espacio de trabajo, y tu plan define cuántos elementos puedes conservar. ¿Necesitas más? Contáctanos.
Paginación
Las listas devuelven primero lo más reciente, hasta limit elementos (25 por defecto, 100 como máximo). Cuando has_more es true, pasa next_cursor como cursor para obtener la página siguiente. Los cursores siguen siendo válidos cuando se añaden elementos.
{
"data": [
"\u2026"
],
"has_more": true,
"next_cursor": "MTc2NzIyNTYwMC5rM1hwOVFh"
}
El objeto item
Los códigos QR, enlaces y códigos de barras son todos elementos. Un elemento individual se devuelve como data; las listas, como data con campos de paginación.
| Nombre | Tipo | Descripción |
|---|---|---|
id | string | ID corto, también es la terminación por defecto del enlace corto. |
kind | qr | link | barcode | Qué es. No se puede cambiar tras la creación. |
type | string | Tipo de contenido, p. ej. url (por defecto), pdf, menu, vcard para códigos QR; ean13, code128 para códigos de barras. |
name | string | Tu etiqueta, hasta 80 caracteres. |
dest | string | null | A dónde van los escaneos y clics. null para páginas alojadas y códigos de barras. |
url | string | El enlace corto que codifica el código QR, p. ej. https://go.yourbrand.com/menu. |
alias | string | null | Final personalizado (3–40 letras, números o guiones), único por dominio. |
domain | string | null | Tu dominio propio verificado, o null para el nuestro. |
campaign | string | null | Agrupa elementos para los informes. |
content | object | null | Datos de la página alojada o datos del código de barras ({ "data": "…" }). |
style | object | Diseño del código QR (colores, estilos de puntos y esquinas). |
rules | object | null | Reglas de enrutamiento (por dispositivo, país, hora…). |
paused | boolean | Los elementos en pausa muestran una página de «pausado» en lugar de redirigir. |
disabled | boolean | Lo desactivamos por incumplir los términos. |
hits | integer | Escaneos totales (códigos QR) o clics (enlaces). |
last_hit | integer | null | Hora Unix del último escaneo o clic. |
created / updated | integer | Horas Unix. |
Endpoints
GET /api/v1/me
Cuenta
El workspace al que pertenece esta clave, su plan, límites, uso, dominios verificados y límites de frecuencia. Útil para comprobar que una clave funciona.
cURL
curl "https://scanmosaic.com/api/v1/me" \
-H "Authorization: Bearer $TESSERA_API_KEY"JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/me", {
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.get(
"https://scanmosaic.com/api/v1/me",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 200 OK
{
"data": {
"workspace": {
"id": "w_8fK2mQ",
"name": "Acme"
},
"plan": "business",
"key": {
"prefix": "tsk_AbC123",
"name": "Shopify sync"
},
"limits": {
"qr": 1000,
"link": 5000,
"barcode": 10000,
"domains": 5
},
"usage": {
"dynamic": 12,
"links": 40,
"barcodes": 3,
"storageBytes": 0,
"workspaces": 1
},
"domains": [
"go.yourbrand.com"
],
"rate_limits": {
"per_minute": 120,
"per_day": 20000
}
}
}GET /api/v1/items
Listar elementos
Elementos del espacio de trabajo, los más recientes primero.
| Nombre | Tipo | Descripción |
|---|---|---|
kind | qr | link | barcode | Solo este tipo. |
type | string | Solo este tipo de contenido, p. ej. url o pdf. |
campaign | string | Solo esta campaña. |
domain | string | Solo los elementos de este dominio personalizado. |
paused | true | false | Solo los elementos en pausa, o solo los activos. |
q | string | Busca por nombre, destino y alias. |
limit | integer | 1–100, por defecto 25. |
cursor | string | next_cursor de la página anterior. |
cURL
curl "https://scanmosaic.com/api/v1/items?kind=link&campaign=spring&limit=50" \
-H "Authorization: Bearer $TESSERA_API_KEY"JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/items?kind=link&campaign=spring&limit=50", {
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.get(
"https://scanmosaic.com/api/v1/items?kind=link&campaign=spring&limit=50",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 200 OK
{
"data": [
{
"id": "k3Xp9Qa",
"kind": "link",
"type": "url",
"name": "Spring menu",
"dest": "https://example.com/menu",
"content": null,
"style": {},
"rules": null,
"alias": "menu",
"domain": "go.yourbrand.com",
"campaign": "spring",
"og": null,
"created": 1767225600,
"updated": 1767225600,
"paused": false,
"disabled": false,
"hits": 42,
"last_hit": 1767312000,
"url": "https://go.yourbrand.com/menu"
}
],
"has_more": false,
"next_cursor": null
}POST /api/v1/items
Crear un elemento
Crea un código QR dinámico, un enlace corto o un código de barras guardado. Cuenta para los límites de tu plan.
| Nombre | Tipo | Descripción |
|---|---|---|
kind | qr | link | barcode | Por defecto qr. |
dest obligatorio | string | Dirección http(s) completa a la que redirigir. No se usa en códigos de barras ni páginas alojadas. |
name | string | Hasta 80 caracteres. |
type | string | Por defecto url (códigos, enlaces) o code128 (códigos de barras). |
alias | string | Final personalizado, p. ej. menu. 3–40 letras, números o guiones, único por dominio. |
domain | string | Uno de tus dominios personalizados verificados (consulta /domains). |
campaign | string | Hasta 60 caracteres. |
style | object | Diseño del QR, p. ej. {"fg": "#112233", "dot": "rounded"}. |
content | object | Datos de la página alojada o del código de barras, p. ej. {"bcid": "ean13", "text": "4006381333931"} para un código de barras. |
rules | object | Reglas de enrutamiento. |
paused | boolean | Empieza en pausa. |
cURL
curl "https://scanmosaic.com/api/v1/items" \
-H "Authorization: Bearer $TESSERA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"kind": "link", "name": "Spring menu", "dest": "https://example.com/menu", "alias": "menu", "domain": "go.yourbrand.com", "campaign": "spring"}'JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/items", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"kind": "link",
"name": "Spring menu",
"dest": "https://example.com/menu",
"alias": "menu",
"domain": "go.yourbrand.com",
"campaign": "spring"
})
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.post(
"https://scanmosaic.com/api/v1/items",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
json={
"kind": "link",
"name": "Spring menu",
"dest": "https://example.com/menu",
"alias": "menu",
"domain": "go.yourbrand.com",
"campaign": "spring"
},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 201 Created
{
"data": {
"id": "k3Xp9Qa",
"kind": "link",
"type": "url",
"name": "Spring menu",
"dest": "https://example.com/menu",
"content": null,
"style": {},
"rules": null,
"alias": "menu",
"domain": "go.yourbrand.com",
"campaign": "spring",
"og": null,
"created": 1767225600,
"updated": 1767225600,
"paused": false,
"disabled": false,
"hits": 42,
"last_hit": 1767312000,
"url": "https://go.yourbrand.com/menu"
}
}GET /api/v1/items/{id}
Obtener un elemento
Un elemento por id.
cURL
curl "https://scanmosaic.com/api/v1/items/k3Xp9Qa" \
-H "Authorization: Bearer $TESSERA_API_KEY"JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/items/k3Xp9Qa", {
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.get(
"https://scanmosaic.com/api/v1/items/k3Xp9Qa",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 200 OK
{
"data": {
"id": "k3Xp9Qa",
"kind": "link",
"type": "url",
"name": "Spring menu",
"dest": "https://example.com/menu",
"content": null,
"style": {},
"rules": null,
"alias": "menu",
"domain": "go.yourbrand.com",
"campaign": "spring",
"og": null,
"created": 1767225600,
"updated": 1767225600,
"paused": false,
"disabled": false,
"hits": 42,
"last_hit": 1767312000,
"url": "https://go.yourbrand.com/menu"
}
}PATCH /api/v1/items/{id}
Actualiza un artículo
Envía solo los campos que quieras cambiar. Cambiar dest surte efecto en el siguiente escaneo; los códigos impresos siguen funcionando. Cambiar domain o alias cambia el enlace corto, así que los códigos ya impresos dejan de funcionar.
| Nombre | Tipo | Descripción |
|---|---|---|
name, dest, alias, domain, campaign, style, content, rules, paused | Igual que en Create. kind no se puede cambiar. Envía null para borrar alias, domain, campaign o rules. |
cURL
curl -X PATCH "https://scanmosaic.com/api/v1/items/k3Xp9Qa" \
-H "Authorization: Bearer $TESSERA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"dest": "https://example.com/summer-menu", "paused": false}'JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/items/k3Xp9Qa", {
method: "PATCH",
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"dest": "https://example.com/summer-menu",
"paused": false
})
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.patch(
"https://scanmosaic.com/api/v1/items/k3Xp9Qa",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
json={
"dest": "https://example.com/summer-menu",
"paused": False
},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 200 OK
{
"data": {
"id": "k3Xp9Qa",
"kind": "link",
"type": "url",
"name": "Spring menu",
"dest": "https://example.com/summer-menu",
"content": null,
"style": {},
"rules": null,
"alias": "menu",
"domain": "go.yourbrand.com",
"campaign": "spring",
"og": null,
"created": 1767225600,
"updated": 1767225600,
"paused": false,
"disabled": false,
"hits": 42,
"last_hit": 1767312000,
"url": "https://go.yourbrand.com/menu"
}
}DELETE /api/v1/items/{id}
Eliminar un elemento
Elimina el elemento y su historial de escaneos. Su enlace corto deja de funcionar al instante. No se puede deshacer.
cURL
curl -X DELETE "https://scanmosaic.com/api/v1/items/k3Xp9Qa" \
-H "Authorization: Bearer $TESSERA_API_KEY"JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/items/k3Xp9Qa", {
method: "DELETE",
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.delete(
"https://scanmosaic.com/api/v1/items/k3Xp9Qa",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 200 OK
{
"data": {
"id": "k3Xp9Qa",
"deleted": true
}
}GET /api/v1/items/{id}/stats
Estadísticas del elemento
Escaneos o clics en un periodo: una serie diaria y desgloses por país, dispositivo, sistema operativo, navegador, idioma y regla de enrutamiento. Los bots no se cuentan.
| Nombre | Tipo | Descripción |
|---|---|---|
days | integer | 1–365, por defecto 30. |
cURL
curl "https://scanmosaic.com/api/v1/items/k3Xp9Qa/stats?days=7" \
-H "Authorization: Bearer $TESSERA_API_KEY"JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/items/k3Xp9Qa/stats?days=7", {
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.get(
"https://scanmosaic.com/api/v1/items/k3Xp9Qa/stats?days=7",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 200 OK
{
"data": {
"days": 7,
"total": 42,
"last_hit": 1767312000,
"inRange": 12,
"series": [
[
"2026-01-01",
3
],
[
"2026-01-02",
0
],
[
"…",
0
]
],
"countries": [
{
"k": "GB",
"n": 7
},
{
"k": "US",
"n": 5
}
],
"devices": [
{
"k": "Mobile",
"n": 10
},
{
"k": "Desktop",
"n": 2
}
],
"os": [
{
"k": "iOS",
"n": 6
}
],
"browsers": [
{
"k": "Safari",
"n": 6
}
],
"langs": [
{
"k": "en-gb",
"n": 7
}
],
"rules": [
{
"k": "default",
"n": 12
}
]
}
}GET /api/v1/qr
Imagen del código QR
Genera un código QR como PNG o SVG. Usa GET con parámetros de consulta, o POST con los mismos parámetros en JSON. Pasa item para dibujar un código guardado con su propio diseño y enlace corto, o data para cualquier texto.
| Nombre | Tipo | Descripción |
|---|---|---|
data | string | Texto o enlace a codificar (hasta 2,953 bytes). Obligatorio salvo que se indique item. |
item | string | ID de un código QR o enlace guardado: codifica su enlace corto con su diseño guardado. |
format | png | svg | Por defecto png. |
size | integer | Píxeles: 64–2048 para PNG (512 por defecto), 64–4096 para SVG (1024 por defecto). |
color | #RRGGBB | Puntos. Predeterminado #141A2E. |
background | #RRGGBB | Por defecto #FFFFFF. |
transparent | boolean | Fondo transparente. |
corner_color | #RRGGBB | Cuadrados de esquina. Por defecto: color. |
gradient_color | #RRGGBB | Solo SVG: segundo color de un degradado diagonal. |
error_correction | L | M | Q | H | Cuánto daño soporta el código: 7 %, 15 %, 25 %, 30 %. Por defecto M (PNG) o Q (SVG). |
margin | integer | Zona de silencio en módulos, 0–8. Por defecto 4. |
dot_style | string | square, dots, rounded, extra-rounded, classy, classy-rounded |
corner_style | string | square, extra-rounded, dot |
corner_dot_style | string | square, dot |
download | string | Nombre de archivo: añade Content-Disposition: attachment. |
Los PNG se dibujan en nuestros servidores con píxeles enteros por módulo, así que los bordes se mantienen nítidos para imprimir. Los degradados y logos son solo para SVG; para logos, usa el generador.
cURL
curl "https://scanmosaic.com/api/v1/qr" \
-H "Authorization: Bearer $TESSERA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"data": "https://example.com", "format": "png", "size": 1024, "color": "#4865F0", "dot_style": "rounded", "corner_style": "extra-rounded"}' \
-o qr.pngJavaScript
import { writeFile } from "node:fs/promises";
const res = await fetch("https://scanmosaic.com/api/v1/qr", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"data": "https://example.com",
"format": "png",
"size": 1024,
"color": "#4865F0",
"dot_style": "rounded",
"corner_style": "extra-rounded"
})
});
if (!res.ok) throw new Error((await res.json()).error.message);
await writeFile("qr.png", Buffer.from(await res.arrayBuffer()));Python
import os, requests
r = requests.post(
"https://scanmosaic.com/api/v1/qr",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
json={
"data": "https://example.com",
"format": "png",
"size": 1024,
"color": "#4865F0",
"dot_style": "rounded",
"corner_style": "extra-rounded"
},
)
r.raise_for_status()
open("qr.png", "wb").write(r.content)GET /api/v1/domains
Dominios
Los dominios personalizados del workspace. Usa como dominio un host cuyo ready sea true cuando crees items.
cURL
curl "https://scanmosaic.com/api/v1/domains" \
-H "Authorization: Bearer $TESSERA_API_KEY"JavaScript
const res = await fetch("https://scanmosaic.com/api/v1/domains", {
headers: { Authorization: `Bearer ${process.env.TESSERA_API_KEY}` },
});
const body = await res.json();
if (!res.ok) throw new Error(body.error.message);
console.log(body.data);Python
import os, requests
r = requests.get(
"https://scanmosaic.com/api/v1/domains",
headers={"Authorization": f"Bearer {os.environ['TESSERA_API_KEY']}"},
)
r.raise_for_status()
print(r.json()["data"])Respuesta 200 OK
{
"data": [
{
"host": "go.yourbrand.com",
"verified": true,
"ready": true
}
]
}Dominios personalizados
Con el plan Business tus enlaces cortos pueden usar tu propio dominio, como go.yourbrand.com/menu. Añade y verifica el dominio en Dominios, dentro del panel: añades un registro CNAME que apunta a nosotros y un registro TXT que demuestra que es tuyo, y nosotros emitimos el certificado SSL. Después indica domain al crear o actualizar un elemento.
Cada dominio puede redirigir su dirección raíz (go.yourbrand.com) y las rutas desconocidas a las páginas que elijas.
OpenAPI
La API completa está descrita en openapi.json (OpenAPI 3.1). Impórtala en Postman, Insomnia o un generador de clientes.
Versiones
v1 es estable. Podemos añadir endpoints, campos y códigos de error, así que ignora los campos que no conozcas. No quitaremos ni renombraremos nada en v1; los cambios que rompan compatibilidad llegarían como v2, anunciada con mucha antelación.