Closed beta · by invitation

A database with the API already written.

Design your entities in the browser, or hand the job to your AI agent. PLEXXER hosts the database and puts a JSON API on top of it, with validation, relations, aggregations, scoped access tokens, row security for your users, and backups. Your team and the AI agents working with it start from the same documented endpoints.

POST/d/{appKey}/Order/read

{1  "status:eq": "paid",  "placedAt:gte": "2026-09-01T00:00:00Z",  "query": {    "sort": { "placedAt": -1 },    "limit": 2,2    "related": ["customer"],3    "count": true  }}

Response● 200

{  "success": true,  "documents": [    {      "_id": "6a3f09c2e1b74d5a8c0f2b11",      "orderNumber": 10482,      "status": "paid",      "total": 129.5,      "placedAt": "2026-09-28T14:02:11Z",      "customer": {        "_id": "6a3e77b0e1b74d5a8c0f1a02",        "name": "Acme Inc"      }    },    { "orderNumber": 10479, … }  ],  "total": 243}
  1. A filter is a field and an operator in one key. Several keys combine with AND.

  2. The customer of every order comes back in the same response, with no second request.

  3. Ask for the total number of matches when you need it for paging.

01 — AI agents

Built for AI agents as well as for people.

A coding agent does good work when the API explains itself and its credentials say how far it may go. PLEXXER provides both.

An agent's first session with one account token
  1. 1POST/appsapp created
  2. 2POST/apps/{appKey}/schemasentity published
  3. 3POST/apps/{appKey}/tokenstoken minted, shown once
  4. 4GET/d/{appKey}/_metaentities, fields, operators
  5. 5POST/d/{appKey}/Order/createdocument stored
  6. 6POST/apps/{appKey}/lockconfiguration locked
  7. 7POST/apps/{appKey}/unlock403 unlock-requires-session
It describes itself
Every app answers the question an agent starts with: what is here, and what may I do? The introspection endpoints list the entities a token can see, their fields, the operators each field accepts and, if you allow it, a few sample documents.
Read-only unless you say otherwise
The dashboard connects an agent in one click with a token that can read your entities and nothing else, and expires after 30 days. Letting it write or change the schema is a deliberate step you take.
From an empty account to a running app
An account token lets an agent create the app, design its entities and mint the narrower tokens your services will use. Give the token an expiry date and it retires by itself.
A lock only a person can open
Lock an app and its configuration is frozen while its data keeps flowing. An agent can switch the lock on after a deploy. Switching it off takes a signed-in person, whatever the token says.
  • MCP

    Plug into your agent

    Claude Code, Cursor, VS Code and any other MCP client connect with one access token. The agent gets tools for exactly what the token allows, and nothing it may not use is even listed.

  • OpenAPI

    A typed description of each app

    Every app publishes an OpenAPI 3.1 document of its entities, typed field by field and cut to the token that asks. Import it into an agent framework or a client generator.

  • llms.txt

    The reference, ready for a context window

    The complete API reference as plain Markdown, with no sign-in. Point an agent at it and it has the grammar, the endpoints and every error code.

02 — How it works

From an entity to five endpoints.

You describe what you store. The API for it exists the moment you publish, and it changes when your schema does.

  1. 1Design

    Add entities and fields in the schema designer: types, required fields, validators, input filters, indexes and relations between entities.

  2. 2Publish

    Changes stay in a draft until you publish them. Publishing shows what will change and puts the new version live at once, with no migration to write.

  3. 3Call

    Each entity answers on create, read, update, delete and aggregate. Call the JSON API from any language, or download a typed C# or TypeScript client generated from your schema. Writes that belong together go in one batch, across entities, and are applied all or not at all.

