/:idRetorna o valor atual, sua versão e os timestamps. Responde 404 quando o ID não existe.
Use um identificador como chave, envie um valor JSON e recupere-o de qualquer cliente HTTP. Cada alteração recebe uma versão e timestamps automáticos.
https://kv.helio.me
Crie ou substitua o documento completo com PUT /:id. Para alterar somente um valor, use PUT /:id/value?path=.... O corpo pode ser objeto, array, string, número, booleano ou null. Estes métodos canônicos são a opção recomendada; aliases via GET existem somente para clientes com limitação de método HTTP.
curl -X PUT https://kv.helio.me/minha_tarefa \
-H "Content-Type: application/json" \
-d '{"titulo":"Comprar café","feito":false}'
curl https://kv.helio.me/minha_tarefa
curl -X DELETE https://kv.helio.me/minha_tarefa
/:idRetorna o valor atual, sua versão e os timestamps. Responde 404 quando o ID não existe.
/:id/versionRetorna somente id e version. Útil para verificar mudanças sem baixar o valor completo.
/:idCria o ID com versão 1 ou substitui completamente o valor existente e incrementa a versão. Não faz merge de objetos.
/:id/value?path=<JSON Pointer>Cria ou substitui um único valor no caminho indicado. Cria objetos ancestrais ausentes, trata arrays com índices explícitos e retorna o item completo atualizado.
/:idApaga definitivamente o item. Se ele for recriado depois, começará novamente na versão 1.
qualquer caminhoResponde ao preflight CORS. São permitidos os headers Content-Type, Authorization, If-None-Match e If-Match.
Clientes que só conseguem emitir GET podem transportar o comando em method e o valor JSON em data. Continue preferindo PUT e DELETE reais sempre que possível.
version, não pelo timestamp.
# Leitura atual e alias explícito
GET /meu-id
GET /meu-id?method=GET
# Substituição completa
GET /meu-id?method=PUT&data=eyJub21lIjoiQW5hIn0
# Alteração por JSON Pointer
GET /meu-id/value?method=PUT&path=%2Fnome&data=IkJpYSI
# Exclusão
GET /meu-id?method=DELETE
# Versão, sempre somente leitura
GET /meu-id/version
data contém um valor JSON completo codificado em UTF-8 e depois em base64url canônico sem padding. eyJub21lIjoiQW5hIn0 representa {"nome":"Ana"}; IkJpYSI representa a string JSON "Bia".
const valor = { nome: "Ana" };
const data = Buffer.from(JSON.stringify(valor), "utf8").toString("base64url");
console.log(data); // eyJub21lIjoiQW5hIn0
function base64urlJson(value) {
const bytes = new TextEncoder().encode(JSON.stringify(value));
let binary = "";
for (const byte of bytes) binary += String.fromCharCode(byte);
return btoa(binary)
.replaceAll("+", "-")
.replaceAll("/", "_")
.replace(/=+$/, "");
}
const data = base64urlJson({ nome: "Ana" });
method, data e seus valores são case-sensitive. Aceite somente GET, PUT e DELETE em maiúsculas nas rotas documentadas.GET /:id, method=GET aceita somente method; method=PUT exige exatamente um data; method=DELETE aceita somente method.GET /:id/value, somente method=PUT é válido, com exatamente um method, um path e um data.GET /:id sem o nome exato method continua sendo leitura e tolera queries alheias.method só altera uma requisição cujo método HTTP real é GET. Queries com esses nomes não reinterpretam um PUT ou DELETE real.GET /:id/version é sempre somente leitura. GET /:id/value sem method continua respondendo 405.data aceita no máximo 10.000 bytes UTF-8; a forma codificada aceita no máximo 13.334 caracteres.path percent-encoded e data compartilham esse orçamento; um caminho maior deixa menos espaço para data.Cache-Control: no-store e Referrer-Policy: no-referrer reduzem alguns riscos, mas não impedem execução automática, histórico ou logs intermediários.Envie um único valor JSON bruto para PUT /:id/value e informe o endereço no parâmetro path. Esta operação não é JSON Patch nem JSON Merge Patch: ela cria ou substitui exatamente um valor.
curl -X PUT \
"https://kv.helio.me/config/value?path=%2Finterface%2Ftema" \
-H "Content-Type: application/json" \
-d '"escuro"'
curl -X PUT \
"https://kv.helio.me/config/value?path=%2Fpreferencias%2Fnotificacoes%2Femail" \
-H "Content-Type: application/json" \
-d 'true'
Se o ID não existir, ele começa como {}. Objetos ausentes são criados recursivamente. Assim, /items/0/name em um item ausente cria chaves de objeto chamadas items, 0 e name; a API nunca infere um array a partir de um token numérico.
| Situação | Comportamento |
|---|---|
| Objeto | Todo token é uma chave literal, inclusive 0, - e a chave vazia. |
| Array existente | Use 0 ou um inteiro positivo sem zeros à esquerda. Índices existentes são substituídos. |
| Índice = tamanho | Adiciona um elemento ao final. Repetir o mesmo índice substitui esse elemento, sem adicionar outro. |
| Índice > tamanho | Retorna ARRAY_INDEX_OUT_OF_BOUNDS; lacunas não são criadas. |
/- em array | Retorna INVALID_ARRAY_INDEX. Append por hífen não é suportado. |
Folha escalar ou null | Pode ser substituída normalmente. |
Ancestral escalar ou null | Retorna PATH_TYPE_CONFLICT; a API não sobrescreve o bloqueador. |
O caminho usa JSON Pointer. Dentro de um segmento, escreva ~0 para a chave ~ e ~1 para a chave /. Primeiro monte o JSON Pointer e depois codifique-o como parâmetro de URL. path= é proibido porque apontaria para o documento completo; path=/ é válido e aponta para uma chave vazia.
const query = new URLSearchParams({ path: "/a~1b/tema" });
const response = await fetch(
"https://kv.helio.me/config/value?" + query,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify("escuro"),
},
);
version, mesmo quando o valor final não muda.PUT /:id pode armazenar JSON mais profundo, mas ele precisa ser substituído por um documento de até 1.000 níveis antes de aceitar atualizações por caminho.9007199254740993 e 1e400.PUT /:id continua preservando o texto JSON bruto e substituindo o documento completo.If-Match.Uma criação ou consulta retorna o envelope abaixo. O campo json contém exatamente o tipo de valor enviado.
{
"id": "minha_tarefa",
"version": 1,
"created_at": "2026-07-12T22:32:19.374Z",
"updated_at": "2026-07-12T22:32:19.374Z",
"json": {
"titulo": "Comprar café",
"feito": false
}
}
Começa em 1 e aumenta a cada gravação bem-sucedida, inclusive aliases PUT via GET e valores que não mudam o resultado.
Instante UTC da criação. Registros antigos podem retornar null.
Instante UTC da última gravação. Na criação, é igual a created_at. Registros antigos ainda não atualizados podem retornar null.
Qualquer valor JSON válido, sem campos obrigatórios como feito.
{
"id": "minha_tarefa",
"version": 1
}
{
"ok": true,
"id": "minha_tarefa"
}
A API aceita CORS de qualquer origem e pode ser chamada diretamente pelo navegador.
const response = await fetch("https://kv.helio.me/preferencias", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ tema: "escuro", idioma: "pt-BR" }),
});
if (!response.ok) throw new Error("Falha ao salvar");
const item = await response.json();
console.log(item.version);
const response = await fetch("https://kv.helio.me/preferencias");
if (response.status === 404) {
console.log("O ID ainda não existe");
} else if (response.ok) {
const item = await response.json();
console.log(item.json);
}
const query = new URLSearchParams({ path: "/interface/tema" });
const updated = await fetch(
"https://kv.helio.me/preferencias/value?" + query,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify("claro"),
},
).then((response) => response.json());
| Regra | Valor |
|---|---|
| ID | De 1 a 100 caracteres: letras ASCII, números, hífen e sublinhado. |
| Expressão | ^[A-Za-z0-9_-]{1,100}$ |
| Payload | Máximo de 1.900.000 bytes em UTF-8. |
| Data via GET | Máximo de 10.000 bytes UTF-8 após decodificar base64url; máximo codificado de 13.334 caracteres. |
| URL mutante via GET | Máximo preventivo de 15.000 bytes na URL absoluta, abaixo do limite de 16 KB da plataforma. |
| Resultado | Uma mutação por caminho também deve resultar em no máximo 1.900.000 bytes UTF-8. |
| JSON Pointer | Máximo de 4.096 bytes UTF-8 após decodificar a URL e 64 segmentos; o caminho raiz é proibido. |
| Aninhamento por caminho | O resultado aceita no máximo 1.000 níveis de objetos e arrays, conforme o limite do JSON1. |
| Atualização | PUT /:id substitui tudo; PUT /:id/value cria ou substitui exatamente um valor. |
| Rate limit | 30 requisições por IP a cada 10 segundos. |
| Cache | Respostas da API usam Cache-Control: no-store. |
| Referer | Respostas usam Referrer-Policy: no-referrer como mitigação parcial para dados na URL. |
| CORS | Qualquer origem pode chamar a API; OPTIONS responde ao preflight. |
| Autenticação | Nenhuma. |
tarefa_1
config-app
usuario123
01J2Y8N7R6K5M4
minha tarefa # espaço
perfil.json # ponto
ação # caracteres fora de ASCII
pasta/item # barra cria outro segmento de rota
Falhas da API retornam JSON estruturado. code é estável para automação, retryable informa se repetir pode resolver o problema e hint sugere a próxima ação. Campos de contexto variam por código e nunca incluem o documento armazenado, data, seus bytes decodificados ou o JSON recebido.
{
"error": "O caminho atravessa um valor que não é objeto nem array.",
"code": "PATH_TYPE_CONFLICT",
"retryable": false,
"hint": "Substitua primeiro o valor bloqueador por um objeto ou use PUT /:id para substituir o documento completo.",
"path": "/perfil/tema",
"blocked_at": "/perfil",
"actual_type": "string",
"required_type": "object_or_array"
}
| Status | code | Contexto adicional | Próxima ação |
|---|---|---|---|
400 | INVALID_ID | id, regra | Use de 1 a 100 letras ASCII, números, hífens ou sublinhados. |
404 | INVALID_ROUTE | path | Consulte GET / e corrija a rota. |
404 | ITEM_NOT_FOUND | id | Confira o ID ou crie o item com PUT /:id. |
405 | METHOD_NOT_ALLOWED | Cabeçalho Allow | Use um dos métodos listados em Allow. |
400 | INVALID_JSON | Nenhum | Envie exatamente um valor JSON válido. |
400 | INVALID_UTF8 | Nenhum | Codifique o valor JSON como UTF-8 válido. |
413 | PAYLOAD_TOO_LARGE | max_bytes e, quando conhecido, received_bytes | Reduza o corpo para no máximo 1.900.000 bytes. |
400 | DUPLICATE_METHOD_PARAMETER | method_count | Envie exatamente um parâmetro method. |
400 | INVALID_METHOD_PARAMETER | accepted_methods | Use somente o valor method documentado para a rota. |
400 | UNEXPECTED_QUERY_PARAMETER | parameters, sem valores | Remova todos os parâmetros não documentados para o comando. |
400 | MISSING_DATA_PARAMETER | Nenhum | Envie exatamente um data com JSON UTF-8 em base64url sem padding. |
400 | DUPLICATE_DATA_PARAMETER | data_count | Remova os parâmetros data extras. |
400 | INVALID_DATA_ENCODING | reason | Use base64url canônico sem padding, whitespace ou alfabeto base64 padrão. |
413 | QUERY_DATA_TOO_LARGE | max_bytes e, quando conhecido, received_bytes | Reduza o JSON decodificado de data para até 10.000 bytes. |
414 | URI_TOO_LONG | uri_bytes, max_uri_bytes | Reduza data, path ou o tamanho total da URL. |
400 | MISSING_PATH_PARAMETER | Nenhum | Envie exatamente um parâmetro path. |
400 | DUPLICATE_PATH_PARAMETER | path_count | Remova os parâmetros path extras. |
400 | INVALID_JSON_POINTER | path, reason | Comece com / e use somente os escapes ~0 e ~1. |
400 | ROOT_PATH_NOT_ALLOWED | Nenhum | Use PUT /:id para substituir o documento completo. |
414 | PATH_TOO_LONG | path_bytes, max_path_bytes | Reduza o caminho decodificado para até 4.096 bytes UTF-8. |
400 | PATH_TOO_DEEP | segments, max_segments | Reduza o caminho para até 64 segmentos. |
409 | PATH_TYPE_CONFLICT | path, blocked_at, actual_type, required_type | Troque o ancestral bloqueador por objeto ou array antes da mutação. |
409 | INVALID_ARRAY_INDEX | path, token e regra ou limite aceito | Use índice canônico entre zero e o tamanho atual do array. |
409 | ARRAY_INDEX_OUT_OF_BOUNDS | path, index, array_length | Use um índice existente ou o tamanho atual para adicionar ao final. |
409 | AMBIGUOUS_PATH | Nenhum | Normalize chaves duplicadas com substituição completa. |
409 | STORED_JSON_INVALID | Nenhum | Substitua o documento completo por JSON válido. |
409 | STORED_JSON_TOO_DEEP | document_depth, max_depth | Substitua o documento completo por JSON com até 1.000 níveis. |
409 | WRITE_CONFLICT | retryable: true | Leia a versão atual e tente novamente. |
422 | RESULT_TOO_LARGE | result_bytes, max_bytes | Reduza o valor ou substitua o documento por uma versão menor. |
422 | RESULT_TOO_DEEP | result_depth, max_depth | Reduza o resultado para até 1.000 níveis de objetos e arrays. |
500 | STORE_FAILED | Nenhum | Consulte o item antes de repetir; o estado da gravação pode ser incerto. |
O WAF pode retornar 429 antes de a requisição chegar à API. Nesse caso, aguarde o período de bloqueio e tente novamente; o corpo não segue necessariamente o contrato estruturado acima.