KV
KV Store
A global key-value store backed by Cloudflare KV. Sub-millisecond reads from 300+ edge locations. Keys are namespaced per project — no collisions between projects.
Eventual consistency: CF KV propagates writes globally within ~60 seconds. For strong read-after-write within the same edge PoP (e.g., right after setting a session), use the
cache: 'no-store' option or rely on the response body returned from PUT.Get Value
GET
/infra/kv/{key}
Retrieve the value and metadata for a single key.
curl
curl https://api.saasignal.saastemly.com/infra/kv/{key} \
-H "Authorization: Bearer sk_live_..."
json — 200 OK
{
"key": "session:u_123",
"value": { "userId": "u_123", "role": "admin" },
"expires_at": "2026-03-05T00:00:00Z"
}
typescript
const entry = await ss.infra.kv.get('session:u_123')
// entry.value, entry.expires_at
- Open Dashboard and select your project
- Go to KV Store in the sidebar
- Search or browse keys, then click any key to view its value and metadata
Path param
Type
Description
key requiredstring
Key to retrieve (1–512 chars, no control characters or
.. sequences)1–512 charspattern
^(?!.*\.\.)[^\x00-\x1f\x7f]+$Error responses
401 Unauthorized
402 Insufficient tokens
404 Not found
429 Rate limited
Set Value
PUT
/infra/kv/{key}
Create or overwrite a key-value pair. Key max 512 chars; value max 256 KB serialized.
curl
curl -X PUT https://api.saasignal.saastemly.com/infra/kv/{key} \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"value":{"example":"data"}}'
json — 200 OK
{ "key": "session:u_123", "value": { ... }, "expires_at": "2026-03-05T..." }
typescript
await ss.infra.kv.set('session:u_123', { userId: 'u_123', role: 'admin' }, { ttl: 86400 })
- Open Dashboard and select your project
- Go to KV Store → click Add Key
- Enter the key name, paste your JSON value, optionally set a TTL
- Click Save
Path param
Type
Description
key requiredstring
Key to store (1–512 chars, no control characters or
.. sequences)1–512 charspattern
^(?!.*\.\.)[^\x00-\x1f\x7f]+$Body field
Type
Description
value requiredany JSON
Value to store (max 256 KB serialized)
ttlinteger
Time-to-live in seconds. Key expires after this duration.
range >0 .. ≤9007199254740991
if_not_existsboolean
If
true, fail with 409 when the key already exists. Default false.default
falseError responses
401 Unauthorized
402 Insufficient tokens
409 Conflict
429 Rate limited
Delete Key
DELETE
/infra/kv/{key}
Remove a key and its value.
curl
curl -X DELETE https://api.saasignal.saastemly.com/infra/kv/{key} \
-H "Authorization: Bearer sk_live_..."
typescript
await ss.infra.kv.delete('session:u_123')
- Open Dashboard and select your project
- Go to KV Store and find the key
- Click the key, then click Delete
Path param
Type
Description
key requiredstring
Key to delete (1–512 chars, no control characters or
.. sequences)1–512 charspattern
^(?!.*\.\.)[^\x00-\x1f\x7f]+$Error responses
401 Unauthorized
402 Insufficient tokens
404 Not found
429 Rate limited
Increment Value
POST
/infra/kv/{key}/increment
Increment (or decrement) a numeric value.
curl
curl -X POST https://api.saasignal.saastemly.com/infra/kv/{key}/increment \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{}'
json — 200 OK
{ "status": "ok" }
typescript
// Rate limit: max 100 req/min
const { value } = await ss.infra.kv.increment(`ratelimit:${userId}`, { ttl: 60 })
if (value > 100) return new Response('Rate limited', { status: 429 })
- Increment is an API-only operation
- Use the REST API or TypeScript SDK to increment values
You can view the resulting value in Dashboard → KV Store
Path param
Type
Description
key requiredstring
Key to increment (1–512 chars, no control characters or
.. sequences)1–512 charspattern
^(?!.*\.\.)[^\x00-\x1f\x7f]+$Body field
Type
Description
deltanumber
Amount to increment (or decrement if negative). Default
1.default
1ttlinteger
Time-to-live in seconds. Applied when the key is first created.
range >0 .. ≤9007199254740991
Error responses
401 Unauthorized
402 Insufficient tokens
429 Rate limited
Scan Keys
GET
/infra/kv
Scan keys by prefix. Returns paginated key names (not values). Costs 5 μt per call.
curl
curl https://api.saasignal.saastemly.com/infra/kv \
-H "Authorization: Bearer sk_live_..."
json — 200 OK
{ "status": "ok" }
typescript
const result = await ss.infra.kv.scan({ prefix: 'session:', limit: 50 })
// result.keys, result.next_cursor
- Open Dashboard and select your project
- Go to KV Store
- Use the search bar to filter keys by prefix
Query param
Type
Description
prefixstring
Key prefix to filter by (max 512 chars). Default returns all keys.
max 512 charspattern
^(?!.*\.\.)[^\x00-\x1f\x7f]*$default cursorstring
Pagination cursor from a previous
next_cursor response.limitinteger
Max keys to return per page. Range 1–1000, default
100.range ≥1 .. ≤1000default
100Error responses
401 Unauthorized
402 Insufficient tokens
429 Rate limited
Batch Operations
POST
/infra/kv
Execute up to 100 get/set/delete operations in a single request. Each op is charged individually.
curl
curl -X POST https://api.saasignal.saastemly.com/infra/kv \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{"ops":[]}'
json — 200 OK
{
"results": [
{ "key": "config:flags", "value": { "dark_mode": true }, "status": "ok" },
{ "key": "session:new", "value": { "userId": "u_456" }, "status": "ok" },
{ "key": "session:old", "value": null, "status": "ok" }
]
}
typescript
const results = await ss.infra.kv.batch([
{ op: 'get', key: 'config:flags' },
{ op: 'set', key: 'session:new', value: { userId: 'u_456' }, ttl: 3600 },
{ op: 'delete', key: 'session:old' },
])
- Batch operations are an API-only feature
- Use the REST API or TypeScript SDK for bulk operations
You can manage keys individually in Dashboard → KV Store
Body field
Type
Description
ops requiredarray
Array of operations (max 100). Each op:
{ op: "get"|"set"|"delete", key, value?, ttl? }. value is required for set.max 100 items
Error responses
401 Unauthorized
402 Insufficient tokens
429 Rate limited