# Using your backend from an app

Your backend runs on your device and speaks
[PocketBase](https://pocketbase.io/docs/)'s API (version 0.40): its REST API,
its realtime API and the official SDKs work exactly as PocketBase documents
them, at your backend's public address.

## The address

```
https://<name>.ownbackend.app
```

- The REST API is under `/api/`, e.g. `GET /api/collections/<collection>/records`.
- Requests from any website are allowed (CORS `*`), so your frontend can be
  hosted anywhere.
- Or let the device serve your frontend too: build it into `dist/` next to
  where you run `ownbackend serve` (Vite's default build folder; or pass
  `--publicDir <folder>`). Single-page apps work: unknown paths fall back to
  `index.html`. Until there's an `index.html`, the address shows a short
  "no app here yet" page.

## The JavaScript SDK

```sh
npm install pocketbase
```

```js
import PocketBase from "pocketbase";

const pb = new PocketBase("https://<name>.ownbackend.app");

// Sign a user in (the "users" collection exists from the start).
await pb.collection("users").authWithPassword("ana@example.com", "a-long-password");

// Read and write records.
const list = await pb.collection("bookings").getList(1, 20, { filter: 'day >= "2026-11-01"' });
const booking = await pb.collection("bookings").create({ name: "Ana", day: "2026-11-02 10:00:00" });

// Live updates.
pb.collection("bookings").subscribe("*", (e) => console.log(e.action, e.record));
```

## Data and rules

Collections (tables), their fields and their API rules (who may list, view,
create, update and delete) are the backend's schema. There's no admin
dashboard: an AI agent changes them with ownbackend's
[MCP server](/docs/mcp.md), on the device. Admin access never works through
the public address.

Rules use PocketBase's filter syntax. For example, anyone may create a
booking but only signed-in users may list them:

- Create rule: empty string (everyone)
- List rule: `@request.auth.id != ""`
- Leaving a rule unset (null) means only admins, which through the public
  address means nobody.

## Sign-in

The `users` collection supports email and password, and OAuth2 (Google,
GitHub and others), set in the collection's options through the MCP server
(`update_collection`). For OAuth2, the redirect URL is
`https://<name>.ownbackend.app/api/oauth2-redirect`. Sending emails
to your app's users (verification, password reset, one-time codes) isn't
available yet.

## Answers from ownbackend itself

Some answers come from the relay in front of your device, not from your
backend. They're JSON for API calls (and a short page for browsers):

| Status | `error` | When |
|---|---|---|
| 503 | `host_offline` | The device isn't connected. `note` holds the owner's offline message, if any. Retry later (`Retry-After` header). |
| 502 | `host_error` | The device is connected but didn't answer. |
| 429 | `rate_limited` | Too many requests from one visitor (by default 50 a second, bursts of 100). |
| 413 | `request_too_large` | The request body is over the limit (by default 100 MB). |
| 404 | `app_not_found` | No backend has that name. |

Example:

```json
{"error":"host_offline","app":"bookings","message":"The device running this app isn't connected. Please try again in a little while.","note":"Closed today, back tomorrow at 9."}
```

A frontend should treat `host_offline` as "temporarily unavailable" and show
the `note` when there is one.
