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

# Device Memory API

> REST API reference for device-memory endpoints

<Info>Device memory reuses the existing `memories.create` and `memories.search` endpoints. Pass `snapshot` or `snapshot_ref` instead of `collection_id` -- they are mutually exclusive.</Info>

All endpoints require authentication via the `Authorization: Bearer <token>` header.

## Export Snapshot

Export a collection's full graph state as a portable snapshot.

```
POST /v1/device-memory/snapshot/export
```

| Field           | Type   | Required | Description                                                |
| --------------- | ------ | -------- | ---------------------------------------------------------- |
| `collection_id` | string | Yes      | UUID of the collection to export                           |
| `destination`   | object | No       | Signed URL destination for customer-owned snapshot storage |

<CodeGroup>
  ```python Python theme={null}
  from nebula import Nebula

  client = Nebula(api_key="YOUR_API_KEY")
  snapshot = client.snapshots.export(collection_id="YOUR_COLLECTION_ID").results
  ```

  ```python Python (async) theme={null}
  from nebula import AsyncNebula

  async with AsyncNebula(api_key="YOUR_API_KEY") as client:
      snapshot = (
          await client.snapshots.export(collection_id="YOUR_COLLECTION_ID")
      ).results
  ```

  ```typescript JavaScript theme={null}
  import Nebula from '@nebula-ai/sdk';

  const client = new Nebula({ apiKey: 'YOUR_API_KEY' });
  const { results: snapshot } = await client.snapshots.export({
    collection_id: 'YOUR_COLLECTION_ID',
  });
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.zeroset.com/v1/device-memory/snapshot/export" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{"collection_id": "YOUR_COLLECTION_ID"}'
  ```
</CodeGroup>

To export directly to customer-owned object storage, pass a signed URL destination:

```bash theme={null}
curl -X POST "https://api.zeroset.com/v1/device-memory/snapshot/export" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "collection_id": "YOUR_COLLECTION_ID",
    "destination": {
      "type": "signed_url",
      "collection_id": "YOUR_COLLECTION_ID",
      "put_url": "https://storage.example.com/signed-put-url"
    }
  }'
```

***

## Store Memory

The existing `/v1/memories` endpoint accepts a `snapshot` or `snapshot_ref` field instead of `collection_id`. When a snapshot source is provided, Nebula processes the content statelessly and returns an updated snapshot or writes the updated snapshot to your signed URL.

```
POST /v1/memories
```

| Field          | Type   | Required                         | Description                                                                        |
| -------------- | ------ | -------------------------------- | ---------------------------------------------------------------------------------- |
| `snapshot`     | object | Yes, unless using `snapshot_ref` | Your current snapshot (mutually exclusive with `collection_id` and `snapshot_ref`) |
| `snapshot_ref` | object | Yes, unless using `snapshot`     | Signed URL reference for customer-owned snapshot storage                           |
| `raw_text`     | string | Yes                              | Content to store                                                                   |
| `metadata`     | object | No                               | Arbitrary metadata                                                                 |

Returns `{ "snapshot": <updated_snapshot> }` when using device memory mode.

<CodeGroup>
  ```python Python theme={null}
  result = client.memories.create(
      snapshot=snapshot,
      raw_text="Had a meeting with Alice about the Q2 roadmap",
  ).results

  snapshot = result.snapshot
  ```

  ```python Python (async) theme={null}
  async with AsyncNebula(api_key="YOUR_API_KEY") as client:
      result = (
          await client.memories.create(
              snapshot=snapshot,
              raw_text="Had a meeting with Alice about the Q2 roadmap",
          )
      ).results
      snapshot = result.snapshot
  ```

  ```typescript JavaScript theme={null}
  const { results } = await client.memories.create({
    snapshot,
    raw_text: 'Had a meeting with Alice about the Q2 roadmap',
  });

  snapshot = results.snapshot;
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.zeroset.com/v1/memories" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "snapshot": { "...your snapshot..." },
      "raw_text": "Had a meeting with Alice about the Q2 roadmap"
    }'
  ```
</CodeGroup>

With customer-owned snapshot storage, provide a signed URL reference:

```bash theme={null}
curl -X POST "https://api.zeroset.com/v1/memories" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "snapshot_ref": {
      "type": "signed_url",
      "collection_id": "YOUR_COLLECTION_ID",
      "get_url": "https://storage.example.com/signed-get-url",
      "put_url": "https://storage.example.com/signed-put-url"
    },
    "raw_text": "Had a meeting with Alice about the Q2 roadmap"
  }'
```

***

## Search

The existing `/v1/memories/search` endpoint accepts a `snapshot` or `snapshot_ref` field instead of `collection_ids`. Nebula scores your snapshot statelessly and returns results. Nothing is persisted.

```
POST /v1/memories/search
```

