# API : chat

7 opérations REST du groupe chat.

Base : `/api/v1`. [Conventions](/documentation/api-conventions/) · [Toutes les ressources](/documentation/api-reference/)

- GET /chat/conversations : Mes conversations (messagerie interne)
- POST /chat/conversations : Ouvrir un fil : DM (idempotent) ou GROUPE (T-768, ADR-110)
- GET /chat/conversations/{id}/messages : Le fil, paginé du plus récent
- POST /chat/conversations/{id}/messages : Envoyer un message texte
- POST /chat/conversations/{id}/read : Accusé de lecture du fil (idempotent)
- POST /chat/messages/{id}/reactions : Poser une réaction emoji (idempotent)
- DELETE /chat/messages/{id}/reactions : Retirer une réaction emoji (idempotent, emoji en query)
## GET /chat/conversations

```json
{
  "summary": "Mes conversations (messagerie interne)",
  "description": "Les fils de l'utilisateur, tri dernier message, non-lus par fil + total. Page complète bornée (30, comme le dock web) - pas de curseur V1. Réservé aux sessions utilisateur (§2bis).",
  "tags": [
    "chat"
  ],
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Conversations + total de non-lus",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "dm",
                        "group"
                      ]
                    },
                    "title": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "other": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "name": {
                              "type": "string"
                            },
                            "avatar": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "online": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "avatar",
                            "online"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "participants": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "avatar": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "online": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "avatar",
                          "online"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "lastMessage": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "body": {
                              "type": "string"
                            },
                            "authorId": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            },
                            "createdAt": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "body",
                            "authorId",
                            "createdAt"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "unread": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "id",
                    "kind",
                    "title",
                    "other",
                    "participants",
                    "lastMessage",
                    "unread"
                  ],
                  "additionalProperties": false
                }
              },
              "unreadTotal": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "nextCursor": {
                "type": "null"
              }
            },
            "required": [
              "data",
              "unreadTotal",
              "nextCursor"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```

## POST /chat/conversations

```json
{
  "summary": "Ouvrir un fil : DM (idempotent) ou GROUPE (T-768, ADR-110)",
  "description": "userId (ou userIds à 1) = message direct, idempotent - le fil existant est rendu tel quel. userIds à 2+ = groupe (créateur inclus d'office, titre optionnel) - pas de dédoublonnage entre groupes.",
  "tags": [
    "chat"
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$schema": "https://json-schema.org/draft/2020-12/schema",
          "type": "object",
          "properties": {
            "userId": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "userIds": {
              "minItems": 1,
              "maxItems": 24,
              "type": "array",
              "items": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "title": {
              "type": "string",
              "maxLength": 80
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Le fil (créé ou existant)",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "conversationId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "required": [
              "conversationId"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```

## GET /chat/conversations/{id}/messages

```json
{
  "summary": "Le fil, paginé du plus récent",
  "description": "Pagination par `before` ISO (précédent comments : pas d'updated_at sur les messages). Fil inconnu ou pas à moi = 404. Curseurs de lecture des deux participants inclus.",
  "tags": [
    "chat"
  ],
  "parameters": [
    {
      "name": "before",
      "in": "query",
      "required": false,
      "schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "anyOf": [
          {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          {
            "type": "string",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?:Z))$"
          }
        ]
      }
    },
    {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "integer",
        "minimum": 1,
        "maximum": 50
      }
    }
  ],
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Messages (ordre chronologique) + curseurs",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "authorId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "body": {
                      "type": "string"
                    },
                    "quoted": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "messageId": {
                              "type": "string"
                            },
                            "author": {
                              "type": "string"
                            },
                            "excerpt": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "messageId",
                            "author",
                            "excerpt"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "attachments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "image",
                              "file",
                              "gif",
                              "audio",
                              "video"
                            ]
                          },
                          "path": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "size": {
                            "type": "number"
                          },
                          "mime": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "kind",
                          "name"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "reactions": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        }
                      }
                    },
                    "createdAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "authorId",
                    "body",
                    "quoted",
                    "attachments",
                    "reactions",
                    "createdAt"
                  ],
                  "additionalProperties": false
                }
              },
              "nextBefore": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "myLastReadAt": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "otherLastReadAt": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "items",
              "nextBefore",
              "myLastReadAt",
              "otherLastReadAt"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```

## POST /chat/conversations/{id}/messages

```json
{
  "summary": "Envoyer un message texte",
  "description": "Texte 1-4000 caractères (bornes du composer web).",
  "tags": [
    "chat"
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$schema": "https://json-schema.org/draft/2020-12/schema",
          "type": "object",
          "properties": {
            "body": {
              "type": "string",
              "minLength": 1,
              "maxLength": 4000
            }
          },
          "required": [
            "body"
          ]
        }
      }
    }
  },
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "201": {
      "description": "Message créé",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "messageId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
              }
            },
            "required": [
              "messageId"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```

## POST /chat/conversations/{id}/read

```json
{
  "summary": "Accusé de lecture du fil (idempotent)",
  "tags": [
    "chat"
  ],
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Fil lu",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "read": {
                "type": "boolean",
                "const": true
              }
            },
            "required": [
              "read"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```

## POST /chat/messages/{id}/reactions

```json
{
  "summary": "Poser une réaction emoji (idempotent)",
  "tags": [
    "chat"
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$schema": "https://json-schema.org/draft/2020-12/schema",
          "type": "object",
          "properties": {
            "emoji": {
              "type": "string",
              "minLength": 1,
              "maxLength": 16
            }
          },
          "required": [
            "emoji"
          ]
        }
      }
    }
  },
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Réactions à jour du message",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "reactions": {
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                }
              }
            },
            "required": [
              "reactions"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```

## DELETE /chat/messages/{id}/reactions

```json
{
  "summary": "Retirer une réaction emoji (idempotent, emoji en query)",
  "tags": [
    "chat"
  ],
  "parameters": [
    {
      "name": "emoji",
      "in": "query",
      "required": true,
      "schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "string",
        "minLength": 1,
        "maxLength": 16
      }
    }
  ],
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Réactions à jour du message",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "reactions": {
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                }
              }
            },
            "required": [
              "reactions"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```
