> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ondb.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# CRUD Overview

> Document operations for OnDB

OnDB uses `client.store()` for all write operations and `client.queryBuilder()` for all read operations.

## Append-Only Storage

OnDB uses an append-only storage model -- updates append new versions instead of modifying existing records, and deletes are soft deletes. See [Immutability](/concepts/immutability) for the full details.

## Available Methods

| Method                           | Description                                                   |
| -------------------------------- | ------------------------------------------------------------- |
| `store()`                        | Store documents (create, update, or delete) with USDC payment |
| `queryBuilder().execute()`       | Query multiple documents with filters                         |
| `queryBuilder().executeUnique()` | Find the latest version of a single document                  |
| `queryBuilder().count()`         | Count matching documents                                      |
| `sql()`                          | Execute SQL queries against collections                       |

## Quick Example

```typescript theme={null}
import { createClient } from '@ondb/sdk';

const client = createClient({
  endpoint: 'https://api.ondb.io',
  appId: 'my-app',
  appKey: 'your-app-key'
});

// Create
const result = await client.store(
  { collection: 'users', data: [{ email: 'alice@example.com', name: 'Alice', active: true }] },
  async (quote) => {
    const txHash = await processPayment(quote);
    return { txHash, network: quote.network, sender: walletAddress, chainType: quote.chainType, paymentMethod: 'native' };
  },
  true
);

// Read (single)
const found = await client.queryBuilder()
  .collection('users')
  .whereField('email').equals('alice@example.com')
  .executeUnique();
console.log('Found:', found?.name);

// Read (many)
const activeUsers = await client.queryBuilder()
  .collection('users')
  .whereField('active').isTrue()
  .orderBy('createdAt', 'DESC')
  .limit(10)
  .execute();

// Update (append new version with same data + changes)
if (found) {
  await client.store(
    { collection: 'users', data: [{ ...found, name: 'Alice Smith' }] },
    paymentCallback,
    true
  );
}

// Soft Delete (append record with deleted flag)
if (found) {
  await client.store(
    { collection: 'users', data: [{ ...found, deleted: true, deletedAt: new Date().toISOString() }] },
    paymentCallback,
    true
  );
}
```

## Payment Proof Structure

All write operations require a payment callback:

```typescript theme={null}
await client.store(
  { collection: 'users', data: [...] },
  async (quote) => {
    // quote contains: totalCost, brokerAddress, tokenSymbol, network, chainType
    const txHash = await processPayment(quote);
    return { txHash, network: quote.network, sender: walletAddress, chainType: quote.chainType, paymentMethod: 'native' };
  },
  true // waitForConfirmation
);
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Create" icon="plus" href="/crud/create">
    Create new documents
  </Card>

  <Card title="Read" icon="book-open" href="/crud/read">
    Find and query documents
  </Card>

  <Card title="Update" icon="pen" href="/crud/update">
    Update existing documents
  </Card>

  <Card title="Delete" icon="trash" href="/crud/delete">
    Soft delete documents
  </Card>
</CardGroup>