| Field          | Type   | Required                         | Description                                                                      |
| -------------- | ------ | -------------------------------- | -------------------------------------------------------------------------------- |
| `snapshot`     | object | Yes, unless using `snapshot_ref` | Your full snapshot (mutually exclusive with `collection_ids` and `snapshot_ref`) |
| `snapshot_ref` | object | Yes, unless using `snapshot`     | Signed URL reference for customer-owned snapshot storage                         |
| `query`        | string | Yes                              | Natural language search query                                                    |

Returns a graph-shaped `SnapshotSearchResult`: `entities` (each with `id`, `name`, `category`, `description`, `score`) and `relationships` (each with `id`, `subject_id`, `object_id`, `predicate`, `description`, `weight`). This is distinct from the standard `MemoryResponse` returned by collection-based search.

<CodeGroup>
  ```python Python theme={null}
  results = client.memories.search(
      query="What do I know about Alice?",
      snapshot=snapshot,
  ).results

  for entity in results.entities or []:
      print(f"{entity.name} ({entity.category}): {entity.description}")
  for rel in results.relationships or []:
      print(f"{rel.subject_id} -[{rel.predicate}]-> {rel.object_id}")
  ```

  ```python Python (async) theme={null}
  results = (
      await client.memories.search(
          query="What do I know about Alice?",
          snapshot=snapshot,
      )
  ).results
  ```

  ```typescript JavaScript theme={null}
  const { results } = await client.memories.search({
    query: 'What do I know about Alice?',
    snapshot,
  });

  for (const entity of results.entities ?? []) {
    console.log(`${entity.name} (${entity.category}): ${entity.description}`);
  }
  for (const rel of results.relationships ?? []) {
    console.log(`${rel.subject_id} -[${rel.predicate}]-> ${rel.object_id}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.zeroset.com/v1/memories/search" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{
      "snapshot": { "...your snapshot..." },
      "query": "What do I know about Alice?"
    }'
  ```
</CodeGroup>

Search can also load the snapshot through a signed URL:

```bash theme={null}
curl -X POST "https://api.zeroset.com/v1/memories/search" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "snapshot_ref": {
      "type": "signed_url",
      "collection_id": "YOUR_COLLECTION_ID",
      "get_url": "https://storage.example.com/signed-get-url"
    },
    "query": "What do I know about Alice?"
  }'
```

***

## Import Snapshot

Import a snapshot into an ephemeral server-side collection. Useful for debugging or running server-side operations against a client-owned snapshot.

```
POST /v1/device-memory/snapshot/import
```

| Field          | Type   | Required                         | Description                                              |
| -------------- | ------ | -------------------------------- | -------------------------------------------------------- |
| `snapshot`     | object | Yes, unless using `snapshot_ref` | The full snapshot to import                              |
| `snapshot_ref` | object | Yes, unless using `snapshot`     | Signed URL reference for customer-owned snapshot storage |

Returns `{ "ephemeral_collection_id": "<uuid>" }`.

<CodeGroup>
  ```python Python theme={null}
  ephemeral_id = client.snapshots.import_(snapshot=snapshot).results.ephemeral_collection_id
  ```

  ```python Python (async) theme={null}
  ephemeral_id = (
      await client.snapshots.import_(snapshot=snapshot)
  ).results.ephemeral_collection_id
  ```

  ```typescript JavaScript theme={null}
  const { results } = await client.snapshots.import({ snapshot });
  const ephemeralId = results.ephemeral_collection_id;
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.zeroset.com/v1/device-memory/snapshot/import" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -d '{"snapshot": { "...your snapshot..." }}'
  ```
</CodeGroup>

## Customer-Owned Snapshot Objects

Use `snapshot_ref` when snapshots are too large to send inline or when your application stores snapshots in customer-owned object storage.

```json theme={null}
{
  "type": "signed_url",
  "collection_id": "YOUR_COLLECTION_ID",
  "get_url": "https://storage.example.com/signed-get-url",
  "put_url": "https://storage.example.com/signed-put-url",
  "get_headers": {},
  "put_headers": {}
}
```

| Field           | Required   | Description                                            |
| --------------- | ---------- | ------------------------------------------------------ |
| `type`          | No         | Must be `signed_url`; defaults to `signed_url`         |
| `collection_id` | Yes        | Collection UUID Nebula authorizes before using the URL |
| `get_url`       | For reads  | Short-lived signed URL Nebula can GET                  |
| `put_url`       | For writes | Short-lived signed URL Nebula can PUT                  |
| `get_headers`   | No         | Additional headers for the GET request                 |
| `put_headers`   | No         | Additional headers for the PUT request                 |

Signed URLs must use public HTTPS destinations. Nebula rejects private, loopback, and link-local hosts, does not follow redirects, and caps snapshot download size.