OrderPublished, version 7
FieldTypeRules
orderNumbernumberrequired, unique index
statusstringrequired
totalnumbermin 0, 2 decimals
placedAtdaterequired, indexed
notestringtrim, max length 500
customerrelationone Customer
itemsrelationmany OrderItem
  • POST/d/{appKey}/Order/create
  • POST/d/{appKey}/Order/read
  • POST/d/{appKey}/Order/update
  • POST/d/{appKey}/Order/delete
  • POST/d/{appKey}/Order/aggregate

03 — Day after launch

Made for apps that keep changing.

A schema is never finished. Three tools for the day after launch.

A canvas for your relations

See every entity and how they connect. Drag from one entity to another to create a relation, choose one or many, and name the field that points back. Open drafts can be reviewed and published together.

Orderdraft against version 7needs confirmation

  • discountnumber, min 0
  • notemax length 500 to 1000
  • legacyCodestring, removed
editing the draft

Every schema has a history

Edit in a draft while the published version keeps serving. Before publishing you see exactly what changes, and a change that can affect stored data is flagged. Every version is kept, and you can roll back to any of them.

  1. shopcopy →shop-stagingconfiguration and data, at one point in time
  2. shop-stagingreplace →shopbackup taken first; key and tokens unchanged

Staging that matches production

Copy an app, with or without its data, to get a test environment. When a change is ready, replace production from the copy: its key, tokens and address stay the same, and a backup is taken before anything is overwritten.

04 — Query language

One grammar for reading, writing and loading relations.

A filter is plain JSON: the field, a colon, the operator. The same keys select what a read returns, what an update changes and what a delete removes.

Operators of the query language
Compareeqnegtgteltlte
Match a listinnin
Match textlike
Check presenceexists
Combine:and:or
Change:set:unset:inc:push:pull:addtoset
Shape the resultsortlimitoffsetincludeFieldsexcludeFieldscount
  • Relations load up to five levels deep, each with its own filter, sort, limit and field list.
  • A create can carry its children. The whole tree is written in one transaction, or not at all.
  • Aggregations count, sum, average and group without a second query language.
  • An update or delete with an empty filter matches nothing, so a forgotten condition cannot wipe your data.

POST/d/{appKey}/Customer/read

{  "country:in": ["NL", "BE"],  "query": {    "related": [      "address.country",      {        "field": "orders",        "filter": { "status:eq": "paid" },        "sort": { "placedAt": -1 },        "limit": 3      }    ]  }}
Customers in two countries, each with their address, its country and their three most recent paid orders.One request.

05 — Realtime

Changes reach your app as they happen.

Switch realtime on for an entity and your app hears of every row that is added, changed or removed, the moment it is saved. In the browser, on your server, in code an agent writes for you. Only where you want it: entities without the switch work exactly as before.

Taskone connection, many subscriptionsSigned forsub alice · org acme
// hear of every open task, as it is saved{ "type": "subscribe", "id": "tasks", "entity": "Task",  "filter": { "status": "open" } } { "type": "event", "id": "tasks", "kind": "insert",  "document": { "_id": "6a3f…", "title": "Write launch post",                "status": "open", "tenantId": "acme" } }{ "type": "event", "id": "tasks", "kind": "leave",  "document": { "_id": "6a3f…" } }
  • insertWrite launch postacmethe row
  • updateFix checkout bugacmethe row
  • leavePlan the offsiteacme → globexid only
  • deleteMigrate CRMglobexnever sent
Your row security, on every change
A user hears only of rows they may read, removals included. A row that moves out of their view is withdrawn by its id alone; what it became stays hidden. Encrypted fields are never sent.
Access ends at once
Revoke a token or a signing key, or suspend an app, and every connection it holds is closed straight away, not when a token runs out.
A filter, as in a read
Subscribe with the same conditions you write for a read: open orders over a hundred, one customer's tickets, the tasks of a project.
Clients that keep the connection
The generated TypeScript and C# clients subscribe in one call, reconnect on their own, renew a user's token before it expires and tell your code when to reload.

Say it to everyone in the room.

Not everything your app shares is a row. Someone is typing, a cursor moved, an export finished. A broadcast channel carries it to everyone listening, the moment it is sent, over the same connection that brings the changes.

