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
- variablejar.com/app → o menu ⋯ do cartão de um projeto → Propriedades → a seção Tokens de API (MCP)
- 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. - 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:
| format | Saída | Content-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 modo | text/plain |
compose@1 (alias compose) | Jetpack Compose (Kotlin) — mesma estrutura do Swift | text/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çalho | Significado |
|---|---|
ETag / If-None-Match | Envie de volta o último ETag; sem mudanças, você recebe 304 sem corpo |
X-VJ-Stamp | Selo 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-TTL | Segundos de espera antes de verificar de novo (30–600) |
X-VJ-Token-Expires | Quando este token expira |
X-VJ-Contract | Versão do contrato da API (1) |
X-VJ-Format | Formato e versão de uma resposta ?format=, por exemplo css@1 |
Erros
As respostas de erro têm o corpo { "error": "<código>" }.
| Status | Significado |
|---|---|
400 unknown_format · unknown_view · unknown_collection | Valor de format ou view desconhecido, ou um nome de collection que não está no projeto |
401 unauthorized | Token ausente / malformado / revogado |
401 token_expired | O token expirou — emita um novo |
403 token_inactive | Quem emitiu o token saiu do espaço de trabalho ou perdeu a função de que o token precisa |
403 plan_required | O plano do espaço de trabalho não inclui acesso à API |
403 scope_denied | include=strings exige um token emitido com valores de texto |
404 not_found | Caminho errado, ou o projeto foi excluído ou movido para a lixeira |
405 method_not_allowed | Método diferente de GET ou OPTIONS (OPTIONS responde à verificação prévia de CORS com 204) |
413 too_large | O 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_outdated | O cliente informado (X-VJ-Client) é mais antigo que a versão mínima que este servidor aceita — atualize @variablejar/mcp |
429 rate_limited | Muitas solicitações — tente de novo depois dos segundos indicados em Retry-After |
500 internal | Erro do servidor — se continuar depois de tentar de novo, fale com support@variablejar.com |
502 upstream_unreachable | O gateway da API não conseguiu alcançar o backend — tente de novo |
503 not_configured | O 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:
| Cliente | Arquivo de configuração |
|---|---|
| Claude Code | .mcp.json na raiz do projeto |
| Cursor | .cursor/mcp.json |
| Outros clientes MCP | Veja as configurações de servidor MCP do cliente |
Ferramentas disponíveis:
| Ferramenta | Entrada | Descriçã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_tokens | collection? 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_token | key 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_tokens | format 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ável | Obrigatória | Descrição |
|---|---|---|
VARIABLEJAR_TOKEN | ✓ | Token de API do projeto (vjt_…) — um token, um projeto |
VARIABLEJAR_API_URL | https://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.