Canonical page: https://docs.singlebase.io/api

# Singlebase API

**A database for agents. A backend for builders.**

Examples use illustrative values and placeholders. Replace IDs, credentials, and configured resource names with your own. Response samples illustrate the envelope, not fixed IDs, totals, or timings.

Singlebase gives your AI agents access to data, knowledge, and context, and gives your application the same foundation to build on. Store records once. Let agents query them by meaning. Let your app create and update them.

## Overview

**One connected foundation:**

| Product | What it does | API |
|---|---|---|
| **DocumentDB** | Flexible JSON documents for app data and agent context | [`data.*`](/data.md) |
| **Full-text search** | Find names, phrases, and keywords in your data | [`data.query` + `search`](/data.md#full-text-search) |
| **VectorDB** | Retrieve records by meaning with similarity search | [Docsets](/chat.md#docsets), [`llm.embed`](/llm.md#embeddings) |
| **Identity** | Sign-up, sign-in, sessions, and user management | [`auth.*`, `user.*`](/auth.md), [`users.*`](/users.md) |
| **Storage** | Files your users upload and content your agents generate | [`files.*`](/files.md) |
| **Intelligence** | Model access, generation, Document to Markdown, embeddings | [`llm.*`](/llm.md) |
| **Conversation** | Chat with Documents: persisted chats with RAG and attachments | [`chat.*`](/chat.md) |
| **Agents** | Give each agent its own access and permissions | [Agent keys](/agents.md) |

**Built for agents and developers:**
- One endpoint and one request shape for every operation
- Per-agent keys scoped to the collections and features you choose
- Structured queries, full-text search, and similarity search over the same data
- Predictable JSON responses and stable error codes that agents can act on
- Templates and helper functions to compute values on write
- Batch up to 10 operations in one request

---

## How It Fits Together

**1. Create your data.** Store the records your app runs on and your agents need as context.

```json
{
  "operation": "data.insert",
  "payload": {
    "collection": "product_catalog",
    "data": {
      "name": "Everyday backpack",
      "description": "A compact bag with a padded laptop sleeve, weather-resistant fabric, and room for your daily essentials.",
      "category": "bags"
    }
  }
}
```

**2. Give your agent access.** Create an [agent key](/agents.md) whose permissions only allow reading `product_catalog`:

```json
{
  "name": "shopping-agent",
  "collections": { "product_catalog": ["read", "search"] },
  "permissions": ["ai.chat"]
}
```

**3. Query by meaning.** Create a `products` [docset](/chat.md#docsets) over `product_catalog` with vector search and `acl: "agent"`. The agent asks in plain language and gets an answer grounded in your records:

```json
{
  "operation": "chat.ask",
  "payload": {
    "message": "Something for a laptop and a daily commute",
    "mode": "kb",
    "retrieval": [{ "source": "docset", "ids": "products" }]
  }
}
```

Your application keeps creating and updating the same `product_catalog` with its own keys and signed-in users.

---

## Quick Start

### 1. Create a project

[Sign up](https://console.singlebase.io) and create a project. In the project settings, copy:
- **API endpoint** - Your project URL, `https://v1.api.singlebase.io/api/<ENDPOINT_KEY>`
- **API key** - Sent in the `X-API-KEY` header on every request

### 2. Make your first request

Every operation is a `POST` to the same endpoint:

```http
POST https://v1.api.singlebase.io/api/<ENDPOINT_KEY>
Content-Type: application/json
X-API-KEY: <API_KEY>
Authorization: Bearer <ID_TOKEN>
```

```json
{
  "operation": "data.query",
  "payload": {
    "collection": "product_catalog",
    "filter": { "category": "bags" },
    "per_page": 20
  }
}
```

`Authorization` is only needed for operations that act as a signed-in user. Get an ID token from [`auth.signin`](/auth.md#auth-signin).

### 3. Call the API from your application

Use the REST helper below from server code. Use a web key plus a signed-in user token for browser requests; server and agent keys stay on your backend.

### 4. A reusable request helper

This helper works with every operation in these docs:

```javascript
const API_URL = 'https://v1.api.singlebase.io/api/<ENDPOINT_KEY>';
const API_KEY = '<API_KEY>';

async function singlebase(operation, payload = {}, idToken) {
  const response = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-KEY': API_KEY,
      ...(idToken ? { Authorization: `Bearer ${idToken}` } : {})
    },
    body: JSON.stringify({ operation, payload })
  });

  const result = await response.json();
  if (!response.ok || result.error) {
    throw new Error(result.error?.message || `HTTP ${response.status}`);
  }
  return result;
}

// Sign in, then read the user's notes
const session = await singlebase('auth.signin', {
  email: 'jane@example.com',
  password: 'ExamplePass123!'
});

const notes = await singlebase('data.query', {
  collection: 'notes',
  per_page: 20
}, session.data.id_token);
```

---

## Request Format

Every request uses the same envelope:

```json
{
  "operation": "data.insert",
  "payload": {
    "collection": "notes",
    "data": { "title": "First note" }
  },
  "options": {}
}
```

| Field | Required | Description |
|---|---|---|
| `operation` | Yes | Operation name, `namespace.action`, such as `data.query` or `auth.signin` |
| `payload` | Yes | Operation parameters. Use `{}` when there are none |
| `options` | No | Request options, such as `_batch_key` in a batch |

Only `operation`, `payload`, and `options` belong at the top level. All parameters go inside `payload`. Most operations ignore unknown payload fields; some stricter payloads, including `files.delete`, reject them. Use only the fields documented for the operation.

### Namespaces

| Namespace | Purpose | Docs |
|---|---|---|
| `data.*` | DocumentDB: store, query, search, and update JSON documents | [Data](/data.md) |
| `auth.*` | Identity: signup, signin, sessions, codes, OAuth | [Authentication](/auth.md) |
| `user.*` | Identity: the signed-in user's own profile | [Authentication](/user.md) |
| `users.*` | Identity: admin user management (server and agent keys) | [Users](/users.md) |
| `files.*` | Storage: uploads, signed URLs, Markdown conversion | [Files](/files.md) |
| `llm.*` | Intelligence: generation and embeddings; deprecated chat aliases | [LLM](/llm.md) |
| `chat.*` | Intelligence: one-off answers, persisted chats, and retrieval | [Conversation](/chat.md) |

---

## API Keys

Each project has several key types. The key prefix decides what the caller can do.

| Key | Prefix | Use it from | Access |
|---|---|---|---|
| Web | `wk_` | Browsers and mobile apps | Public operations; signed-in user operations with a bearer token |
| Server | `sk_` | Your backend | Admin access to the project |
| Agent | `agk_` | AI agents and automations | Admin access, limited to the key's permissions. See [Agents](/agents.md) |

**Rules to know:**
- Web keys require an `Origin` or `Referer` on the project's authorized domain list, over HTTPS. `localhost` and `127.0.0.1` may use HTTP.
- Keep server and agent keys out of browser code.
- When a request includes a bearer token, the API acts as that signed-in user, whatever the key type.
- An invalid, disabled, or unknown key returns `404 PROJECT_NOT_FOUND`.

---

## Access Levels

Each operation has an access level. These pages state it per operation.

| Level | Who can call it |
|---|---|
| Public | Anyone with a valid project key. Project settings and ownership rules still apply |
| User | A signed-in user (bearer token required) |
| Admin | Server or agent keys |

Some public operations still need a user. For example, `data.query` requires a bearer token unless the key is a server or agent key.

---

## Responses

Successful requests return `data`, `meta`, and `exec_time` (seconds). The shape of `data` depends on the operation.

```json
{
  "data": { "count": 3 },
  "meta": {},
  "exec_time": 0.012
}
```

Queries return an array in `data` and pagination in `meta.pagination`. A query with no matches returns an empty array.

### Errors

Errors use the HTTP status code and an `error` object:

```json
{
  "error": {
    "type": "BAD_REQUEST",
    "status": 400,
    "message": "INVALID_PAYLOAD",
    "details": [],
    "trace_id": null
  },
  "meta": {},
  "exec_time": 0.003
}
```

- **message** - A stable error code, such as `INVALID_PAYLOAD` or `FILE_FORBIDDEN`
- **details** - Optional extra information, such as validation errors
- **trace_id** - Include it when you contact support

| Status | Typical cause | What to do |
|---|---|---|
| `400` | Invalid envelope, payload, filter, or selector | Fix the request |
| `401` | Missing session, invalid token, or invalid credentials | Sign in or refresh the session |
| `403` | Access level, project setting, domain, or agent scope | Check keys, permissions, and settings |
| `404` | Unknown operation, project, or resource | Check the endpoint, key, operation, and ID |
| `409` | Conflict with existing data | Resolve the conflict, then retry |
| `413` | Request or file too large | Reduce the size |
| `415` | File type not allowed | Use an allowed type |
| `422` | Invalid attachment, retrieval, or file state | Fix the input or wait for processing |
| `429` | Rate limit exceeded | Retry with exponential backoff and jitter |
| `500`, `502`, `503` | Server, upstream, or maintenance error | Retry later; keep the `trace_id` |

**Limits:**
- The JSON body must be smaller than 10 MB. Upload file bytes directly to storage with the [upload workflow](/files.md#upload-workflow).
- Rate limits depend on your project's plan.

---

## Batch Requests

Run 1 to 10 operations in order with `batch`:

```json
{
  "operation": "batch",
  "payload": {
    "operations": [
      {
        "operation": "data.query",
        "payload": { "collection": "notes", "per_page": 5 },
        "options": { "_batch_key": "notes" }
      },
      {
        "operation": "data.count",
        "payload": { "collection": "notes" },
        "options": { "_batch_key": "total" }
      }
    ]
  }
}
```

**Response:**
```json
{
  "data": [
    { "__batch_key": "notes", "data": [{ "_id": "note_123", "title": "First note" }], "meta": { "pagination": {} }, "message": null },
    { "__batch_key": "total", "data": { "count": 12 }, "meta": {}, "message": null }
  ],
  "meta": { "batch": true },
  "exec_time": 0.031
}
```

**Behavior:**
- Operations run in order and share the request's credentials. A signin inside a batch does not authenticate later items.
- Outer `options` override item `options`.
- Execution stops at the first error. Earlier writes are kept, so a batch is not a transaction.

---

## Check Connectivity

```json
{
  "operation": "ping",
  "payload": {}
}
```

Returns `data: "pong"`. Ping does not validate project credentials.

---

## Next Steps

**Database:**
- [Data](/data.md) - DocumentDB, full-text search, and data operators
- [Query Syntax](/queries.md) - Filters, sorting, pagination, and search
- [Templates](/templates.md) - Expressions and helper functions for computed values

**Identity and Storage:**
- [Authentication](/auth.md) - Sign users in and manage sessions
- [Users](/users.md) - Manage users from your server or agent
- [Files](/files.md) - Store uploads and agent-generated content

**Intelligence and Agents:**
- [LLM](/llm.md) - Model access, generation, and embeddings
- [Conversation](/chat.md) - Chat with Documents, docsets, and attachments
- [Agents](/agents.md) - Give each agent its own access and permissions

**Components:** Add Singlebase to your website with the [Auth UI](https://singlebase.io/components/auth-ui/), [File Uploader](https://singlebase.io/components/file-uploader/), and [Chat Box](https://singlebase.io/components/chat-box/) web components.
