V2.0.0-BETA · no-account · no-schema · SQLite-backed · free
MantleDB
A hosted JSON key-value store for side projects, prototypes, and quick hacks. No accounts. No schemas. No servers to configure.
- Store any JSON at any path — arbitrarily deep
- Claim a namespace to add write-key protection
- Atomic increments, merge patches, field-level reads
- Per-entry public/private visibility controls
- Email-based key recovery if you lose your key
- Export your entire namespace as a single JSON blob
- ★ Pro: TTL expiry, version history, webhooks, extended limits
curl -X POST https://mantledb.sh/v2/my-app/config \
-H "Content-Type: application/json" \
-d '{"theme": "dark", "lang": "en"}'
curl https://mantledb.sh/v2/my-app/config
# → {"theme": "dark", "lang": "en"}
curl https://mantledb.sh/v2/claim/my-app
# → {"key": "a3f9...", "namespace": "my-app"}
/v2/. Unclaimed by default — anyone can use it. Claim it to add write protection.
Your namespace is the first segment of any path —
/v2/my-app/....
Out of the box it's unclaimed: anyone can read and write. Good for public data and rapid prototyping.
Unclaimed namespaces are purged after 30 days of inactivity.
A path like /v2/my-app/users/alice stores one JSON object.
POST to overwrite, PATCH to merge, GET to read.
Use ?key=field on a GET to pluck a single field without fetching the whole object.
No schema to declare. Store whatever shape you need.
GET /v2/claim/:ns locks your namespace and returns a secret key.
After that, writes require X-Mantle-Key.
Reads are private by default — toggle individual entries to public as needed.
Claimed namespaces are purged after 90 days of inactivity. Buy credits to pause this clock indefinitely.
- → Anyone can read and write — no key needed
- → Great for prototypes, public config, shared state
- → Up to 100 entries, 64 KB per entry
- → Purged after 30 days of no writes
- → All writes require
X-Mantle-Key - → Reads private unless entry is marked
public_read - → Up to 100 entries, 64 KB per entry
- → Purged after 90 days of inactivity
- → Everything in Claimed, plus:
- → Unlimited entries, 1 MB per entry
- → Full namespace export
- → TTL entries — auto-expiry via
?ttl=<seconds> - → Version history — rollback any entry to a past state
- → Webhooks — HTTP callbacks on write & delete
- → Inactivity clock paused — 1 credit burned per day
- Unlimited entries & 1 MB payloads
- TTL auto-expiry on any entry
- Full version history & rollback
- Webhooks on write & delete
- Namespace never reaped while credits remain
curl "https://mantledb.sh/v2/upgrade/my-app"
# → open the returned URL in your browser
see how to upgrade →
Working examples built entirely on the MantleDB API — no separate backend, no database config.
POST /v2/increment/:ns/*pathPATCH /v2/:ns/*pathPOST /v2/:ns/*pathhttps://mantledb.sh
application/json
X-Mantle-Key: <key>
| Method | Path | What it does | Auth |
|---|---|---|---|
| Namespace | |||
| GET | /v2/claim/:ns |
Claim namespace, receive secret key | None |
| GET | /v2/list/:ns |
List all paths in a namespace | Optional |
| Data | |||
| POST | /v2/:ns/*path |
Write (overwrite) an entry | Required* |
| GET | /v2/:ns/*path |
Read entry. ?key=field to pluck one value |
Required* |
| PATCH | /v2/:ns/*path |
Merge-update an entry (RFC 7396) | Required* |
| POST | /v2/increment/:ns/*path |
Atomically increment a numeric field | Required* |
| DELETE | /v2/:ns/*path |
Delete an entry permanently | Required* |
| Access Control | |||
| PUT | /v2/visibility/:ns/*path |
Toggle per-entry public read access | Required |
| Pro Features requires credits | |||
| POST | /v2/:ns/*path?ttl= |
Write entry with auto-expiry (seconds) | Required* |
| GET | /v2/history/:ns/*path |
List past versions of an entry | Required |
| POST | /v2/restore/:ns/*path |
Restore entry to a previous version | Required |
| POST | /v2/webhooks/:ns |
Register a webhook URL | Required |
| GET | /v2/webhooks/:ns |
List registered webhooks | Required |
| DELETE | /v2/webhooks/:ns/:id |
Remove a webhook | Required |
| GET | /v2/export/:ns |
Export all entries as a single JSON object | Required |
| GET | /v2/upgrade/:ns |
Get a Stripe checkout URL to buy credits | None |
| Key Recovery | |||
| POST | /v2/email/:ns |
Set or update recovery email | Required |
| POST | /v2/recover/:ns |
Send recovery link to email on file | None |
| GET | /v2/recover/:ns?token= |
Validate token, issue new key | None |
* Required only if the namespace has been claimed. Unclaimed namespaces are open to all.
/v2/claim/:namespace
— no key required
Locks a namespace and returns a one-time secret key. The key is hashed before storage —
save it immediately, it cannot be reconstructed.
Once claimed, all writes to this namespace require X-Mantle-Key.
Claiming also extends your data retention from 30 to 90 days of inactivity.
Pass ?email= to register a recovery address at claim time.
If you lose the key, you can request a reset link via Key Recovery.
# Basic claim
curl https://mantledb.sh/v2/claim/my-app
# With a recovery email (recommended)
curl "https://mantledb.sh/v2/claim/[email protected]"
# Response
{
"success": true,
"namespace": "my-app",
"key": "a3f9...",
"warning": "SAVE THIS KEY. It cannot be recovered."
}
/v2/list/:namespace
— key optional
Returns all paths stored in a namespace along with each entry's public_read flag
and last-updated timestamp. Without a key, only public_read: true entries are returned.
curl https://mantledb.sh/v2/list/my-app \
-H "X-Mantle-Key: YOUR_KEY"
# Response
{
"namespace": "my-app",
"entries": [
{ "path": "config", "public_read": 1, "updated_at": 1748000000000 },
{ "path": "users/alice", "public_read": 0, "updated_at": 1748000001000 }
]
}
/v2/:namespace/*path
— key required on claimed namespaces
Creates or fully overwrites a JSON entry at the given path.
Paths can be as deep as you need — /v2/my-app/users/alice/settings works
without any upfront setup. If you only want to update certain fields, use
PATCH instead.
- Entries
- Max 100 per namespace. Updates to existing paths are always allowed.
- Payload
- Max 64 KB per entry. Returns
413if exceeded.
Pass ?ttl=<seconds> on any write to automatically delete the entry after that duration.
The response includes expires_at (ms timestamp). Requires credits.
# Entry expires in 1 hour
curl -X POST "https://mantledb.sh/v2/my-app/session/abc123?ttl=3600" \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"userId": 42, "token": "..."}'
# Response includes when it will expire
{"success": true, "path": "session/abc123", "expires_at": 1748003600000}
curl -X POST https://mantledb.sh/v2/my-app/users/alice \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"name": "Alice", "status": "online", "role": "admin"}'
/v2/:namespace/*path
— key required unless entry is public_read
Returns the stored JSON for the given path. On a claimed namespace, a key is required
unless that entry has public_read enabled. Use the ?key=
query param to read a single top-level field — useful for lightweight polling without
transferring the full object.
# Full entry
curl https://mantledb.sh/v2/my-app/users/alice \
-H "X-Mantle-Key: YOUR_KEY"
# → {"name": "Alice", "status": "online", "role": "admin"}
# Single field — no need to fetch the whole object
curl "https://mantledb.sh/v2/my-app/users/alice?key=status"
# → {"status": "online"}
/v2/:namespace/*path
— key required on claimed namespaces
Merges the request body into the existing entry using
JSON Merge Patch (RFC 7396).
Only the fields you send are changed — all other fields are untouched.
Set a field to null to remove it entirely.
# alice is currently: {"name": "Alice", "status": "online", "role": "admin"}
curl -X PATCH https://mantledb.sh/v2/my-app/users/alice \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"status": "away", "lastSeen": 1748000000}'
# alice is now: {"name": "Alice", "status": "away", "role": "admin", "lastSeen": 1748000000}
# Remove a field by setting it to null
# -d '{"role": null}' → removes the role field entirely
/v2/increment/:namespace/*path
— key required on claimed namespaces
Atomically increments (or decrements) a numeric field in an existing entry.
The operation runs inside a transaction — safe for concurrent updates from multiple clients.
If the entry doesn't exist yet, it is created with the field set to 0 before incrementing.
curl -X POST https://mantledb.sh/v2/increment/my-app/stats \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"key": "views", "by": 1}'
# Response
{"success": true, "views": 42}
# Use a negative value to decrement
# -d '{"key": "views", "by": -1}'
- key
- string, required — the field name to increment
- by
- number, default
1— amount to add. Negative to decrement. Decimals are fine.
/v2/:namespace/*path
— key required on claimed namespaces
Permanently removes a single entry. Returns 404 if the path does not exist.
curl -X DELETE https://mantledb.sh/v2/my-app/users/alice \
-H "X-Mantle-Key: YOUR_KEY"
# Response
{"success": true, "message": "Entry deleted"}
/v2/visibility/:namespace/*path
— key required
Toggles the public_read flag on a specific entry. When enabled, anyone can
read that entry without a key — even if the rest of the namespace is private.
This lets you expose individual endpoints (a public config, a leaderboard, an API status)
while keeping everything else locked down. Writes always require the key regardless of this setting.
# Make a single entry publicly readable
curl -X PUT https://mantledb.sh/v2/visibility/my-app/config \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"public_read": true}'
# Now anyone can read it — no key required
curl https://mantledb.sh/v2/my-app/config
# Revert to private
curl -X PUT https://mantledb.sh/v2/visibility/my-app/config \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"public_read": false}'
/v2/export/:namespace
— key required on claimed namespaces
Downloads every entry in the namespace as a single JSON object, keyed by path. Useful for backups, migrations, or seeding another system. Requires the namespace key on claimed namespaces.
curl https://mantledb.sh/v2/export/my-app \
-H "X-Mantle-Key: YOUR_KEY"
# Response
{
"namespace": "my-app",
"exported_at": "2026-03-17T12:00:00.000Z",
"entry_count": 3,
"entries": {
"config": {"theme": "dark", "lang": "en"},
"users/alice": {"name": "Alice", "role": "admin"},
"users/bob": {"name": "Bob", "role": "viewer"}
}
}
/v2/upgrade/:namespace
— no key required
Creates a Stripe Checkout session and returns a URL to complete payment. Credits are denominated in days — one unit of purchase equals 30 credits (30 days). The scavenger burns one credit per day; while credits remain, your namespace is exempt from the inactivity reaper and your limits are upgraded.
- Retention
- Inactivity clock paused. Namespace lives as long as credits remain.
- Entries
- Unlimited (free tier: 100).
- Payload
- Up to 1 MB per entry (free tier: 64 KB).
- Export
- Full namespace dump via
GET /v2/export/:ns. - TTL
- Auto-expiring entries via
?ttl=<seconds>on any write. - History
- Last 10 versions of every entry, with rollback via
/v2/restore/:ns/*path. - Webhooks
- Up to 5 HTTP callbacks per namespace, fired on write and delete events.
# Get a checkout URL — opens in browser or redirect from your app
curl "https://mantledb.sh/v2/upgrade/my-app?quantity=3"
# → {"url": "https://checkout.stripe.com/..."}
# quantity = number of 30-day blocks (1–12). Defaults to 1.
# Credits are added automatically after payment completes.
/v2/history/:namespace/*path
— key required · pro only
Returns a list of past snapshots for the given entry, newest first.
A snapshot is saved automatically before every overwrite on a pro namespace —
up to 10 versions are kept per entry. Versions include an id you can pass to /v2/restore.
curl https://mantledb.sh/v2/history/my-app/users/alice \
-H "X-Mantle-Key: YOUR_KEY"
# Response
{
"path": "users/alice",
"versions": [
{ "id": 42, "created_at": 1748001000000 },
{ "id": 37, "created_at": 1747900000000 }
]
}
/v2/restore/:namespace/*path
— key required · pro only
Restores an entry to a specific version. The current data is snapshotted before the restore (so it's recoverable too). Returns the restored data.
curl -X POST https://mantledb.sh/v2/restore/my-app/users/alice \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"version_id": 37}'
# Response
{
"success": true,
"path": "users/alice",
"restored": {"name": "Alice", "role": "viewer"}
}
/v2/webhooks/:namespace
— key required · pro only
Registers a webhook URL that will receive a POST request whenever an entry in the namespace
is written to or deleted. Up to 5 webhooks per namespace. The URL must use https://.
Optionally pass a secret — if set, each request will include an
X-Mantle-Signature: sha256=<hmac> header so you can verify the payload.
- event
"write"or"delete"- namespace
- The namespace ID
- path
- The entry path that changed
- data
- The written JSON body, or
nullon delete - timestamp
- Unix milliseconds
# Register a webhook
curl -X POST https://mantledb.sh/v2/webhooks/my-app \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"url": "https://my-server.com/hooks/mantle", "events": "write,delete", "secret": "opt-sig-key"}'
# Response
{"id": "a1b2c3...", "url": "https://my-server.com/hooks/mantle", "events": "write,delete"}
# List webhooks
curl https://mantledb.sh/v2/webhooks/my-app \
-H "X-Mantle-Key: YOUR_KEY"
# Delete a webhook
curl -X DELETE https://mantledb.sh/v2/webhooks/my-app/a1b2c3... \
-H "X-Mantle-Key: YOUR_KEY"
Lost your namespace key? If you registered an email address, you can request a one-time reset link. Tokens expire after 1 hour and requests are rate-limited to 3 per hour per IP. The old key is invalidated the moment the token is redeemed.
/v2/email/:namespace
— key required
Associates (or updates) a recovery email with a claimed namespace.
You can also set one at claim time via GET /v2/claim/:ns?email=.
curl -X POST https://mantledb.sh/v2/email/my-app \
-H "Content-Type: application/json" \
-H "X-Mantle-Key: YOUR_KEY" \
-d '{"email": "[email protected]"}'
# Response
{"success": true}
/v2/recover/:namespace
— no key required · rate limited (3/hour)
Sends a one-time recovery link to the address on file. Always responds with the same message — even if no email is registered — to prevent namespace or address enumeration.
curl -X POST https://mantledb.sh/v2/recover/my-app
# Response (same regardless of whether an email exists)
{
"success": true,
"message": "If a recovery email is on file, you'll receive it shortly."
}
/v2/recover/:namespace?token=
— no key required
Validates the recovery token from your email link and issues a new secret key. The previous key is immediately invalidated. Save the new one right away.
curl "https://mantledb.sh/v2/recover/my-app?token=TOKEN_FROM_EMAIL"
# Response
{
"success": true,
"namespace": "my-app",
"key": "b7c2...",
"warning": "SAVE THIS KEY. It cannot be recovered."
}