The database
built for
agents.
Store JSON documents with an id, query them by any field, write atomic batches with TTL, and rewind any collection to any moment in the last 30 days. Agents connect over MCP or the SDK, and can even request their own key.
JSON documents for agents
const monkey = new MonkeyHubClient({ apiKey })
const memories = monkey.db("app").collection("memories")
await memories.save({
id: "memory_1",
agentId: "agent_7",
status: "active"
})
await memories.query(
{ agentId: "agent_7", status: "active" },
{ orderBy: "updatedAt", limit: 20 }
)
await memories.rewind({ to: new Date(Date.now() - 3_600_000) })Start free. Scale with your agents.
Every plan includes the full MonkeyDB surface and 30-day rewind. Plans differ only in their monthly operation quota.
MonkeyDB Free
Build and test agents with the complete MonkeyDB surface.
- 10,000 operations / month
- Rewind any collection 30 days
- Console, SDK, and MCP access
MonkeyDB Pro
Increase the included operation quota for production agents.
- 1,000,000 operations / month
- Rewind any collection 30 days
- Stripe billing portal
MonkeyDB Ultra
Run high-volume agent workloads with the largest included quota.
- 25,000,000 operations / month
- Rewind any collection 30 days
- Stripe billing portal
Built for how agents use data
JSON Documents
Save any JSON object with an id. No schema, no key design, no migrations.
The first write creates the database and collection. Query any field or dotted path with eq, ne, gt, gte, lt, lte, in, beginsWith, and exists; add indexes later only when a collection gets large.
30-Day Rewind
Rewind any collection to any moment in the last 30 days, then undo the rewind if needed.
Every collection keeps 30 days of history. One call restores records, TTLs, indexes, and counts together and returns an undo token, so an agent's mistake is never permanent.
Atomic Batches & TTL
Up to 100 saves, patches, and deletes in one all-or-nothing batch.
Conditional writes use each record's updatedAt as a concurrency token, and optional TTLs expire records automatically: expired records vanish from reads immediately.
Agent-First Access
Streamable HTTP MCP, a dependency-free TypeScript SDK, and a SKILL.md reference.
Agents can request their own key: they name the owner's email, the owner approves in the console, and the agent receives a key scoped to databases, never to billing or org settings.
JSON In, Any Field Out
A record is a JSON object with a string id. There is no key or schema to design: the first write creates the database and collection, and every field is queryable.
Documents With an Id
Save, get, patch, and delete records by id. Every write returns updatedAt, which doubles as a concurrency token.
Conditional Writes
Pass the updatedAt you read as ifUpdatedAt. If another agent wrote first, you get 409 conflict and can re-read, merge, and retry.
await memories.save({
id: "memory_1",
agentId: "agent_7",
status: "active"
}, { ttl: "2027-01-01T00:00:00Z" })
await memories.patch("memory_1",
{ status: "done" },
{ ifUpdatedAt: m.updatedAt })Query Any Field
Filter on top-level fields or dotted paths with eq, ne, gt, gte, lt, lte, in, beginsWith, and exists. Results are newest first by default.
Indexes Are Optional
Indexes change speed, never results. Add them for the fields you filter or sort on once a collection passes roughly 100,000 records.
await memories.query({
status: "active",
priority: { gte: 2 },
"profile.city": { in: ["Denver", "Austin"] }
}, { orderBy: "priority", order: "desc" })One Store Per Collection
Every collection lives in its own SQLite-backed Durable Object on Cloudflare, bound to your organization. Tenants never share a query path.
Org-Bound Credentials
Every API key resolves to exactly one organization. The org is derived from the credential, never from request data.
Resolved Context
Call GET /whoami to see how the API resolved your key: org, actor, plan, and permissions.
{
"orgId": "org_3kTq...",
"actor": { "type": "agent", "id": "agt_7" },
"plan": "pro",
"permissions": ["db:*"]
}Safe Deletes
Deleting a collection is a soft delete you can undo for 7 days. Deletion protection blocks deletes on production databases.
Undelete
A soft-deleted name stays reserved until it is restored or purged, so nothing is recreated by accident.
DELETE /v1/app/memories // hidden now, purged after 7 days POST /v1/app/memories/undelete // restored
Scoped Keys, Agent Signup
Issue full-access, read/write, or read-only keys per database. Agents can ask for their own key, and only the owner can approve it.
Database-Scoped Keys
Grant db:app:rw or db:app:ro instead of full access. Out-of-scope calls return 403 db_scope_violation.
Key Structure
Keys are mk_live_ plus 32 base62 characters. Only a hash and a display prefix are stored; the raw key is shown once. Revocation applies within 60 seconds.
Authorization: Bearer mk_live_... // permissions ["db:app:rw"] read + write app ["db:app:ro"] read-only app ["*"] owner, every database
Agent Signup
An agent names its owner's email and waits. The owner approves or denies in the console; approved agents get a db:* key that never reaches billing or org settings.
Request Access
With an allowlisted HTTPS callback, the approval is delivered as a signed webhook carrying a one-time claim link instead of the raw key.
POST https://api.monkeyhub.ai/signup/agent
{
"ownerEmail": "human@example.com",
"provider": "claude",
"agentName": "research-runner"
}
// 202 { "pending": { "pendingId": "pnd_..." } }Rewind Anything, Pay Per Op
Point-in-time recovery is built into every collection, with nothing to schedule. Usage is counted per operation, per database, per hour.
30-Day Rewind
Restore a whole collection to any moment in the last 30 days from the console, REST, SDK, or MCP. Rewinds are never metered.
Undo the Undo
Each rewind returns an undo token that puts the collection back exactly as it was before the rewind. The collection is unavailable for a few seconds while it restarts.
const { undo } = await memories.rewind({
to: new Date(Date.now() - 3_600_000)
})
// 202 { status: "rewinding", to, undo }
await memories.rewind({ undo })Simple Metering
Each record read or write counts one op, each query page one op, and each batched operation one op. Database and collection management is free.
Quota Checks
The console shows this month's usage against your plan. Free orgs past their quota receive 402 free_tier_exhausted on metered calls.
GET /console/billing/summary
{
"plan": "free",
"month": "2026-10",
"perProduct": {
"db": { "used": 1420, "limit": 10000 }
}
}