Skip to main content
Get up and running with KV: create a namespace, then use it from a TypeScript function through an env binding, or from anywhere through the REST API.

1. Create a Namespace

A namespace is an isolated key space. Create one with the CLI or the API.
The response includes the namespace id (a UUID) — you’ll need it in the next step.
A new namespace starts in status: "pending" and isn’t writable yet: writes return 409 ("Namespace is not ready (status: pending)") until provisioning finishes, which typically takes a few seconds and can stretch to ~20. If you’re scripting, poll GET https://api.telnyx.com/v2/storage/kvs/{id} until "status": "provision_ok" before your first write. (With the binding path below you rarely notice — editing func.toml and deploying already takes longer than provisioning.)

Path A: The Function Binding

Recommended for TypeScript edge functions. The runtime injects the credential, so your code holds no API key.

2. Bind the Namespace

Declare the namespace in func.toml. The block key is a name you choose — it’s not a reserved word — and it becomes the property on env. This example uses MY_KV, so the binding is reached as env.MY_KV:
Add @telnyx/edge-runtime (≥ 0.2.2) to your package.json dependencies, then regenerate the environment types:
Each [storage.kv.<NAME>] block becomes env.<NAME>: KvNamespace in the generated telnyx-env.d.ts — declare as many namespaces as you need. KV type generation requires CLI ≥ v0.2.3 (earlier releases report the block as an unrecognized key and write an empty Env). The binding itself resolves at runtime from func.toml — types are for the compiler, and a stale telnyx-env.d.ts doesn’t affect the deployed function.

3. Use env.MY_KV in Your Code

The binding surface:
list() returns key metadata, not values — { keys: [{ name, sizeBytes, updatedAt }], list_complete, cursor? }. Paginate by passing the returned cursor back in list({ cursor }). On 0.2.1 entries carry only name; 0.2.0 throws a response-shape error.
put’s expirationTtl option requires ≥ 0.2.2 — earlier versions accept it but silently ignore it. The metadata option is deprecated and ignored on every version. See Key Expiration.

Path B: The REST API

Use this anywhere outside a TypeScript edge function — a non-TypeScript function (Go, JS, Python, Quarkus), your own backend, or tooling. Authenticate with your TELNYX_API_KEY (the SDKs read it from the environment). Whether you use an SDK or plain HTTP, the value is the raw request/response body — no base64, no envelope.
KV support landed in the official server SDKs in telnyx-node ≥ 7.5.0, telnyx-python ≥ 4.166.0, telnyx-php ≥ 7.88.0 (see the PHP tab for the required version pin), telnyx-ruby ≥ 5.152.0, and telnyx-go ≥ v4.85.0 — on earlier versions the storage resource is object storage (buckets) only. The Java SDK doesn’t cover KV yet; call the endpoints over plain HTTP as in the curl tab.
Server-side TTL (ttl_secs), its error cases, and an inspectable application-level alternative are covered in Key Expiration. list returns key names and per-key metadata, never values:
When meta.has_more is true, pass the returned meta.cursor back as ?cursor= (in the SDKs, the cursor parameter) to fetch the next page — key listing does not auto-paginate in any SDK.
Inside an edge function, the org binding injects TELNYX_API_KEY (and a base-URL proxy) at runtime, so REST calls from a function authenticate without you shipping a key.
Next: Best Practices for key naming, serialization, and error handling.