Rules you already write
Who may listen and send follows the same claims as your row security. A room per organisation is one line; a user outside it is refused with one word, and who else is listening is never said.
Browser, server or agent
The generated clients open a channel in one call and pace themselves to the limits the server announces. A server sends with a single request; an agent has a tool for it.
Fair to the room
Every listener receives the payload byte for byte, in order. A sender over its rate is told how long to wait; nobody else is slowed, and a busy room never crowds out the changes your app also listens for.
Nothing stored, by design
A channel keeps no history and reaches those listening now, which is what makes it instant. What must last is a row, and the stream of changes carries it.
chat:acme:generallisten, send, hear
{ "type": "subscribe", "id": "room", "channel": "chat:acme:general" }{ "type": "send", "channel": "chat:acme:general",  "payload": { "event": "typing", "user": "alice" }, "id": "m1", "ack": true } // every listener in the room, as it was sent{ "type": "message", "id": "room", "channel": "chat:acme:general",  "payload": { "event": "typing", "user": "alice" } }{ "type": "sent", "id": "m1" }
Channel policies of chat
"policies": [  { "name": "rooms", "pattern": "chat:{org}:**",    "mode": "permissive", "operations": ["receive", "send"],    "rule": { "org": "$claims.org" } }]
Signed forsub alice · org acme
  • subscribe chat:acme:generalsubscribed
  • send { "event": "typing" }sent

06 — Security

Every token says exactly what it may do.

Access is granted per token and per entity, and always written out in full. There is no admin shorthand to hand out by accident.

storefront-weballowed from 203.0.113.0/24Click a grant to change it
Grants of the token storefront-web, per entity and verb
EntityGrantreadaggregatecreateupdatedelete
Productallowedallowedrefusedrefusedrefused
Orderallowedallowedallowedallowedallowed
Customerrefusedrefusedallowedallowedallowed
Shown once
A token is visible only in the response that creates it and cannot be retrieved afterwards. Revoking one takes effect at once.
Address ranges and expiry
Restrict a token to the networks it should come from and give it an end date.
A database per app
Apps never share storage. What belongs to one app cannot turn up in a query against another.
Two-factor sign-in
The dashboard takes codes from an authenticator app, with a one-time code by e-mail as the fallback.

Your users see only their own rows.

Let the users of your app call PLEXXER directly, from a browser or a phone, with a token your backend signs. Row policies on each entity decide which rows a user may read and change, and the fields that tie a row to its tenant and owner are filled in from the token, never taken from the request. A forgotten filter cannot leak a row, because the caller is not the one adding it.

Keys you hold
PLEXXER generates a key pair and shows the private key once, or you upload a public key of your own. There is no shared secret to keep.
Test as a user before you publish
Type a user's claims in the designer and see exactly which rows they would get, against the draft or the published policies.
Your backend keeps its view
Server tokens are not limited by row policies, so back-office jobs and reports still see everything.
Row policies of Task
"policies": [  { "name": "tenant",  "mode": "restrictive",    "operations": ["read", "create", "update", "delete"],    "rule": { "tenantId": "$claims.org" } },  { "name": "members", "mode": "permissive",    "operations": ["read"], "rule": true },  { "name": "owner",   "mode": "permissive",    "operations": ["update", "delete"],    "rule": { "ownerId": "$claims.sub" } }],"stamp": { "tenantId": "$claims.org", "ownerId": "$claims.sub" }
Signed forsub alice · org acme
  • Write launch postalice · acmeread · change
  • Fix checkout bugbob · acmeread
  • Migrate CRMcarol · globexhidden

Fields only you can read.

Mark a field as encrypted and send your key with the request. PLEXXER encrypts the value before it is stored and decrypts it on the way back, and never keeps the key: not in the database, not in a log. A request without the key gets the rest of the record and is told which fields it did not get.

