Referência da API

Busque as variáveis do variable Jar de qualquer lugar — apps iOS/Android, pipelines de CI — via REST. Somente leitura, com o mesmo token do servidor MCP.

Beta: a API e o MCP podem mudar antes do lançamento; os formatos agora têm versão (veja Saída de código de plataforma), e mudanças incompatíveis são anunciadas com 12 meses de convivência.

Emitir um token

  1. variablejar.com/app → o menu ⋯ do cartão de um projeto → Propriedades → a seção Tokens de API (MCP)
  2. Digite um nome para o token e clique em Emitir — o token (vjt_…) aparece uma única vez, logo depois da emissão. Guarde-o num lugar seguro.
  3. Um token dá acesso só àquele projeto. Se ele vazar, revogue-o na hora, na mesma tela.

Os tokens expiram (180 dias por padrão, até 365). Você recebe uma notificação no sino 14 dias antes. Só o proprietário do espaço de trabalho pode emitir um token que inclua valores de texto (STRING) — saem todos os idiomas, inclusive traduções não publicadas. Também dá para limitar um token a coleções escolhidas.

Um token é tão seguro quanto o lugar onde você o guarda: quem o tiver recebe todos os valores dentro do seu escopo. Os dados que você exporta pela API ou pelo MCP saem do serviço e são tratados sob sua responsabilidade.

Endpoint

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

Os valores de texto (STRING) só vêm incluídos se o token foi emitido com valores de texto e você adicionar ?include=strings.

Resposta

Os valores são finais, com os aliases ({Collection/key}) resolvidos. Só as células que não puderam ser resolvidas aparecem em unresolved com um motivo (broken · cycle · inline), mantendo o 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" }
  ]
}

Sem include=strings, os tokens STRING continuam listados, mas com valuesByMode vazio e "omitted": "strings".

Saída de código de plataforma

Adicione ?format= para receber código de plataforma gerado em vez de JSON:

formatSaídaContent-Type
css@1 (alias css)Propriedades personalizadas de CSS — modo padrão em :root, outros modos em [data-theme="<mode>"]text/css
swift@1 (alias swift)SwiftUI — um tipo por coleção, uma instância estática por modotext/plain
compose@1 (alias compose)Jetpack Compose (Kotlin) — mesma estrutura do Swifttext/plain

Os formatos têm versão. O nome sem versão (css) é um alias permanente de @1 — ele nunca passa sozinho para uma versão mais nova. Dentro de uma versão, só dois tipos de mudança são permitidos: corrigir uma saída que não era sintaxe válida e corrigir o escape por segurança; os dois aumentam o rev do formato (listado por /formats, abaixo) e invalidam os caches. Qualquer coisa que mude a representação de um valor ou um identificador é uma nova versão (css@2), e a versão anterior continua disponível por 12 meses (anunciado com os cabeçalhos Deprecation e Sunset).

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

A saída é determinística — tokens idênticos sempre geram bytes idênticos, então o cache com ETag/If-None-Match funciona do mesmo jeito que na resposta JSON. Os aliases são sempre resolvidos para valores finais; referências não resolvidas saem como comentários, nunca como valores inventados. Um format desconhecido retorna 400 { "error": "unknown_format" }.

Os identificadores vêm dos nomes de coleção e de variável e não dependem da ordem dos seus dados: reordenar coleções, variáveis ou modos no Figma nunca renomeia um token. Quando dois nomes resultam no mesmo identificador, o que vem primeiro na ordenação (pelo nome original) fica com o identificador simples e os outros recebem _2, _3 …; adicionar um novo nome em conflito pode renumerar os sufixos existentes, então evite nomes que só diferem em separadores ou em maiúsculas e minúsculas. A mesma variável recebe o mesmo identificador seja qual for o filtro usado (collection, include=strings ou um token limitado a algumas coleções): os nomes são definidos primeiro no projeto inteiro e a resposta é filtrada depois.

?collection=<name> limita a saída a uma coleção (400 unknown_collection se o nome não estiver no projeto). ?view=ai@1 retorna uma visão compacta e higienizada para agentes de IA (só nomes e valores, sem valores de texto por padrão); não dá para combinar com format, e qualquer outro valor de view além de index (abaixo) retorna 400 unknown_view.

?view=index junto com format retorna, em vez de código, o identificador que cada variável recebe naquele formato — para conferir nomes sem analisar o código gerado. Os identificadores são escritos como na saída (palavras-chave do Swift/Kotlin mantêm as crases). Variáveis de texto (STRING) ficam fora do índice, a menos que o token tenha sido emitido com valores de texto e você passe include=strings. view=index sem format retorna 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 lista os formatos e versões que este servidor oferece, com o rev atual, o nome de arquivo e o Content-Type de cada um. Usa o mesmo token, não conta para o uso nem para o limite de solicitações e aceita ETag/If-None-Match como o endpoint de variáveis (sem X-VJ-Stamp — a lista é estática). Uma versão substituída também traz "deprecated": { "since": "YYYY-MM-DD", "sunset": "YYYY-MM-DD" }; sunset só aparece quando há uma data marcada.

{
  "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" }]
}

Polling e ETag

As respostas incluem um cabeçalho ETag. Envie-o de volta como If-None-Match e você recebe 304 (sem corpo) quando nada mudou — economizando banda nas verificações periódicas de apps móveis e da CI. Use o valor de ETag recebido como está (ele pode incluir W/).

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

Toda resposta 200 ou 304 traz estes cabeçalhos:

