No setup, no accounts, no complexity. Just make a request.
POST to create a stash and get a token
POST your text to create an item
Use the key to GET it, no auth required
Let's store some data right now. Copy and paste this into your terminal:
# Create a stash to organize your data
curl -X POST https://wrendb.com/api/stash
stash_id and master_token. Save both!
{
"stash_id": "stash-a1b2c3d4...",
"master_token": "token-x9y8z7...",
"message": "Save this token securely..."
}
# Add an item to your stash
curl -X POST https://wrendb.com/api/item/stash-a1b2c3d4... \
-H "Content-Type: text/plain" \
-d "Hello from WrenDB!"
Here's how to use WrenDB in your favorite language:
# Create stash
curl -X POST https://wrendb.com/api/stash
# Create item in stash
curl -X POST https://wrendb.com/api/item/stash-abc123 \
-d "My data"
# List items in stash
curl https://wrendb.com/api/stash/stash-abc123/items
# Read item
curl https://wrendb.com/api/item/stash-abc123/my-key
# Update item (requires stash token)
curl -X PUT https://wrendb.com/api/item/stash-abc123/my-key \
-H "Authorization: Bearer token-xyz789" \
-d "Updated data"
# Delete item (requires stash token)
curl -X DELETE https://wrendb.com/api/item/stash-abc123/my-key \
-H "Authorization: Bearer token-xyz789"
// Create
const response = await fetch('https://wrendb.com/api/item', {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: 'My data'
});
const { key, master_token } = await response.json();
// Read (need stashId and key)
const data = await fetch(`https://wrendb.com/api/item/${stashId}/${key}`)
.then(r => r.text());
// Update
await fetch(`https://wrendb.com/api/item/${stashId}/${key}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${master_token}`,
'Content-Type': 'text/plain'
},
body: 'Updated data'
});
// Delete
await fetch(`https://wrendb.com/api/item/${stashId}/${key}`, {
method: 'DELETE',
headers: { 'Authorization': `Bearer ${master_token}` }
});
import requests
# Create
response = requests.post(
'https://wrendb.com/api/item',
data='My data',
headers={'Content-Type': 'text/plain'}
)
result = response.json()
key = result['key']
master_token = result['master_token']
# Read (need stash_id and key)
data = requests.get(f'https://wrendb.com/api/item/{stash_id}/{key}').text
# Update
requests.put(
f'https://wrendb.com/api/item/{stash_id}/{key}',
data='Updated data',
headers={
'Authorization': f'Bearer {master_token}',
'Content-Type': 'text/plain'
}
)
# Delete
requests.delete(
f'https://wrendb.com/api/item/{stash_id}/{key}',
headers={'Authorization': f'Bearer {master_token}'}
)
package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
)
func main() {
// Create
resp, _ := http.Post(
"https://wrendb.com/api/item",
"text/plain",
bytes.NewBufferString("My data"),
)
var result map[string]string
json.NewDecoder(resp.Body).Decode(&result)
key := result["key"]
token := result["master_token"]
// Read
resp, _ = http.Get("https://wrendb.com/api/item/" + stashId + "/" + key)
data, _ := io.ReadAll(resp.Body)
// Update
req, _ := http.NewRequest(
"PUT",
"https://wrendb.com/api/item/"+stashId+"/"+key,
bytes.NewBufferString("Updated"),
)
req.Header.Set("Authorization", "Bearer "+token)
http.DefaultClient.Do(req)
}
use reqwest;
use serde_json::Value;
async fn example() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
// Create
let res: Value = client
.post("https://wrendb.com/api/item")
.body("My data")
.send()
.await?
.json()
.await?;
let key = res["key"].as_str().unwrap();
let token = res["master_token"].as_str().unwrap();
// Read
let data = client
.get(&format!("https://wrendb.com/api/item/{}/{}", stash_id, key))
.send()
.await?
.text()
.await?;
Ok(())
}
Tips to get the most out of WrenDB:
Data is temporary and may be cleaned up periodically. WrenDB is designed for ephemeral storage, not permanent archives. Think of it as a scratch pad, not a vault.
There's no recovery. The token is shown only once when you create a key-value pair. If you lose it, you won't be able to update or delete that data (but anyone can still read it).
No, only text data. You can Base64-encode binary data if needed, but keep in mind the 100KB size limit.
Yes. Be respectful. If you hit rate limits, you'll get a 429 response. For high-volume use cases, consider caching reads or batching updates.
Yes, it can be used in production for small, low-volume apps where it doesn't depend on data being permanent. Keep in mind the rate limits when planning your use case.
A presigned URL is a one-time write link. When you generate it, you choose the exact value that will be stored. The URL contains a short-lived JWT (15 minutes) that authorizes that specific write. Anyone who calls the URL triggers that write — no token required. Perfect for webhooks, forms, and one-click actions.