Key-value interface

POST /kv implements Redis string and hash command semantics over HTTP, against the same walk-in database as /sql.

This is not a RESP wire endpoint. redis-py, ioredis and node-redis open a raw TCP socket and speak RESP immediately, so they cannot reach an HTTP path and will not work against /kv. A raw TCP port is not available. Use plain HTTP as shown below.

Request shape

The body is a JSON array whose first element is the command name. A {"command": [...]} envelope is also accepted, and numeric arguments need not be quoted. Session handling, rate limits, TTL and quotas are identical to /sql — omit X-Walkin-Session to provision a new walk-in, or pass it to reach an existing one.

curl -i -X POST https://api.walkindb.com/kv \
  -H "content-type: application/json" \
  -d '["SET","session:42","ready","EX","300"]'

# HTTP/2 200
# x-walkin-session: wkn_AZ159u9PdmS97ks7FnSmnRc6...
# x-walkin-ttl: 1775868670
# {"result":"OK"}

curl -X POST https://api.walkindb.com/kv \
  -H "X-Walkin-Session: wkn_AZ159u9PdmS97ks7FnSmnRc6..." \
  -H "content-type: application/json" \
  -d '["HSET","user:1","name","ada","role","admin"]'
# {"result":2}

curl -X POST https://api.walkindb.com/kv \
  -H "X-Walkin-Session: wkn_AZ159u9PdmS97ks7FnSmnRc6..." \
  -d '["HGETALL","user:1"]'
# {"result":{"name":"ada","role":"admin"}}

Replies are always {"result": <value>}, where the value is a string, integer, array, object, or null (Redis’s nil reply). Errors are {"error": "..."}.

Supported commands

Anything not listed returns unknown command.

GroupCommands
StringsSET (EX, PX, NX, XX, KEEPTTL), GET, GETDEL, APPEND, STRLEN, INCR, INCRBY, DECR, DECRBY, GETRANGE, MSET, MGET
HashesHSET, HSETNX, HGET, HMGET, HDEL, HGETALL, HEXISTS, HKEYS, HVALS, HLEN, HINCRBY
KeyspaceDEL, EXISTS, TYPE, EXPIRE, PEXPIRE, PERSIST, TTL, PTTL
ConnectionPING, ECHO

Divergences from Redis

Three, and they are deliberate:

  1. TTL is clamped to the instance deadline. A per-key expiry cannot outlive the walk-in holding it, so EXPIRE k 3600 inside a 10-minute instance stores the instance deadline and TTL returns roughly 600, not 3600. Keys with no explicit TTL also report the instance bound rather than -1, because claiming “no expiry” for something guaranteed to vanish would be false.
  2. Values are UTF-8 strings. Redis strings are binary-safe; JSON is not. Base64-encode arbitrary bytes yourself.
  3. No pipelining, transactions, pub/sub, streams, sorted sets or Lua. One command per request.

Error messages match Redis wording so clients that branch on them behave: WRONGTYPE Operation against a key holding the wrong kind of value and value is not an integer or out of range.

It is the same database

KV state lives in two ordinary tables inside your own walk-in — _wk_kv (strings and key metadata) and _wk_kv_h (hash fields). Both are readable and writable over /sql:

curl -X POST https://api.walkindb.com/kv \
  -d '["SET","greeting","hello"]'

curl -X POST https://api.walkindb.com/sql \
  -H "X-Walkin-Session: wkn_..." \
  -d '{"sql":"SELECT k, v FROM _wk_kv"}'
# {"columns":["k","v"],"rows":[["greeting","hello"]],"rows_affected":0}

This works both ways: rows inserted, updated or deleted through /sql are observed by /kv immediately. Do not create your own tables named _wk_kv or _wk_kv_h.

A hash and a one-level JSON object are interchangeable — json_group_object(f, v) over _wk_kv_h produces JSON matching HGETALL key-for-key, and json_each explodes a flat document back into hash fields. Nested documents do not round-trip through hashes, because Redis hashes are flat.

Trademarks

Redis is a registered trademark of Redis Ltd. Valkey is a trademark of LF Projects, LLC. walkindb is not affiliated with, endorsed by, or sponsored by either.

Also see