Referencia de la API

Obtén las variables de variable Jar desde cualquier lugar (apps de iOS/Android, pipelines de CI) mediante REST. Es de solo lectura y usa el mismo token que el servidor MCP.

Beta: la API y MCP pueden cambiar antes del lanzamiento; los formatos ya llevan versión (consulta Salida de código de plataforma), y los cambios incompatibles se anuncian con 12 meses de convivencia.

Emitir un token

  1. variablejar.com/app → menú ⋯ → Propiedades de una tarjeta de proyecto → la sección Tokens de API (MCP)
  2. Escribe un nombre de token y pulsa Emitir: el token (vjt_…) se muestra solo una vez, justo después de emitirlo. Guárdalo en un lugar seguro.
  3. Un token da acceso solo a ese proyecto. Si se filtra, revócalo de inmediato en la misma pantalla.

Los tokens caducan (180 días por defecto, hasta 365). Recibirás una notificación en la campana 14 días antes. Solo el propietario del espacio de trabajo puede emitir un token que incluya valores de texto (STRING): salen todos los idiomas, incluidas las traducciones no publicadas. También puedes limitar un token a las colecciones que elijas.

Un token es tan seguro como el lugar donde lo guardes: quien lo tenga recibe todos los valores dentro de su alcance. Los datos que exportas mediante la API o MCP salen del servicio y se procesan bajo tu responsabilidad.

Endpoint

GET https://variablejar.com/api/v1/variables
Authorization: Bearer vjt_...
curl -H "Authorization: Bearer vjt_..." \
  "https://variablejar.com/api/v1/variables"

Los valores de texto (STRING) solo se incluyen si el token se emitió con valores de texto y añades ?include=strings.

Respuesta

Los valores son finales, con los alias ({Collection/key}) resueltos. Solo las celdas que no se pudieron resolver aparecen en unresolved con un motivo (broken · cycle · inline), conservando su valor original.

{
  "apiVersion": "v1",
  "project": { "name": "My Variables" },
  "collections": [
    { "name": "Color", "modes": ["light", "dark"] },
    { "name": "Text", "modes": ["en", "ko"] }
  ],
  "tokens": [
    {
      "key": "color/primary",
      "collection": "Color",
      "type": "COLOR",
      "valuesByMode": { "light": "#3B82F6", "dark": "#60A5FA" }
    },
    { "key": "hello", "collection": "Text", "type": "STRING", "valuesByMode": {}, "omitted": "strings" }
  ]
}

Sin include=strings, los tokens STRING siguen apareciendo, pero con valuesByMode vacío y "omitted": "strings".

Salida de código de plataforma

Añade ?format= para recibir código de plataforma generado en lugar de JSON:

formatResultadoContent-Type
css@1 (alias css)Propiedades personalizadas de CSS: el modo predeterminado en :root, los demás en [data-theme="<mode>"]text/css
swift@1 (alias swift)SwiftUI: un tipo por colección, una instancia estática por modotext/plain
compose@1 (alias compose)Jetpack Compose (Kotlin): la misma estructura que Swifttext/plain

Los formatos tienen versión. El nombre sin versión (css) es un alias permanente de @1: nunca pasa por sí solo a una versión más nueva. Dentro de una versión solo se permiten dos tipos de cambio: corregir una salida que no era sintaxis válida y corregir el escape por seguridad; ambos suben el rev del formato (listado por /formats, más abajo) e invalidan las cachés. Todo lo que cambie la representación de un valor o un identificador es una versión nueva (css@2), y la versión anterior sigue disponible durante 12 meses (se anuncia con las cabeceras Deprecation y Sunset).

curl -H "Authorization: Bearer vjt_..." \
  "https://variablejar.com/api/v1/variables?format=css" \
  > variables.css

La salida es determinista: los mismos tokens producen siempre los mismos bytes, así que la caché con ETag/If-None-Match funciona igual que con la respuesta JSON. Los alias siempre se resuelven a valores finales; las referencias sin resolver se emiten como comentarios, nunca como valores inventados. Un format desconocido devuelve 400 { "error": "unknown_format" }.

Los identificadores se derivan de los nombres de colección y de variable y no dependen del orden de tus datos: reordenar colecciones, variables o modos en Figma nunca renombra un token. Cuando dos nombres se reducen al mismo identificador, el que va primero al ordenar por su nombre original conserva el identificador simple y los demás reciben _2, _3 …; añadir un nombre nuevo que colisione puede renumerar los sufijos existentes, así que evita nombres que solo se diferencien en separadores o en mayúsculas y minúsculas. La misma variable recibe el mismo identificador sea cual sea el filtro que uses (collection, include=strings o un token limitado a algunas colecciones): los nombres se fijan primero en todo el proyecto y la respuesta se filtra después.

