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

# Notes API — create, read, update, delete

> REST endpoints for Spote notes: create, list with bucket and tag filters, get by ID, update with conflict detection, and delete. Embeddings are auto-generated.

The notes endpoints are the core of the Spote API. You can create, read, update, delete, and list notes programmatically. When you create or update a note, Spote automatically generates a semantic embedding so the note is immediately searchable.

## Note object

All endpoints that return a note use this structure:

<ResponseField name="_id" type="string" required>
  UUID string identifying the note. Use this to reference the note in other endpoints.
</ResponseField>

<ResponseField name="title" type="string" required>
  The note title.
</ResponseField>

<ResponseField name="text" type="string" required>
  The note body in Markdown.
</ResponseField>

<ResponseField name="bucket" type="string" required>
  The folder the note belongs to. Defaults to `"Inbox"`.
</ResponseField>

<ResponseField name="tags" type="string[]" required>
  Array of tag strings. Tags do **not** include the `#` prefix.
</ResponseField>

<ResponseField name="attachments" type="object[]">
  File attachments linked to this note.

  <Expandable title="attachment properties">
    <ResponseField name="filename" type="string">
      Original filename of the uploaded file.
    </ResponseField>

    <ResponseField name="url" type="string">
      Internal proxy URL: `/api/files/{userId}/{uuid}.{ext}`. See [Files](/api/files).
    </ResponseField>

    <ResponseField name="mime_type" type="string">
      MIME type of the file, e.g. `"image/png"`.
    </ResponseField>

    <ResponseField name="size_bytes" type="number">
      File size in bytes.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 date string of when the note was created.
</ResponseField>

<ResponseField name="updated_at" type="string" required>
  ISO 8601 date string of when the note was last updated.
</ResponseField>

***

## POST /api/notes

Create a new note. Spote generates a semantic embedding from the title, bucket, tags, and text automatically.

### Request body

<ParamField body="title" type="string" required>
  The note title. Must be at least 1 character.
</ParamField>

<ParamField body="text" type="string" required>
  The note body in Markdown.
</ParamField>

<ParamField body="bucket" type="string" default="Inbox">
  The folder to place the note in. If the bucket does not exist, it is created automatically.
</ParamField>

<ParamField body="tags" type="string[]" required>
  Array of tags without the `#` prefix. Pass an empty array if the note has no tags.
</ParamField>

### Response

**201 Created** — returns the full Note object.

```bash theme={null}
curl -X POST https://your-spote-app.com/api/notes \
  -H "Authorization: Bearer spote_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "How vector search works",
    "text": "Vector search finds semantically similar content by comparing embeddings...",
    "bucket": "Research",
    "tags": ["ai", "search", "embeddings"]
  }'
```

```json theme={null}
{
  "_id": "a3f1e2b4-...",
  "title": "How vector search works",
  "text": "Vector search finds semantically similar content by comparing embeddings...",
  "bucket": "Research",
  "tags": ["ai", "search", "embeddings"],
  "attachments": [],
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}
```

***

## GET /api/notes

List notes for your account. Results are sorted by creation date, newest first. Supports pagination and filtering by bucket or tag.

### Query parameters

<ParamField query="limit" type="number" default="20">
  Maximum number of notes to return.
</ParamField>

<ParamField query="offset" type="number" default="0">
  Number of notes to skip. Use with `limit` for pagination.
</ParamField>

<ParamField query="buckets" type="string[]">
  Filter by bucket name. Pass multiple values to include notes from several buckets: `?buckets=Work&buckets=Research`.
</ParamField>

<ParamField query="tags" type="string[]">
  Filter by tag. Pass multiple values to include notes with any of the specified tags: `?tags=ai&tags=ml`.
</ParamField>

### Response

**200 OK** — returns an array of note list items. Embedding fields (`embedding`, `embedding_text`) are excluded from list responses.

```bash theme={null}
curl "https://your-spote-app.com/api/notes?limit=5&buckets=Research&tags=ai" \
  -H "Authorization: Bearer spote_YOUR_TOKEN"
```

```json theme={null}
[
  {
    "_id": "a3f1e2b4-...",
    "title": "How vector search works",
    "text": "Vector search finds semantically similar content...",
    "bucket": "Research",
    "tags": ["ai", "search", "embeddings"],
    "created_at": "2024-01-15T10:30:00Z"
  }
]
```

***

## GET /api/notes/:id

Retrieve a single note by its ID.

### Path parameters

<ParamField path="id" type="string" required>
  The note UUID.
</ParamField>

### Response

**200 OK** — returns the full Note object including the `version` field.

**404 Not Found** — the note does not exist or belongs to another user.

```bash theme={null}
curl https://your-spote-app.com/api/notes/a3f1e2b4-... \
  -H "Authorization: Bearer spote_YOUR_TOKEN"
```

***

## PUT /api/notes/:id

Update an existing note. All body fields are optional — only the fields you include are updated. If you include a `version`, Spote performs conflict detection.

### Path parameters

<ParamField path="id" type="string" required>
  The note UUID.
</ParamField>

### Request body

<ParamField body="title" type="string">
  Updated title.
</ParamField>

<ParamField body="text" type="string">
  Updated Markdown body. Updating `text` triggers a new embedding to be generated.
</ParamField>

<ParamField body="bucket" type="string">
  Updated bucket name.
</ParamField>

<ParamField body="tags" type="string[]">
  Updated tags array without `#` prefixes.
</ParamField>

<ParamField body="version" type="number">
  The version number you last received for this note. If provided, Spote compares this against the database version. If they differ, a `409` is returned instead of applying the update.
</ParamField>

### Response

**200 OK** — returns the updated Note object with the incremented `version`.

**403 Forbidden** — you have read-only access to this note via a share.

**409 Conflict** — the `version` you sent does not match the current version in the database. The response body contains the current note so you can resolve the conflict.

```bash theme={null}
curl -X PUT https://your-spote-app.com/api/notes/a3f1e2b4-... \
  -H "Authorization: Bearer spote_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "How vector search works (updated)",
    "tags": ["ai", "search", "embeddings", "cosine"],
    "version": 2
  }'
```

***

## DELETE /api/notes/:id

Delete a note and all of its shares permanently.

### Path parameters

<ParamField path="id" type="string" required>
  The note UUID.
</ParamField>

### Response

**204 No Content** — the note and all associated shares have been deleted.

```bash theme={null}
curl -X DELETE https://your-spote-app.com/api/notes/a3f1e2b4-... \
  -H "Authorization: Bearer spote_YOUR_TOKEN"
```
