# Mobile API: Workbook Notes Documentation

## Overview

The Mobile API Notes endpoints provide access to store announcements and notes with support for reactions (likes/hearts) and comments. These endpoints use API key authentication suitable for mobile apps.

**Important:** These endpoints are separate from the web API (`/api/:typeNum/workbook/notes/`) which uses session-based authentication. Mobile apps must use the `/api/mobile/notes/` endpoints documented here.

## Base URL

```
/api/mobile/notes
```

## Authentication

All endpoints require an `APIKey` parameter in the POST body.

```
APIKey=your_api_key_here
```

---

## Endpoints

### 1. Get Notes (Paginated Feed)

Retrieves a paginated list of notes for infinite scroll.

```
POST /api/mobile/notes/:typeNum
```

#### POST Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `APIKey` | string | Yes | - | Your API key |
| `limit` | int | No | 10 | Number of notes to return (1-50) |
| `offset` | int | No | 0 | Pagination offset |
| `includeManagerOnly` | string | No | "false" | Include manager-only notes ("true"/"false") |
| `employeeId` | int | No | null | Employee ID for checking reaction status |

#### Example Request

```bash
curl -X POST "https://buyerkiosk.com/api/mobile/notes/pc00" \
  -d "APIKey=your_api_key" \
  -d "limit=10" \
  -d "offset=0" \
  -d "includeManagerOnly=false" \
  -d "employeeId=123"
```

#### Success Response (HTTP 200)

```json
{
  "success": true,
  "data": [
    {
      "id": 42,
      "authorEmployeeId": 35235297,
      "authorFirstName": "Kay",
      "authorLastName": "Oss",
      "authorName": "Kay Oss",
      "title": "Holiday Schedule Reminder",
      "content": "Please submit your holiday availability by Friday.",
      "contentHtml": null,
      "startDate": "2025-11-15",
      "endDate": "2025-12-01",
      "isManagerOnly": false,
      "isPinned": true,
      "reactionCount": 4,
      "commentCount": 2,
      "userHasReacted": false,
      "reactionCounts": {
        "like": 3,
        "heart": 1
      },
      "reactionNames": {
        "like": ["Hellen Hywater", "Holly Wood", "Anonymous"],
        "heart": ["Ryan VanVuren"]
      },
      "createdAt": "2025-11-18 18:49:56",
      "updatedAt": null
    }
  ],
  "hasMore": true,
  "offset": 0,
  "limit": 10
}
```

#### Note Object Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | int | Unique note identifier |
| `authorEmployeeId` | int\|null | Employee ID of note author (null if created by name without match) |
| `authorFirstName` | string\|null | Author's first name (from employee record) |
| `authorLastName` | string\|null | Author's last name (from employee record) |
| `authorName` | string | Full author name (computed from employee or stored directly) |
| `title` | string\|null | Optional note title |
| `content` | string | Plain text content |
| `contentHtml` | string\|null | Rich HTML content |
| `startDate` | string | Start visibility date (Y-m-d) |
| `endDate` | string\|null | End visibility date (null = indefinite) |
| `isManagerOnly` | bool | Restricted to managers |
| `isPinned` | bool | Pinned to top of feed |
| `reactionCount` | int | Total reaction count |
| `commentCount` | int | Total comment count |
| `userHasReacted` | bool | Whether requesting employee has reacted |
| `reactionCounts` | object | Breakdown by reaction type |
| `reactionNames` | object | Names of reactors by type (for tooltips) |
| `createdAt` | string | Creation timestamp |
| `updatedAt` | string\|null | Last update timestamp |

---

### 2. Create Note

Creates a new note/announcement.

```
POST /api/mobile/notes/:typeNum/create
```

#### POST Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `APIKey` | string | Yes | Your API key |
| `authorEmployeeId` | int | Yes | Employee ID creating the note |
| `content` | string | Yes | Plain text content |
| `startDate` | string | Yes | Start date (Y-m-d format) |
| `title` | string | No | Optional title |
| `contentHtml` | string | No | Rich HTML content |
| `endDate` | string | No | End date (null = indefinite) |
| `isManagerOnly` | bool | No | Default: false |
| `isPinned` | bool | No | Default: false |

