# Contract: Chat Conversations REST API

**Feature**: `004-chat-conversations`  
**Version**: API v1  
**Consumer**: `ChatFront/src/app/core/services/chat-api.service.ts`  
**Producer**: `ChatController` → `ConversationQueryService`, `ChatConversationService`

## Authentication

All endpoints require:

```
Authorization: Bearer {access_token}
```

## Endpoints

### List conversations

| Method | Path |
|--------|------|
| `GET` | `/api/v1/chat/conversations` |

**Response** `200`:

```json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": 12,
        "title": "¿Cuántos clientes tenemos?",
        "updated_at": "2026-05-25T10:30:00+00:00",
        "message_count": 8
      }
    ]
  }
}
```

Ordered by `updated_at` descending (FR-004).

---

### Create conversation

| Method | Path |
|--------|------|
| `POST` | `/api/v1/chat/conversations` |

**Body** (optional):

```json
{
  "title": "Nueva conversación"
}
```

If omitted, server uses default title «Nueva conversación».

**Response** `201`:

```json
{
  "success": true,
  "data": {
    "id": 13,
    "title": "Nueva conversación",
    "updated_at": "2026-05-25T11:00:00+00:00",
    "message_count": 0
  }
}
```

---

### Get messages

| Method | Path |
|--------|------|
| `GET` | `/api/v1/chat/conversations/{conversationId}/messages` |

**Response** `200`:

```json
{
  "success": true,
  "data": {
    "conversation_id": 12,
    "messages": [
      {
        "id": 101,
        "role": "user",
        "content": "Hola",
        "meta": null,
        "created_at": "2026-05-25T10:00:00+00:00"
      },
      {
        "id": 102,
        "role": "assistant",
        "content": "Hola, ¿en qué puedo ayudarte?",
        "meta": null,
        "created_at": "2026-05-25T10:00:05+00:00"
      }
    ]
  }
}
```

---

### Delete conversation

| Method | Path |
|--------|------|
| `DELETE` | `/api/v1/chat/conversations/{conversationId}` |

**Response** `200`:

```json
{
  "success": true,
  "data": { "deleted": true }
}
```

Cascade deletes all messages in the conversation (FR-008).

---

### Send message (sync — attachments)

| Method | Path |
|--------|------|
| `POST` | `/api/v1/chat/conversations/{conversationId}/message` |

**Content-Type**: `multipart/form-data`

| Field | Type | Required |
|-------|------|----------|
| `message` | string | no (required if no attachment) |
| `attachment` | file | no (PDF/JPG) |

**Response** `200`: same shape as baseline `SendConversationResponse` with `conversation_id` echoed:

```json
{
  "success": true,
  "data": {
    "conversation_id": 12,
    "user": { "content": "...", "meta": null },
    "assistant": { "id": 103, "content": "..." }
  }
}
```

---

### Send message (stream — text only)

See [chat-stream-sse.md](./chat-stream-sse.md).

---

## Authorization errors

| Status | When |
|--------|------|
| `401` | Missing/invalid JWT |
| `404` | Conversation not found **or** not owned by user (FR-009) |
| `422` | Validation (empty message, invalid attachment) |

Never return `403` with body revealing foreign conversation existence.

---

## Legacy endpoints (deprecated)

| Method | Path | Behavior |
|--------|------|----------|
| `GET` | `/api/v1/chat/conversation` | Proxy → messages of user's most recently updated conversation |
| `DELETE` | `/api/v1/chat/conversation` | Proxy → delete most recently updated conversation |

Response header (optional): `Deprecation: true`

Frontend MUST migrate to nested routes in v1 of this feature.

---

## TypeScript types (add to `api.types.ts`)

```typescript
export interface ConversationSummary {
  id: number;
  title: string;
  updated_at: string;
  message_count: number;
}

export interface ConversationsListResponse {
  success: boolean;
  data: { items: ConversationSummary[] };
}

export interface ConversationMessagesResponse {
  success: boolean;
  data: {
    conversation_id: number;
    messages: ConversationMessage[];
  };
}

export interface CreateConversationResponse {
  success: boolean;
  data: ConversationSummary;
}
```

---

## FR Traceability

| Requirement | Contract element |
|-------------|------------------|
| FR-001 | `user_id` ownership on server |
| FR-003 | POST `/chat/conversations` |
| FR-004 | GET `/chat/conversations` |
| FR-008 | DELETE `/chat/conversations/{id}` |
| FR-009 | 404 for foreign ids |
| FR-010 | GET messages + client sessionStorage |
| FR-011 | POST message + stream under `{id}` |
| FR-012 | `title` in summary |
