# Key-value API

> Read, write, list and delete the keys in a project's key-value store, the same store a Worker's KV binding uses.

Source: https://docs.fortly.com/api/kv

Each project has a key-value store, organized into namespaces. A Worker reads and writes it through a [KV binding](https://docs.fortly.com/kv), and you can do the same from any program with this API. Both see the same keys, as does **Storage → Key-value** in the console.

- `GET /projects/{name}/kv` — Every namespace, with its size
- `GET /projects/{name}/kv/{namespace}` — List keys
- `GET /projects/{name}/kv/{namespace}/value?key={key}` — Read a value
- `PUT /projects/{name}/kv/{namespace}/value?key={key}` — Write a value
- `DELETE /projects/{name}/kv/{namespace}/value?key={key}` — Delete a key
- `DELETE /projects/{name}/kv/{namespace}` — Delete every key in a namespace

## Limits

| | |
| --- | --- |
| Namespace name | 1 to 64 letters, digits, hyphens and underscores |
| Key | Up to 512 bytes. Not empty, `.` or `..` |
| Value | Up to 1 MiB. Store anything larger as a file in [Storage](https://docs.fortly.com/files) |
| Metadata | Up to 1024 bytes of JSON |
| Expiry | At least 60 seconds from now |

A namespace exists once it holds a key. An expired key stops being returned the moment it expires.

## List namespaces

- `GET /projects/{name}/kv` — Every namespace, with its size

```bash
curl https://api.fortly.com/projects/my-app-ada/kv \
  -H "Authorization: Bearer $FORTLY_TOKEN"
```

```json
{
  "namespaces": [
    { "namespace": "cache", "keys": 12, "bytes": 3480, "updated_at": 1792301003, "bindings": ["CACHE"] }
  ],
  "limits": { "key_bytes": 512, "value_bytes": 1048576, "metadata_bytes": 1024, "min_ttl": 60 }
}
```

`bindings` names the live Worker's KV bindings that read this namespace. A namespace the live Worker binds is listed even while it is empty.

## List keys

- `GET /projects/{name}/kv/{namespace}` — List keys

- `prefix` (string, optional) — Query. Only keys that start with this.
- `cursor` (string, optional) — Query. The `cursor` from the previous page.

Keys come back in byte order, 100 at a time. While `list_complete` is `false`, pass `cursor` to get the next page.

```json
{
  "keys": [
    { "name": "user:1", "size": 18, "expiration": null, "metadata": { "by": "signup" }, "updated_at": 1792301003 }
  ],
  "cursor": null,
  "list_complete": true
}
```

## Read a value

- `GET /projects/{name}/kv/{namespace}/value?key={key}` — Read a value

```bash
curl "https://api.fortly.com/projects/my-app-ada/kv/cache/value?key=user:1" \
  -H "Authorization: Bearer $FORTLY_TOKEN"
```

```json
{ "key": "user:1", "value": "{\"name\":\"Ada\"}", "encoding": "text", "size": 15, "metadata": null, "expiration": null }
```

`encoding` is `text` when the value is UTF-8, and `base64` otherwise, with `value` base64-encoded. A key that does not exist or has expired answers `404`.

## Write a value

- `PUT /projects/{name}/kv/{namespace}/value?key={key}` — Write a value

- `value` (string, required) — Body. The value, as text.
- `metadata` (object, optional) — Body. Any JSON, returned with the key.
- `ttl` (integer, optional) — Body. Seconds until the key expires, at least 60.

**curl**

```bash
curl -X PUT "https://api.fortly.com/projects/my-app-ada/kv/cache/value?key=user:1" \
  -H "Authorization: Bearer $FORTLY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"value": "{\"name\":\"Ada\"}", "ttl": 3600}'
```

**JavaScript**

```js
await fetch("https://api.fortly.com/projects/my-app-ada/kv/cache/value?key=user:1", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.FORTLY_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ value: JSON.stringify({ name: "Ada" }), ttl: 3600 }),
});
```

Answers `204`. A key that already exists is replaced, metadata and expiry included.

## Delete

- `DELETE /projects/{name}/kv/{namespace}/value?key={key}` — Delete a key
- `DELETE /projects/{name}/kv/{namespace}` — Delete every key in a namespace

Deleting a key answers `204`, whether or not it existed. Clearing a namespace answers `{ "deleted": 12 }`.