CabeçalhoSignificado
ETag / If-None-MatchEnvie de volta o último ETag; sem mudanças, você recebe 304 sem corpo
X-VJ-StampSelo de atualização do conteúdo do projeto + do escopo deste token (o mesmo valor em todos os formatos do mesmo token) — mesmo selo, mesmos dados em todos os formatos
X-VJ-TTLSegundos de espera antes de verificar de novo (30–600)
X-VJ-Token-ExpiresQuando este token expira
X-VJ-ContractVersão do contrato da API (1)
X-VJ-FormatFormato e versão de uma resposta ?format=, por exemplo css@1

Erros

As respostas de erro têm o corpo { "error": "<código>" }.

StatusSignificado
400 unknown_format · unknown_view · unknown_collectionValor de format ou view desconhecido, ou um nome de collection que não está no projeto
401 unauthorizedToken ausente / malformado / revogado
401 token_expiredO token expirou — emita um novo
403 token_inactiveQuem emitiu o token saiu do espaço de trabalho ou perdeu a função de que o token precisa
403 plan_requiredO plano do espaço de trabalho não inclui acesso à API
403 scope_deniedinclude=strings exige um token emitido com valores de texto
404 not_foundCaminho errado, ou o projeto foi excluído ou movido para a lixeira
405 method_not_allowedMétodo diferente de GET ou OPTIONS (OPTIONS responde à verificação prévia de CORS com 204)
413 too_largeO projeto passa do limite de tamanho da API (25.000 variáveis ou 24 MB de dados de variáveis) — mova algumas coleções para outro projeto ou fale com support@variablejar.com
426 client_outdatedO cliente informado (X-VJ-Client) é mais antigo que a versão mínima que este servidor aceita — atualize @variablejar/mcp
429 rate_limitedMuitas solicitações — tente de novo depois dos segundos indicados em Retry-After
500 internalErro do servidor — se continuar depois de tentar de novo, fale com support@variablejar.com
502 upstream_unreachableO gateway da API não conseguiu alcançar o backend — tente de novo
503 not_configuredO serviço não está configurado — fale com support@variablejar.com

Servidor MCP (IDE / agentes de IA)

Em IDEs e agentes de programação com IA, o servidor MCP @variablejar/mcp é mais prático que o REST — o mesmo token serve para os dois. Você pode passar esta página para um agente de IA e pedir que ele configure a integração para você.

Adicione à sua configuração de MCP (fixe a versão):

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

O local do arquivo depende do cliente:

ClienteArquivo de configuração
Claude Code.mcp.json na raiz do projeto
Cursor.cursor/mcp.json
Outros clientes MCPVeja as configurações de servidor MCP do cliente

Ferramentas disponíveis:

FerramentaEntradaDescrição
list_collections—Coleções com os modos, a contagem de tokens, a distribuição por tipo e os grupos de primeiro nível — comece por aqui
list_tokenscollection? prefix? type? query? format? limit (50, máx. 200) cursor? include_strings?Tokens paginados, com os valores resolvidos por modo. A primeira linha do bloco de dados é sempre total=<n> returned=<m> nextCursor=<c|none>. Com format (por exemplo, css@1), cada token também traz o identificador naquele formato
get_tokenkey collection? format?Um único token pela chave (por exemplo, color/primary); se a chave existir em várias coleções, você recebe os candidatos
list_formats—Formatos e versões que o servidor consegue gerar, igual a GET /formats
get_tokensformat collection?O projeto (ou uma coleção) como código gerado. Resultados acima de 24.000 caracteres não são truncados — a ferramenta explica ao agente como restringir por coleção. Para arquivos inteiros no CI, use o REST e faça commit do arquivo

O servidor mantém os resultados só na memória, verifica a API de novo uma vez por TTL (30–600 s) e reaproveita tudo enquanto o selo de atualização do projeto não mudar. Os resultados das ferramentas trazem os códigos de erro da API (error: unauthorized, error: plan_required, …); quando não é possível alcançar a API, o último resultado é entregue com uma nota sobre a idade dele. Os dados de tokens vêm envolvidos em marcadores de limite aleatórios, com um preâmbulo fixo dizendo que são dados, não instruções.

Variáveis de ambiente:

VariávelObrigatóriaDescrição
VARIABLEJAR_TOKEN✓Token de API do projeto (vjt_…) — um token, um projeto
VARIABLEJAR_API_URLhttps://variablejar.com/api/v1 (padrão) ou https://staging.variablejar.com/api/v1; qualquer outro host é recusado

Atualizando a partir da 0.2.0: essa versão chama um endpoint desativado e agora recebe 410. Os nomes das ferramentas não mudaram e as entradas só ganharam acréscimos, mas as saídas mudaram — list_tokens é paginado, com uma primeira linha total=… e chaves curtas (c, k, t, v); get_token retorna as mesmas chaves curtas e lista os candidatos quando a chave existe em várias coleções; list_collections não retorna mais ids; e get_tokens retorna um bloco de preâmbulo mais um bloco de código dentro de marcadores de limite.

O servidor é somente leitura — o token não consegue gravar nem excluir nada.

Observações

  • Não chame direto de um navegador (frontend web) — o token ficaria exposto no código do cliente. Use em servidores, apps ou CI, onde o token fica escondido.
  • Ainda não há APIs de gravação nem consultas delta (só mudanças).
  • Para contexto de LLM, a documentação completa está disponível em /llms.txt (índice) e /llms-full.txt (tudo num arquivo só), em inglês.