RESTHeart
The Open Source Backend for MongoDB.
Open Source · Modern Java · MongoDB-native
Instant REST, GraphQL and WebSocket APIs. No backend code.
Authentication, sign-up, teams and Stripe subscriptions, built in.
AI-native: an MCP server on your data, and vector search.
Extend it in Java, Kotlin, JavaScript or TypeScript.
Fully managed, no installation required โข Or run it yourself โ free and open source
Run RESTHeart with MongoDB:
curl -O https://raw.githubusercontent.com/\
SoftInstigate/restheart/master/docker-compose.yml
docker compose upYour MongoDB, instantly an API:
# create a collection (needs authentication)
curl -X PUT localhost:8080/inventory \
-u admin:secret
# write a document
curl -X POST localhost:8080/inventory \
-u admin:secret \
-H 'Content-Type: application/json' \
-d '{"item":"card", "qty":15}'
# read documents with a filter
curl -g 'localhost:8080/inventory?filter={"qty":{"$gt":10}}' \
-u admin:secretGet Started
MongoDB REST API Tutorial MongoDB GraphQL API Tutorial Framework Tutorial Auth TutorialSetup instructions included in each tutorial
Your Data, Ready for AI Agents
What your app already has, an agent can discover and call, with the permissions your app already enforces. No wrapper, no hand-written tools.
๐ค MCP server
Publish a collection, an aggregation or a stream with one line of metadata. Claude, Cursor or VS Code find it and call it, reading only what their user may read.
๐ Vector search and RAG
Chunk, embed with your provider, search by meaning with $vectorSearch โ or $vectorScan, with no Atlas Search at all.
Building with it? Sophia, the documentation assistant, is the chat button on every page โ or in your editor.
Your App, Running, in Four Commands
Clone a starter, point it at a free RESTHeart Cloud service, run it. Sign-up, login, social sign-in, password reset, teams and invitations already work โ there is no server of yours to write.
These starters run on RESTHeart Cloud, the managed service. rhc is its command line: it configures your cloud service from a file in the repo. For a RESTHeart you run yourself, start from Setup instead.
# 1. get the app
git clone https://github.com/SoftInstigate/restheart-cloud-starter-react.git
cd restheart-cloud-starter-react
npm install
# 2. point it at your free RESTHeart Cloud service: paste its URL from the Connect page
# into src/environments/environment.ts
# 3. configure the cloud service with rhc, the RESTHeart Cloud CLI (accounts, sign-up, your origin)
npm install -g @restheart-cloud/cli
rhc login # paste a personal access token from cloud.restheart.com
rhc setup --srv <srvId> # the six characters at the start of your service URL
# 4. run it
npm run devReact โ sign up, check your inbox, and you are in. README โ
# 1. get the app
git clone https://github.com/SoftInstigate/restheart-cloud-starter-ng.git
cd restheart-cloud-starter-ng
npm install
# 2. point it at your free RESTHeart Cloud service: paste its URL from the Connect page
# into src/environments/environment.dev.ts
# 3. configure the cloud service with rhc, the RESTHeart Cloud CLI (accounts, sign-up, your origin)
npm install -g @restheart-cloud/cli
rhc login # paste a personal access token from cloud.restheart.com
rhc setup --srv <srvId> # the six characters at the start of your service URL
# 4. run it
ng serveAngular โ sign up, check your inbox, and you are in. README โ
# 1. get the app
git clone https://github.com/SoftInstigate/restheart-cloud-starter-ecommerce.git
cd restheart-cloud-starter-ecommerce
npm install
# 2. point it at your free RESTHeart Cloud service: paste its URL from the Connect page
# into src/environments/environment.ts
# and export your Stripe test keys, which the setup stores on the service once
export STRIPE_SECRET_KEY=sk_test_...
export STRIPE_WEBHOOK_SECRET=whsec_...
# 3. configure the cloud service with rhc, the RESTHeart Cloud CLI (accounts, sign-up, your origin)
npm install -g @restheart-cloud/cli
rhc login # paste a personal access token from cloud.restheart.com
rhc setup --srv <srvId> # the six characters at the start of your service URL
# 4. run it
npm run devEcommerce โ sign up, check your inbox, and you are in. README โ
Already have an app? The same pieces are on npm as @restheart-cloud/kit-react, @restheart-cloud/kit-ng and @restheart-cloud/kit-vue.
RESTHeart Features
MongoDB's best friend
RESTHeart unlocks all the features of MongoDB via REST, GraphQL and WebSocket APIs.
Also supports Mongo Atlas, FerretDB, AWS DocumentDB, and Azure Cosmos DB
Declarative Access Control
RESTHeart provides a powerful and battle-tested security layer that keeps your application secure without coding.
User Accounts
The restheart-accounts plugin covers the full user lifecycle: registration, email verification, password reset, team invitations and Google social login โ all configurable, no code.
REST Data API
Read, write and search JSON documents with HTTP requests without coding; specify MongoDB queries and projection options; deal with large result sets with automatic pagination.
GraphQL Data API
The GraphQL plugin works side by side with the REST plugin to get an unified API to build modern applications. GraphQL applications are configured through an API without coding.
WebSocket Data API
The WebSocket API notifies clients of data changes in real time and supports thousands of connected clients. Data streams are configured through an API without coding.
Modern Java Framework
Build microservices in Java 25, Kotlin, JavaScript or TypeScript, powered by virtual threads, with a set of simple yet robust building blocks: Service, Provider, Interceptor, and Initializer.
Stripe Payments
Add subscriptions and one-time purchases to your app with the restheart-stripe module. Multi-tenant ready, no backend code.
Available from RESTHeart 9.8
Container friendly
RESTHeart is available as a Docker image and tailored for the GraalVM to build lightweight native images with instant startup time, low memory footprint.
Data API
Query documents from the command line with httpie.
The GET request has two query parameters:
filter to apply a query and
pagesize to limit the response to one
document.
Here we use the brilliant
httpie, a modern command line HTTP client.
$ http -b GET https://demo.restheart.org/messages'?filter={"from":"Bob"}&pagesize=1'
[
{
"_id": { "$oid": "5c50963e477870eb8258fa68" },
"from": "Bob",
"message": "was here"
}
]Query documents from the command line with cURL.
The GET request has two query parameters:
filter to apply a query (that needs to
be encoded with `-G --data-urlencode` option since it contains the
curly brackets) and pagesize to limit
the response to one document.
Here we use the immortal
cURL!
$ curl -G --data-urlencode 'filter={"from":"Bob"}' \
https://demo.restheart.org/messages?pagesize=1
[
{
"_id": { "$oid": "5c50963e477870eb8258fa68" },
"from": "Bob",
"message": "was here"
}
]Query documents with JavaScript.
The GET request has two query parameters:
filter to apply a query and
pagesize to limit the response to one
document.
Here we use the
fetch API.
const url = encodeURI('https://demo.restheart.org/messages?filter={"from":"Bob"}&pagesize=1');
fetch(url)
.then(response => response.json())
.then(json => JSON.stringify(json, null, 2))
.then(docs => console.log(docs));Query documents with Java.
The GET request has two query parameters:
filter to apply a query and
pagesize to limit the response to one
document.
Here we use the
unirest
java http library.
public void printOutMessages() throws UnirestException {
var resp = Unirest.get("https://demo.restheart.org/messages")
.queryString("filter", "{'from':'Bob'}")
.queryString("pagesize", "1")
.asJson();
// print out each message
resp.getBody().getArray().forEach(msg ->
System.out.println(msg.toString())
);
}Query documents with Python.
The GET request has two query parameters:
filter to apply a query and
pagesize to limit the response to one
document.
This example uses the popular
requests
library.
import requests
import json
url = "https://demo.restheart.org/messages"
params = {
"filter": '{"from":"Bob"}',
"pagesize": "1"
}
response = requests.get(url, params=params)
data = response.json()
print(json.dumps(data, indent=2))Query documents with Swift.
The GET request has two query parameters:
filter to apply a query and
pagesize to limit the response to one
document.
This example uses modern Swift with async/await (Swift 5.5+).
import Foundation
func fetchMessages() async throws {
var components = URLComponents(string: "https://demo.restheart.org/messages")
components?.queryItems = [
URLQueryItem(name: "pagesize", value: "1"),
URLQueryItem(name: "filter", value: "{\"from\":\"Bob\"}")
]
guard let url = components?.url else {
throw URLError(.badURL)
}
let (data, _) = try await URLSession.shared.data(from: url)
let json = try JSONSerialization.jsonObject(with: data)
print(json)
}
// Usage
Task {
try await fetchMessages()
}Polyglot Framework
Implement web services in minutes.
Implement a simple interface and deploy the web service by copying its jar file into the plugins directory.
See it on GitHub More examples@RegisterPlugin(name="greetings", description="just another Hello World")
public class GreeterService implements JsonService {
@Override
public void handle(JsonRequest req, JsonResponse res) {
switch(req.getMethod()) {
case GET ->
res.setContent(object().put("message", "Hello World!"));
case OPTIONS ->
handleOptions(req);
default ->
res.setStatusCode(HttpStatus.SC_METHOD_NOT_ALLOWED);
}
}
}Implement plugins in Kotlin.
You can use Java and Kotlin to implement plugins.
Kotlin Service example@RegisterPlugin(name="kotlinGreeterService", description="just another Hello World")
class GreeterService : JsonService {
override fun handle(req: JsonRequest, res: JsonResponse) {
when(req.method) {
METHOD.GET ->
res.content = obj().put("msg", "Hello World").get()
METHOD.OPTIONS ->
handleOptions(req)
else ->
res.setStatusCode(HttpStatus.SC_METHOD_NOT_ALLOWED)
}
}
}Snoop and modify requests at different stages of their lifecycle.
This interceptor applies to requests of the hello web service
adding a timestamp to the response content.
Interceptor can be executed at different points of the request as
defined by the interceptPoint parameter of the annotation
RegisterPlugin
@RegisterPlugin(
name = "helloInterceptor",
description = "add a timestamp to the response of /greetings",
interceptPoint = InterceptPoint.RESPONSE)
public class HelloInterceptor implements JsonInterceptor {
@Override
public void handle(JsonRequest req, JsonResponse res) {
res.getContent()
.getAsJsonObject()
.addProperty("timestamp", Instant.now().toString());
}
@Override
public boolean resolve(JsonRequest req, JsonResponse res) {
return req.isHandledBy("greetings");
}
}Implement plugins in JavaScript.
This is yet another Hello World web service.
Running RESTHeart on the GraalVM allows you to deploy JavaScript
Services and Interceptors.
export const options = {
name: "helloWorldService",
description: "just another Hello World",
uri: "/hello"
}
export function handle(req, res) {
res.setContent(JSON.stringify({ msg: 'Hello World' }));
res.setContentTypeAsJson();
}