#### Example Request

```bash
curl -X POST "https://buyerkiosk.com/api/mobile/notes/pc00/create" \
  -d "APIKey=your_api_key" \
  -d "authorEmployeeId=45" \
  -d "title=Team Meeting" \
  -d "content=Weekly team meeting moved to Thursday at 3pm" \
  -d "startDate=2025-12-01" \
  -d "isPinned=true"
```

#### Success Response (HTTP 201)

```json
{
  "success": true,
  "noteId": 56
}
```

#### Error Responses

**Missing Required Fields (HTTP 400)**
```json
{
  "success": false,
  "error": "authorEmployeeId, content, and startDate are required"
}
```

---

### 2b. Create Note by Author Name

Creates a new note using the author's name instead of employee ID. The system will attempt to match the name to an existing employee. If a match is found, the note is linked to that employee. If no match is found, the author name is stored directly.

```
POST /api/mobile/notes/:typeNum/createByName
```

#### POST Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `APIKey` | string | Yes | Your API key |
| `authorName` | string | Yes | Author's full name (e.g., "John Smith") |
| `content` | string | Yes | Plain text content |
| `startDate` | string | Yes | Start date (Y-m-d format) |
| `title` | string | No | Optional title |
| `contentHtml` | string | No | Rich HTML content |
| `endDate` | string | No | End date (null = indefinite) |
| `isManagerOnly` | bool | No | Default: false |
| `isPinned` | bool | No | Default: false |

#### Example Request

```bash
curl -X POST "https://buyerkiosk.com/api/mobile/notes/pc00/createByName" \
  -d "APIKey=your_api_key" \
  -d "authorName=John Smith" \
  -d "title=Team Meeting" \
  -d "content=Weekly team meeting moved to Thursday at 3pm" \
  -d "startDate=2025-12-01" \
  -d "isPinned=true"
```

#### Success Response (HTTP 201)

When the author name matches an employee:
```json
{
  "success": true,
  "noteId": 57,
  "matchedEmployee": true,
  "employeeId": 35194463
}
```

When the author name does not match any employee:
```json
{
  "success": true,
  "noteId": 58,
  "matchedEmployee": false,
  "employeeId": null
}
```

#### Error Responses

**Missing Required Fields (HTTP 400)**
```json
{
  "success": false,
  "error": "authorName, content, and startDate are required"
}
```

#### Name Matching Logic

The system attempts to match the provided name to an employee using:

1. **Exact match**: Full name match (e.g., "Ryan VanVuren" matches employee "Ryan VanVuren")
2. **Fuzzy match**: First name + last initial (e.g., "Ryan V" matches employee "Ryan VanVuren")

If no match is found, the `authorName` is stored directly in the note.

---

### 3. Add Reaction

Adds a reaction (like or heart) to a note.

```
POST /api/mobile/notes/:typeNum/:noteId/react
```

#### POST Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `APIKey` | string | Yes | Your API key |
| `employeeId` | int | No | Employee ID (0 for anonymous) |
| `reactionType` | string | No | `"like"` or `"heart"` (default: `"like"`) |

Note: `reaction` is also accepted as an alias for `reactionType`.

#### Example Request

```bash
curl -X POST "https://buyerkiosk.com/api/mobile/notes/pc00/42/react" \
  -d "APIKey=your_api_key" \
  -d "employeeId=123" \
  -d "reactionType=heart"
```

#### Success Response (HTTP 200)

```json
{
  "success": true,
  "reactionCount": 5
}
```

---

### 4. Remove Reaction

Removes a reaction from a note.

```
POST /api/mobile/notes/:typeNum/:noteId/unreact
```

#### POST Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `APIKey` | string | Yes | Your API key |
| `employeeId` | int | No | Employee ID (0 for anonymous) |