Not even we can read it
Without your key the stored value is of no use to anyone: to us, to the dashboard, to your app's users, or to whoever gets hold of a backup. Only the services you give the key can read the field.
Switch it on in a live app
Existing values are encrypted in batches while the app keeps serving, and a new key replaces the old one the same way.
Clear about what it costs
An encrypted value cannot be filtered, sorted or indexed. The designer names every index or policy that stands in the way before you switch it on.
Read with the keyyour backend
{ "_id": "66f0…", "name": "Alice",  "ssn": "123-45-6789" }
Read without itanyone else
{ "_id": "66f0…", "name": "Alice",  "_encrypted": ["ssn"] }

07 — Operations

The operational side is included.

The parts a team usually builds in its second year are there on the first day, and they stay the same as an app grows from a prototype to millions of calls a month.

  • Backups

    Back up configuration, data or both, from the dashboard or on your own schedule through the API, and restore any of them when you need to.

  • Indexes in the schema

    Declare unique, compound and expiring indexes next to your fields. They are applied on publish, and you can compare what is live with what is declared.

  • Usage and errors

    Calls per app, per verb and per day, and the most recent errors with their codes, in the dashboard and over the API.

  • Stable error codes

    Every error carries a code that does not change and says what it concerns: the field, the entity or the limit. The full catalogue is one request away.

  • A typed client

    Download a C# or TypeScript client generated from your published schema: typed entities and a project that builds as it is.

  • Fast at any size

    Requests are answered quickly and stay quick as an app grows. Paging, field selection and bulk create keep each call small.

08 — Licences

Four licences, one product.

Every licence includes the whole product. Licences differ in how much you can run, and in one thing: where your data may live.

  • Free

    For trying PLEXXER and for small projects.

    Apps
    2
    API calls per month
    50,000
    Database size per app
    500 MB
    Backups kept per app
    2
    Realtime connections at once
    100
    Realtime messages per month
    1 million
    Realtime events per second
    100
    Database on your own servers
    Not included
    Request access
  • For production

    Standard

    For products in production.

    Apps
    10
    API calls per month
    5 million
    Database size per app
    8 GB
    Backups kept per app
    14
    Realtime connections at once
    1,000
    Realtime messages per month
    10 million
    Realtime events per second
    2,000
    Database on your own servers
    Not included
    Request access
  • Enterprise

    For teams running many apps or heavy traffic.

    Apps
    50
    API calls per month
    25 million
    Database size per app
    100 GB
    Backups kept per app
    60
    Realtime connections at once
    10,000
    Realtime messages per month
    100 million
    Realtime events per second
    20,000
    Database on your own servers
    On request
    Request access
  • Unlimited

    Every limit lifted, by agreement.

    Apps
    No limit
    API calls per month
    No limit
    Database size per app
    No limit
    Backups kept per app
    No limit
    Realtime connections at once
    No limit
    Realtime messages per month
    No limit
    Realtime events per second
    No limit
    Database on your own servers
    On request
    Request access

Included in every licence

  • Schema designer with versions and rollback
  • JSON API: relations, nested writes, aggregations
  • Realtime changes and broadcast channels, under your rules
  • Data browser
  • Dashboard with usage and error logs
  • Scoped access tokens
  • Row security for your users
  • Fields encrypted with a key only you hold
  • Backups and restore
  • Copies and staging environments
  • Generated client and agent access
  • Two-factor sign-in
  • A licence belongs to your account and covers every app in it.
  • You get an e-mail at 80% of your monthly API calls, and again at the limit.
  • Realtime messages are the changes and channel messages delivered to your subscribers. They are counted on their own, never as API calls; a message sent on a channel is one API call.
  • At a limit the API answers 402 plan-limit-reached and names the limit. When a database is full, reading and deleting keep working.

Request access.

PLEXXER is in closed beta and accounts are created by invitation. Tell us what you are building and we will e-mail you an invitation link. You choose your own password when you accept it.

Already have an account? Sign in to the dashboard