# Enregistrer un profil

> Crée ou met à jour un profil dans Adapty Mail. Un profil contient l'adresse e-mail de l'utilisateur et les attributs
> qu'Adapty Mail utilise pour identifier les destinataires et construire des [segments](/docs/mail-segments).
>
> Identifiez chaque utilisateur par un `external_profile_id` stable. Envoyer le même `external_profile_id`
> à nouveau met à jour le profil existant plutôt que d'en créer un doublon.

## OpenAPI

```yaml
/api-specs/adapty-mail-api.yaml post /api/v1/profile/save/
openapi: 3.1.0
info:
  title: Adapty Mail API
  version: 1.0.0
  description: |
    L'API Adapty Mail vous permet d'envoyer des profils utilisateur et des événements de transaction à Adapty Mail directement
    depuis votre serveur, sans faire transiter les données par le SDK Adapty.

    Utilisez-la pour :

    - Ajouter des abonnés lorsque vous n'avez pas encore de base dans Adapty Mail.
    - Réutiliser la base d'abonnés de vos autres applications.
    - Alimenter Adapty Mail en mode serveur à serveur, avec votre backend comme source de vérité.

    Un profil avec une adresse e-mail suffit pour le flow **never purchased**. Tous les autres flows
    (renewal cancelled, billing issue, expired, refunded) sont pilotés par l'historique d'achats, donc ces
    profils ont également besoin d'événements de transaction pour être placés dans le bon flow.

    Pour un guide étape par étape, consultez [Envoyer des e-mails et des transactions via l'API Adapty Mail](/docs/mail-send-data-via-api).
servers:
  - url: https://api-mail.adapty.io
    description: Serveur de production
paths:
  /api/v1/profile/save/:
    post:
      summary: Enregistrer un profil
      description: |
        Crée ou met à jour un profil dans Adapty Mail. Un profil contient l'adresse e-mail de l'utilisateur et les attributs
        qu'Adapty Mail utilise pour identifier les destinataires et construire des [segments](/docs/mail-segments).

        Identifiez chaque utilisateur par un `external_profile_id` stable. Envoyer le même `external_profile_id`
        à nouveau met à jour le profil existant plutôt que d'en créer un doublon.
      operationId: saveProfile
      security:
        - apikeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ProfileDTO"
            examples:
              basic:
                summary: Profile with an email, ready for the "never purchased" flow
                value:
                  external_profile_id: user_12345
                  external_created_at: "2026-06-01T10:30:00Z"
                  email: jane@example.com
                  country: US
                  custom_attributes:
                    plan: trial
      responses:
        "200":
          description: Profil enregistré avec succès. Le corps de la réponse est un objet vide.
          content:
            application/json:
              schema:
                type: object
              examples:
                default:
                  value: {}
        "400":
          description: Échec de la validation — un champ obligatoire est manquant ou invalide. `field_name` indique quel champ est concerné.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Errors"
              examples:
                default:
                  value:
                    errors:
                      - message: Field required
                        error_code: base_error
                        status_code: 400
                        field_name: email
        "403":
          description: Clé API secrète manquante ou invalide.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Errors"
              examples:
                default:
                  value:
                    errors:
                      - message: Secret key doesn't exist
                        error_code: secret_key_does_not_exist_error
                        status_code: 403
                        field_name: null
components:
  schemas:
    ProfileDTO:
      type: object
      required:
        - external_profile_id
        - external_created_at
        - email
      properties:
        external_profile_id:
          type: string
          description: |
            Identifiant stable pour l'utilisateur, géré par votre application ou votre backend. Réutilisez la même valeur dans toutes les
            requêtes afin qu'Adapty Mail associe les e-mails, les clics et les achats à un seul profil. N'utilisez jamais un identifiant
            anonyme ou propre à une installation.
        external_created_at:
          type: string
          format: date-time
          description: |
            La date de création de l'utilisateur, au format ISO 8601 (par exemple, `"2026-06-01T10:30:00Z"`).
            Vous pouvez utiliser cette date dans les segments.
        email:
          type: string
          format: email
          description: |
            L'adresse e-mail de l'utilisateur. Adapty Mail envoie les campagnes à cette adresse.

            L'adresse est en écriture unique : elle est définie lors de la création du profil et les enregistrements ultérieurs ne
            l'écrasent pas.
        customer_user_id:
          type: string
          description: |
            L'identifiant de l'utilisateur dans votre propre système, si vous en avez un qu'Adapty connaît également. Adapty
            Mail l'utilise pour reconnaître une personne qui l'atteint également via le SDK, afin que les deux
            sources partagent un seul profil au lieu de produire un doublon qui envoie un e-mail à la même personne deux fois.
        first_name:
          type: string
          description: Le prénom de l'utilisateur.
        last_name:
          type: string
          description: Le nom de famille de l'utilisateur.
        gender:
          type: string
          description: Le genre de l'utilisateur.
        birthday:
          type: string
          format: date
          description: La date de naissance de l'utilisateur, au format ISO 8601 (par exemple, `"1990-05-21"`).
        country:
          type: string
          description: Le pays de l'utilisateur sous forme de code ISO 3166-1 alpha-2 à deux lettres en majuscules (par exemple, `US`).
        store_country:
          type: string
          description: La région du store de l'utilisateur sous forme de code ISO 3166-1 alpha-2 à deux lettres en majuscules (par exemple, `US`).
        custom_attributes:
          type: object
          description: |
            Paires clé-valeur arbitraires (valeurs de type chaîne ou nombre) à associer au profil. Utilisez-les pour
            créer des [segments](/docs/mail-segments) — par exemple, `plan`, `signup_source` ou `trial_days`.
        device_info:
          $ref: "#/components/schemas/DeviceInfoDTO"
    Errors:
      type: object
      description: Réponse d'erreur standard. Chaque échec renvoie un statut 4XX avec cette structure.
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              message:
                type: string
                description: Description de l'erreur lisible par un humain.
              error_code:
                type: string
                description: Identifiant d'erreur lisible par une machine.
              status_code:
                type: integer
                description: Code de statut HTTP pour cette erreur.
              field_name:
                type: string
                description: Le champ de la requête à l'origine de l'erreur, ou `null` si l'erreur n'est pas liée à un champ spécifique.
    DeviceInfoDTO:
      type: object
      required:
        - platform
      properties:
        platform:
          type: string
          description: La plateforme sur laquelle se trouve l'utilisateur, par exemple `iOS` ou `Android`.
        device:
          type: string
          description: Modèle de l'appareil, par exemple `iPhone15,2`.
        os:
          type: string
          description: Version du système d'exploitation, par exemple `17.5`.
        locale:
          type: string
          description: La langue et région de l'utilisateur, par exemple `en-US`.
        timezone:
          type: string
          description: Le fuseau horaire de l'utilisateur, par exemple `America/New_York`.
        app_version:
          type: string
          description: Version de votre application utilisée par l'utilisateur, par exemple `3.1.0`.
  securitySchemes:
    apikeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: |
        Authentifiez chaque requête avec votre clé API secrète Adapty Mail, envoyée en tant qu'en-tête **Authorization**
        avec la valeur `Bearer {your_secret_api_key}`, par exemple, `Bearer secret_live_...`.

        Vous trouverez cette clé dans Adapty Mail sous **Settings**. La clé est spécifique au projet — elle identifie le
        projet auquel les données appartiennent, ainsi les endpoints de profil et de transaction ne nécessitent pas d'ID de projet.
```
