Skip to content
WrongNotebook
ProductsPersonal BaaSDocumentationQuickstart
Sign inCreate workspace
Browse documentation

Start here

  • Quickstart
  • API keys and scopes

Working with data

  • Collections
  • Records
  • Filtering, sorting and paging
  • Schemas and validation
  • Files

Integrate

  • Webhooks
  • Recipes

Reference

  • Errors
  • Limits and rate limits

Start here

  • Quickstart
  • API keys and scopes

Working with data

  • Collections
  • Records
  • Filtering, sorting and paging
  • Schemas and validation
  • Files

Integrate

  • Webhooks
  • Recipes

Reference

  • Errors
  • Limits and rate limits
  1. WrongNotebook
  2. /
  3. Docs
  4. /
  5. Quickstart

Quickstart

Store your first JSON record in about five minutes, with copy-paste examples for curl, JavaScript and Python.

Personal BaaS gives your app a database and an HTTP API without you running a server. You send JSON, it stores JSON, and you read it back with a key.

This page takes about five minutes. By the end you will have saved a record and read it back from the command line and from code.

What you need

  1. An account — create one; it is free to start and takes a minute.
  2. A collection. A collection is one box of similar things: todos, bookmarks, signups. Create one on your dashboard with New collection.
  3. An API key, so your code can talk to the API. Go to Settings → API keys → Create API key, tick records:read and records:create, and copy the key.

The key is shown once. Copy it into your password manager or .env file now. If you lose it, create a new one — you cannot look it up later.

Set up your terminal

Paste these two lines, with your own key:

Terminal
export BAAS_URL="https://www.wrongnotebook.com/v1"
export BAAS_KEY="pb_live_your_key_here"

Now check that the key works:

Terminal
curl -s "$BAAS_URL/me" -H "Authorization: Bearer $BAAS_KEY"

You get back your account, your workspace and what the key is allowed to do:

JSON
{
  "data": {
    "principal": {
      "type": "user",
      "apiKey": { "environment": "live", "scopes": ["records:read", "records:create"] }
    },
    "workspaces": [
      { "id": "ac3385ca-8b0f-489b-8cf4-f76c6c4a4feb", "name": "Personal", "slug": "you-ab12cd" }
    ]
  }
}

Copy the workspace id and keep it handy:

Terminal
export BAAS_WS="ac3385ca-8b0f-489b-8cf4-f76c6c4a4feb"

Save your first record

Replace todos with your collection's slug (the short name under its title on the dashboard).

Terminal
curl -s -X POST "$BAAS_URL/workspaces/$BAAS_WS/collections/todos/records" \
  -H "Authorization: Bearer $BAAS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"data":{"title":"Ship the landing page","done":false}}'

The reply is 201 Created and contains the stored record:

JSON
{
  "data": {
    "id": "01a12621-a7f6-7241-a836-853cd6595895",
    "collectionId": "41a46615-602c-461d-8155-3760b9468a38",
    "data": { "title": "Ship the landing page", "done": false },
    "version": 1,
    "createdAt": "2026-10-10T14:05:02.301Z"
  }
}

Your own fields live under data. Everything beside it — id, version, createdAt — is added by the API, so your JSON can contain a field called id without clashing.

Read it back

Terminal
curl -s "$BAAS_URL/workspaces/$BAAS_WS/collections/todos/records" \
  -H "Authorization: Bearer $BAAS_KEY"
JSON
{
  "data": [{ "id": "01a12621-…", "data": { "title": "Ship the landing page", "done": false } }],
  "pagination": { "nextCursor": null, "hasMore": false }
}

Lists always come back in that shape: your rows in data, and pagination telling you whether there is more. See Filtering and sorting for searching and paging.

From JavaScript

Works in Node, Bun, Deno, a Next.js route handler, or any server-side JavaScript.

JavaScript
const BASE = 'https://www.wrongnotebook.com/v1';
const KEY = process.env.BAAS_KEY;
const WS = process.env.BAAS_WS;

async function baas(path, options = {}) {
  const response = await fetch(`${BASE}${path}`, {
    ...options,
    headers: {
      Authorization: `Bearer ${KEY}`,
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });
  const body = await response.json();
  if (!response.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
  return body;
}

// Save one
await baas(`/workspaces/${WS}/collections/todos/records`, {
  method: 'POST',
  body: JSON.stringify({ data: { title: 'Buy milk', done: false } }),
});

// Read them all
const { data: todos } = await baas(`/workspaces/${WS}/collections/todos/records`);
console.log(todos.map((todo) => todo.data.title));

Keep your key on the server. Anything in browser JavaScript is readable by visitors. Call the API from your backend, a serverless function, or a build script. If you want data readable by anyone, use a public collection instead.

From Python

Python
import os, requests

BASE = "https://www.wrongnotebook.com/v1"
WS = os.environ["BAAS_WS"]
headers = {"Authorization": f"Bearer {os.environ['BAAS_KEY']}"}

requests.post(
    f"{BASE}/workspaces/{WS}/collections/todos/records",
    headers=headers,
    json={"data": {"title": "Water the plants", "done": False}},
).raise_for_status()

todos = requests.get(
    f"{BASE}/workspaces/{WS}/collections/todos/records", headers=headers
).json()["data"]

for todo in todos:
    print(todo["data"]["title"])

Two ways to name a collection

Both of these point at the same place:

AddressWhen to use it
/v1/workspaces/{workspaceId}/collections/{slug}/recordsReadable. Good while building.
/v1/collections/{collectionId}/recordsThe collection's UUID. Never changes, even if you rename the collection.

Renaming a collection changes its slug and breaks slug links. UUID links keep working.

If something goes wrong

You seeWhat it means
401 UNAUTHENTICATEDThe key is missing, mistyped, or the header is not Authorization: Bearer ….
403 INSUFFICIENT_SCOPEThe key exists but lacks a scope. The message names the one it needs.
404 COLLECTION_NOT_FOUNDWrong slug or workspace id — or the key is not allowed to see that collection.

Every error reply has the same shape, with a requestId you can quote:

JSON
{ "error": { "code": "INSUFFICIENT_SCOPE", "message": "…", "requestId": "8ce3d344-…" } }

See Errors for the full list.

Next steps

  • API keys and scopes — who can do what.
  • Records — updating, deleting and restoring.
  • Filtering and sorting — finding the rows you want.
  • Recipes — a contact form, a todo app and a static-site feed, in full.

View this page as Markdown — handy for copying into an editor or an AI assistant.

NextAPI keys and scopes

On this page

  • What you need
  • Set up your terminal
  • Save your first record
  • Read it back
  • From JavaScript
  • From Python
  • Two ways to name a collection
  • If something goes wrong
  • Next steps
WrongNotebook

Personal BaaS is one focused product from WrongNotebook.

Documentation

  • All pages
  • Quickstart
  • Recipes
  • Errors

Product

  • Personal BaaS
  • All products
  • View the demo

Get started

  • Sign in
  • Create workspace

© 2026 WrongNotebook. All rights reserved.