Declare a collection, then save records.
Collections use your own field names. Ensure explicitly, include a schema on the first save, or let a record with an id field create an id-keyed collection.
PUT /v1/app/memories
{
"key": "agentId",
"sort": "memoryId",
"indexes": [
{ "field": "status", "sort": "createdAt" }
]
}PUT /v1/app/memories/agent_7/memory_1
{
"data": {
"agentId": "agent_7",
"memoryId": "memory_1",
"status": "active",
"createdAt": "2026-04-22T12:00:00Z"
},
"ttl": 1798761600
}Use bearer API keys.
Product calls authenticate with Authorization: Bearer mk_live_.... Human and agent keys resolve to an org-scoped request context; storage operations derive the organization from that context rather than request data.
curl https://api.monkeyhub.ai/whoami \ -H "Authorization: Bearer mk_live_..."
Collection keys are stable; indexes are additive.
Key, sort, and index declarations use top-level record fields. Repeating an ensure is safe, and new indexes can be added without changing existing mappings.
Every record is org-scoped.
REST keeps user data in data and server metadata beside it. TTL accepts ISO-8601 or epoch seconds. Save and patch can send ifUpdatedAt to reject stale writes; patch treats null as field deletion. The SDK and MCP flatten the response envelope.
{
"data": {
"agentId": "agent_7",
"memoryId": "memory_1",
"status": "active"
},
"updatedAt": 1776859200000,
"ttl": 1798761600
}Query with your record's field names.
Range operators are eq, lt, lte, gt, gte, between, and beginsWith.
Primary key
Select a key value and optionally narrow its declared sort field.
{ "where": { "agentId": "agent_7", "memoryId": { "beginsWith": "memory_" } } }Newest records
Omit where to read the collection's most recently updated records.
{ "limit": 50 }Declared index
Use the record fields you declared; storage mappings stay private.
{ "where": { "status": "active", "createdAt": { "gte": "2026-04-01" } } }Verified, portable, self-serve backups.
Every active collection is snapshotted nightly, and you can snapshot one collection or an entire database before risky work. Manifests carry the collection schema, record count, compressed byte count, and SHA-256 checksum.
Downloads use 15-minute presigned URLs. Restore verifies bytes, checksum, and record count, creates a new collection from the embedded schema, preserves every original updatedAt, and verifies the written count. Synchronous restore supports up to 50,000 records; larger snapshots use download plus chunked batch import.
const database = monkey.db("app");
const snapshots = await database.snapshot("memories");
const snapshot = snapshots[0];
if (!snapshot) throw new Error("No active collection to snapshot");
const download = await database.downloadBackup("memories", snapshot.snapshot);
const restored = await database.restore({
collection: "memories",
snapshot: snapshot.snapshot,
target: "memories_verified"
});Endpoint reference.
| Method | Path | Purpose | Notes |
|---|---|---|---|
| GET | /v1 | List databases | Returns databases visible to the current key. |
| PUT | /v1/:db | Configure database | Creates or updates environment, description, and deletion protection. |
| DELETE | /v1/:db | Delete database | Cascade soft-deletes active collections; blocked by deletion protection. |
| PUT | /v1/:db/:collection | Ensure collection | Creates a collection or adds indexes idempotently. |
| GET | /v1/:db | List collections | Returns active collection metadata for a database. |
| GET | /v1/:db/:collection | Get collection | Returns schema, status, and recovery metadata. |
| DELETE | /v1/:db/:collection | Delete collection | Soft-deletes a collection for 7-day recovery. |
| POST | /v1/:db/:collection/restore | Restore collection | Restores during the recovery window. |
| PUT | /v1/:db/:collection/:key[/:sort] | Save record | The path must match the schema-named data fields. |
| PATCH | /v1/:db/:collection/:key[/:sort] | Patch record | Updates selected fields; null removes a field; ifUpdatedAt rejects stale writes. |
| GET | /v1/:db/:collection/:key[/:sort] | Get record | Reads by the collection key and optional sort value. |
| DELETE | /v1/:db/:collection/:key[/:sort] | Delete record | Deletes by the same uniform record path. |
| POST | /v1/:db/:collection/query | Query records | Uses declared field names; empty where returns newest first. |
| POST | /v1/:db/:collection/batch | Batch write | Transactional save/delete, max 25 operations. |
| GET | /v1/:db/_backups | List backups | Returns verified manifest entries. |
| GET | /v1/:db/_backups/download | Download backup | Returns a 15-minute presigned gzip JSONL URL. |
| POST | /v1/:db/_backups | Snapshot now | Snapshots one collection or the active database. |
| POST | /v1/:db/_backups/restore | Restore backup | Creates a new collection and preserves updatedAt. |
Use REST, MCP, or the TypeScript SDK.
Agents can connect to https://api.monkeyhub.ai/mcp. Generated SKILL.md and openapi.json are served from the same host, and @monkeyhub/sdk wraps the DB client surface.
import { MonkeyHubClient } from "@monkeyhub/sdk";
const monkey = new MonkeyHubClient({ apiKey });
const database = monkey.db("app");
const memories = database.collection({
name: "memories",
key: ["agentId", "memoryId"],
indexes: [{ field: "status" }]
});
await memories.save({
agentId: "agent_7",
memoryId: "memory_1",
status: "active"
});
const result = await memories.query({
status: "active"
}, { limit: 50 });