---
title: "Adresse postale (privée)"
description: "Adresse postale stockée dans la table user_address (clé primaire = user_id, donc 0 ou 1 adresse par utilisateur). Données strictement privées : aucun endpo…"
---

Adresse postale stockée dans la table `user_address` (clé primaire = `user_id`, donc **0 ou 1** adresse par utilisateur). Données strictement **privées** : aucun endpoint public ni paramétré ne les expose ; seules les 3 routes ci-dessous, toutes derrière l'`AuthenticationMiddleware`, opèrent — et toujours sur l'utilisateur authentifié, jamais sur un id transmis dans l'URL.

Champs exposés aujourd'hui (les colonnes `city_id` et `region` du schéma sont délibérément ignorées en attendant la fonctionnalité d'autocomplétion ville) :

| Attribut       | Type           | Max | Notes |
|----------------|----------------|-----|-------|
| `unitNumber`   | string \| null | 10  | Appartement / étage / lot. |
| `streetNumber` | string \| null | 10  | Numéro de voie. |
| `addressLine1` | string \| null | 150 | Ligne principale (rue, voie). |
| `addressLine2` | string \| null | 150 | Complément (bâtiment, résidence). |
| `postalCode`   | string \| null | 10  | Code postal. |
| `updatedAt`    | string \| null | —   | ISO 8601, `null` tant qu'aucun update n'a eu lieu. |
| `createdAt`    | string \| null | —   | ISO 8601, `null` si l'utilisateur n'a jamais rempli son adresse. |

**Sémantique des mutations** :
- `PATCH` est strictement partiel : un champ absent n'est pas touché.
- Un champ explicitement `null` (ou chaîne vide après trim) **efface** la colonne (= NULL en base).
- `DELETE` retire la ligne entière (retour à "aucune adresse"). Idempotent.

**Validation** : tout-ou-rien. La moindre erreur sur un champ rejette le PATCH complet en `422` (mirror de `PATCH /users/me/settings`).

---

## `GET /api/users/me/address`

- **Auth** : requise (Bearer)
- **Action** : [GetMyAddressAction](../src/Http/Action/Api/Users/GetMyAddressAction.php)
- **Réponse `200 OK`** — forme stable même quand aucune ligne n'existe (tous les champs sont alors `null`) :

```json
{
  "jsonapi": { "version": "1.1" },
  "data": {
    "type": "userAddresses",
    "id":   "<userUuid>",
    "attributes": {
      "unitNumber":   "3A",
      "streetNumber": "12",
      "addressLine1": "rue de Rivoli",
      "addressLine2": null,
      "postalCode":   "75001",
      "updatedAt":    "2026-06-07T12:34:56+00:00",
      "createdAt":    "2026-06-07T10:00:00+00:00"
    }
  }
}
```

---

## `PATCH /api/users/me/address`

Crée la ligne si elle n'existe pas encore (upsert implicite via `ON DUPLICATE KEY UPDATE`).

- **Auth** : requise (Bearer)
- **Action** : [UpdateMyAddressAction](../src/Http/Action/Api/Users/UpdateMyAddressAction.php)
- **Body** (flat ou `data.attributes`) :

```json
{ "addressLine1": "12 rue de Rivoli", "postalCode": "75001" }
```

- **Effacer un champ** : envoyer `null` ou `""` :

```json
{ "addressLine2": null }
```

- **Erreurs `422`** (par champ, avec `meta.code`) :
  - `address.unknownField`         — clé hors whitelist
  - `address.expectedStringOrNull` — valeur non scalaire (number, array, bool…)
  - `address.tooLong`              — dépasse la longueur maxi de la colonne
- **Erreur `400`** : corps non-JSON ou non-objet.
- **Réponse `200 OK`** : snapshot complet post-update + `meta.appliedKeys` (clés camelCase effectivement écrites).

---

## `DELETE /api/users/me/address`

- **Auth** : requise (Bearer)
- **Action** : [DeleteMyAddressAction](../src/Http/Action/Api/Users/DeleteMyAddressAction.php)
- **Idempotent** : `204` même si l'utilisateur n'avait pas d'adresse.
- **Réponse `204 No Content`** (corps vide).

---