?collection=<name> limita la salida a una colección (400 unknown_collection si el nombre no está en el proyecto). ?view=ai@1 devuelve una vista compacta y saneada para agentes de IA (solo nombres y valores, sin valores de texto por defecto); no se puede combinar con format, y cualquier otro valor de view salvo index (más abajo) devuelve 400 unknown_view.

?view=index junto con format devuelve, en lugar de código, el identificador que recibe cada variable en ese formato, para comprobar nombres sin analizar el código generado. Los identificadores se escriben igual que en la salida (las palabras clave de Swift/Kotlin conservan sus comillas invertidas). Las variables de texto (STRING) quedan fuera del índice salvo que el token se haya emitido con valores de texto y pases include=strings. view=index sin format devuelve 400 unknown_view.

curl -H "Authorization: Bearer vjt_..." \
  "https://variablejar.com/api/v1/variables?format=css@1&view=index"
{
  "format": "css@1",
  "rev": "1-1",
  "identifiers": [
    { "collection": "Color", "key": "btn/bg", "identifier": "--color-btn-bg" }
  ]
}

GET /api/v1/formats enumera los formatos y versiones que ofrece este servidor, con el rev actual, el nombre de archivo y el Content-Type de cada uno. Usa el mismo token, no cuenta para el uso ni para el límite de solicitudes y admite ETag/If-None-Match igual que el endpoint de variables (sin X-VJ-Stamp: la lista es estática). Una versión reemplazada incluye además "deprecated": { "since": "YYYY-MM-DD", "sunset": "YYYY-MM-DD" }; sunset solo aparece cuando hay una fecha programada.

{
  "contract": "1",
  "formats": [
    { "id": "css", "version": 1, "spec": "css@1", "rev": "1-1", "alias": "css", "filename": "variables.css", "mime": "text/css; charset=utf-8" },
    { "id": "swift", "version": 1, "spec": "swift@1", "rev": "1-1", "alias": "swift", "filename": "Tokens.swift", "mime": "text/plain; charset=utf-8" },
    { "id": "compose", "version": 1, "spec": "compose@1", "rev": "1-1", "alias": "compose", "filename": "Tokens.kt", "mime": "text/plain; charset=utf-8" }
  ],
  "views": [{ "view": "ai@1", "rev": "1" }]
}

Sondeo y ETag

Las respuestas incluyen una cabecera ETag. Devuélvela como If-None-Match y obtendrás 304 (sin cuerpo) si nada ha cambiado, lo que ahorra ancho de banda en las comprobaciones periódicas desde apps móviles y CI. Usa el valor de ETag recibido tal cual (puede incluir W/).

curl -i -H "Authorization: Bearer vjt_..." \
  -H 'If-None-Match: "…"' \
  "https://variablejar.com/api/v1/variables"
# HTTP/2 304

Toda respuesta 200 o 304 lleva estas cabeceras:

CabeceraSignificado
ETag / If-None-MatchDevuelve el último ETag; si los datos no cambiaron, obtienes 304 sin cuerpo
X-VJ-StampSello de actualización del contenido del proyecto + el alcance de este token (el mismo valor en todos los formatos del mismo token): mismo sello, mismos datos en todos los formatos
X-VJ-TTLSegundos que conviene esperar antes de volver a comprobar (30–600)
X-VJ-Token-ExpiresCuándo caduca este token
X-VJ-ContractVersión del contrato de la API (1)
X-VJ-FormatFormato y versión de una respuesta con ?format=, p. ej. css@1

Errores

Las respuestas de error tienen el cuerpo { "error": "<código>" }.