#### Example Request

```bash
curl -X POST "https://buyerkiosk.com/api/mobile/notes/pc00/42/unreact" \
  -d "APIKey=your_api_key" \
  -d "employeeId=123"
```

#### Success Response (HTTP 200)

```json
{
  "success": true,
  "reactionCount": 4
}
```

---

### 5. Add Comment

Adds a comment to a note.

```
POST /api/mobile/notes/:typeNum/:noteId/comment
```

#### POST Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `APIKey` | string | Yes | Your API key |
| `comment` | string | Yes | Comment text (max 2000 characters) |
| `employeeId` | int | No | Employee ID (0 for anonymous) |

#### Example Request

```bash
curl -X POST "https://buyerkiosk.com/api/mobile/notes/pc00/42/comment" \
  -d "APIKey=your_api_key" \
  -d "employeeId=123" \
  -d "comment=Will we need to adjust our shifts?"
```

#### Success Response (HTTP 201)

```json
{
  "success": true,
  "commentId": 15
}
```

#### Error Responses

**Missing Comment (HTTP 400)**
```json
{
  "success": false,
  "error": "comment is required"
}
```

**Comment Too Long (HTTP 400)**
```json
{
  "success": false,
  "error": "Comment exceeds maximum length of 2000 characters"
}
```

---

### 6. Get Comments

Retrieves all comments for a note.

```
POST /api/mobile/notes/:typeNum/:noteId/comments
```

#### POST Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `APIKey` | string | Yes | Your API key |

#### Example Request

```bash
curl -X POST "https://buyerkiosk.com/api/mobile/notes/pc00/42/comments" \
  -d "APIKey=your_api_key"
```

#### Success Response (HTTP 200)

```json
{
  "success": true,
  "data": [
    {
      "id": 15,
      "noteId": 42,
      "employeeId": 123,
      "employeeFirstName": "Jane",
      "employeeLastName": "Doe",
      "comment": "Will we need to adjust our shifts?",
      "createdAt": "2025-12-01 14:30:00"
    }
  ]
}
```

---

## Error Responses

All endpoints may return these common errors:

**Missing API Key (HTTP 400)**
```json
{
  "error": "Missing APIKey parameter"
}
```

**Store Not Found (HTTP 200 with error)**
```json
{
  "success": false,
  "error": "Store not found"
}
```

**Server Error (HTTP 500)**
```json
{
  "error": "An internal error occurred"
}
```

---

## Usage Notes

1. **All endpoints use POST**: Unlike REST conventions, the mobile API uses POST for all operations to allow API key authentication in the request body.

2. **Pagination**: Use `limit` and `offset` for infinite scroll. Check `hasMore` to know if more notes exist.

3. **Manager-Only Notes**: Set `includeManagerOnly=true` only for users with manager permissions.

4. **Anonymous Reactions/Comments**: Pass `employeeId=0` or omit it for anonymous interactions.

5. **Note Visibility**: Notes are only visible between `startDate` and `endDate`. Set `endDate` to `null` for indefinite visibility.

6. **Pinned Notes**: Pinned notes always appear first in the feed, regardless of creation date.

7. **Reaction Types**: Currently supports `"like"` and `"heart"` reaction types.

8. **Reaction Names**: The `reactionNames` field provides names for tooltip display (e.g., "Liked by John, Jane, and 3 others").

---

## Endpoint Summary

| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/mobile/notes/:typeNum` | Get paginated notes |
| POST | `/api/mobile/notes/:typeNum/create` | Create a note (with employee ID) |
| POST | `/api/mobile/notes/:typeNum/createByName` | Create a note (with author name) |
| POST | `/api/mobile/notes/:typeNum/:noteId/react` | Add reaction |
| POST | `/api/mobile/notes/:typeNum/:noteId/unreact` | Remove reaction |
| POST | `/api/mobile/notes/:typeNum/:noteId/comment` | Add comment |
| POST | `/api/mobile/notes/:typeNum/:noteId/comments` | Get comments |
