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
New Use MantleDB as AI memory — connect any MCP-compatible assistant in one line of config
from zero to storage in 30 seconds
1 write JSON to any path — no setup required
curl -X POST https://mantledb.sh/v2/my-app/config \
  -H "Content-Type: application/json" \
  -d '{"theme": "dark", "lang": "en"}'
2 read it back from anywhere, instantly
curl https://mantledb.sh/v2/my-app/config
# → {"theme": "dark", "lang": "en"}
3 claim your namespace to lock it down
curl https://mantledb.sh/v2/claim/my-app
# → {"key": "a3f9...", "namespace": "my-app"}
How it Works
https://mantledb.sh/v2/my-app/users/alice/settings
                              ── namespace ──   ────────── path ──────────
namespace
Your top-level bucket. The first segment after /v2/. Unclaimed by default — anyone can use it. Claim it to add write protection.
path
Everything after the namespace. Arbitrarily deep. Each unique path stores exactly one JSON object. No nesting, no relations.
1 Namespaces

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.

2 Entries

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.

3 Claiming

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.

Tiers
Unclaimed
  • 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
Claimed
  • 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
Claimed + Credits
  • 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
Get more out of MantleDB
Credits unlock higher limits and pro features. One purchase, no subscription, no account.
  • 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
from
$3 / 30 days
curl "https://mantledb.sh/v2/upgrade/my-app"
# → open the returned URL in your browser
see how to upgrade →

Demos

Working examples built entirely on the MantleDB API — no separate backend, no database config.


API Reference
Base URL
https://mantledb.sh
Content-Type
application/json
Auth header
X-Mantle-Key: <key>
Quick Reference
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.


Namespace Management
GET /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."
}
GET /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 }
  ]
}

Data Operations
POST /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.

Free tier limits
Entries
Max 100 per namespace. Updates to existing paths are always allowed.
Payload
Max 64 KB per entry. Returns 413 if exceeded.
Add credits to raise both limits — unlimited entries, 1 MB per entry.
Pro: TTL / Auto-Expiry

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"}'
GET /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"}
PATCH /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
POST /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.
DELETE /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"}

Access Control
PUT /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}'

Pro Features
GET /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"}
  }
}
GET /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.

What credits unlock
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.
GET /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 }
  ]
}
POST /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"}
}
POST /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.

Webhook payload
event
"write" or "delete"
namespace
The namespace ID
path
The entry path that changed
data
The written JSON body, or null on 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"

Key Recovery

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.

POST /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}
POST /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."
}
GET /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."
}