EstadoSignificado
400 unknown_format · unknown_view · unknown_collectionValor de format o view desconocido, o un nombre de collection que no está en el proyecto
401 unauthorizedToken ausente, mal formado o revocado
401 token_expiredEl token caducó: emite uno nuevo
403 token_inactiveQuien emitió el token dejó el espacio de trabajo o perdió el rol que el token necesita
403 plan_requiredEl plan del espacio de trabajo no incluye acceso a la API
403 scope_deniedinclude=strings requiere un token emitido con valores de texto
404 not_foundRuta incorrecta, o el proyecto se eliminó o se movió a la papelera
405 method_not_allowedMétodo distinto de GET u OPTIONS (OPTIONS responde a la verificación previa de CORS con 204)
413 too_largeEl proyecto supera el límite de tamaño de la API (25.000 variables o 24 MB de datos de variables): mueve algunas colecciones a otro proyecto o escribe a support@variablejar.com
426 client_outdatedEl cliente declarado (X-VJ-Client) es anterior a la versión mínima que acepta este servidor: actualiza @variablejar/mcp
429 rate_limitedDemasiadas solicitudes: reintenta tras los segundos indicados en Retry-After
500 internalError del servidor: si persiste tras reintentar, escribe a support@variablejar.com
502 upstream_unreachableLa pasarela de la API no pudo llegar al backend: reintenta
503 not_configuredEl servicio no está configurado: escribe a support@variablejar.com

Servidor MCP (IDE / agentes de IA)

Desde IDE y agentes de programación con IA, el servidor MCP @variablejar/mcp es más cómodo que REST, y el mismo token sirve para ambos. Puedes pasarle esta página a un agente de IA y pedirle que configure la integración por ti.

Añádelo a tu configuración de MCP (fija la versión):

{
  "mcpServers": {
    "variablejar": {
      "command": "npx",
      "args": ["-y", "@variablejar/mcp@0.3.1"],
      "env": { "VARIABLEJAR_TOKEN": "vjt_your_token_here" }
    }
  }
}

La ubicación del archivo depende del cliente:

ClienteArchivo de configuración
Claude Code.mcp.json en la raíz del proyecto
Cursor.cursor/mcp.json
Otros clientes MCPConsulta la configuración de servidores MCP del cliente

Herramientas disponibles:

HerramientaEntradaDescripción
list_collections—Colecciones con sus modos, número de tokens, distribución por tipo y grupos de primer nivel: empieza por aquí
list_tokenscollection? prefix? type? query? format? limit (50, máx. 200) cursor? include_strings?Tokens paginados, con los valores resueltos por modo. La primera línea del bloque de datos es siempre total=<n> returned=<m> nextCursor=<c|none>. Con format (p. ej., css@1), cada token incluye además su identificador en ese formato
get_tokenkey collection? format?Un token por clave (p. ej., color/primary); si la clave existe en varias colecciones, recibes los candidatos
list_formats—Formatos y versiones que el servidor puede generar, igual que GET /formats
get_tokensformat collection?El proyecto (o una colección) como código generado. Los resultados de más de 24.000 caracteres no se truncan: la herramienta le indica al agente cómo acotar por colección. Para archivos completos en CI, usa REST y haz commit del archivo

El servidor guarda los resultados solo en memoria, vuelve a consultar la API una vez por TTL (30–600 s) y lo reutiliza todo mientras el sello de actualización del proyecto no cambie. Los resultados de las herramientas llevan los códigos de error de la API (error: unauthorized, error: plan_required, …); cuando no se puede llegar a la API, se sirve el último resultado con una nota sobre su antigüedad. Los datos de tokens van envueltos en marcadores de límite aleatorios, con un preámbulo fijo que indica que son datos, no instrucciones.

Variables de entorno:

VariableObligatoriaDescripción
VARIABLEJAR_TOKEN✓Token de API del proyecto (vjt_…): un token, un proyecto
VARIABLEJAR_API_URLhttps://variablejar.com/api/v1 (por defecto) o https://staging.variablejar.com/api/v1; cualquier otro host se rechaza

Actualizar desde 0.2.0: esa versión llama a un endpoint retirado y ahora recibe 410. Los nombres de las herramientas no cambian y las entradas solo se ampliaron, pero las salidas cambiaron: list_tokens está paginado, con una primera línea total=… y claves cortas (c, k, t, v); get_token devuelve las mismas claves cortas y, si la clave existe en varias colecciones, lista los candidatos; list_collections ya no devuelve ids, y get_tokens devuelve un bloque de preámbulo más un bloque de código dentro de marcadores de límite.

El servidor es de solo lectura: el token no puede escribir ni eliminar nada.

Notas

  • No lo llames directamente desde un navegador (frontend web): el token quedaría expuesto en el código del cliente. Úsalo desde servidores, apps o CI, donde el token queda oculto.
  • Todavía no hay API de escritura ni consultas delta (solo cambios).
  • Para contexto de LLM, toda la documentación está disponible como /llms.txt (índice) y /llms-full.txt (todo en un archivo), en inglés.