---
url: 'https://dxpr.com/fr/hc/documentation/apprendre-dxpr-builder/reference/points-de-terminaison-d-api'
title: 'Points de terminaison d’API | DXPR'
author:
  name: Jurriaan
  url: 'https://dxpr.com/users/jurriaan'
date: '2026-10-24T14:30:50+00:00'
updated: '2026-10-24T17:19:22+00:00'
copyright: 'Copyright DXPR. All rights reserved.'
type: article
summary: |-
  Cette page répertorie chaque route que DXPR Builder déclare dans dxpr_builder.routing.yml, avec les méthodes HTTP, les conditions d’accès, les paramètres de requête et les formes de réponse tels qu’implémentés dans les contrôleurs. Le JavaScript de l’éditeur est le client prévu pour les points de terminaison AJAX ; rien sur cette page n’est une API publique stable, et les noms de paramètres peuvent changer entre les versions.
  Conditions d’accès
  Les routes utilisent trois sortes de conditions. Une route peut les combiner.
tags:
  - 'Configuration and API'
image: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
published: true
og:
  site_name: DXPR
  updated_time: '2026-10-24T17:19:22+0000'
  'image:alt': 'DXPR, powered by Drupal: AI-powered Drupal for marketers.'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      mainEntity: {  }
    -
      '@type': TechArticle
      headline: 'Points de terminaison d’API'
      description: |-
        Cette page répertorie chaque route que DXPR Builder déclare dans dxpr_builder.routing.yml, avec les méthodes HTTP, les conditions d’accès, les paramètres de requête et les formes de réponse tels qu’implémentés dans les contrôleurs. Le JavaScript de l’éditeur est le client prévu pour les points de terminaison AJAX ; rien sur cette page n’est une API publique stable, et les noms de paramètres peuvent changer entre les versions.
        Conditions d’accès
        Les routes utilisent trois sortes de conditions. Une route peut les combiner.
      image:
        '@type': ImageObject
        url: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
        width: '1200'
        height: '630'
      datePublished: '2026-10-24T14:30:50+0000'
      dateModified: '2026-10-24T17:19:22+0000'
      author:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
        url: 'https://dxpr.com/'
        logo:
          '@type': ImageObject
          url: 'https://dxpr.com/themes/custom/dxpr_com/dxpr-logo-dark.svg'
          width: '1348'
          height: '501'
      mainEntityOfPage: 'https://dxpr.com/fr/hc/documentation/apprendre-dxpr-builder/reference/points-de-terminaison-d-api'
      articleSection: 'Configuration et API'
    -
      '@type': WebPage
      '@id': 'https://dxpr.com/fr/hc/documentation/apprendre-dxpr-builder/reference/points-de-terminaison-d-api'
      description: |-
        Cette page répertorie chaque route que DXPR Builder déclare dans dxpr_builder.routing.yml, avec les méthodes HTTP, les conditions d’accès, les paramètres de requête et les formes de réponse tels qu’implémentés dans les contrôleurs. Le JavaScript de l’éditeur est le client prévu pour les points de terminaison AJAX ; rien sur cette page n’est une API publique stable, et les noms de paramètres peuvent changer entre les versions.
        Conditions d’accès
        Les routes utilisent trois sortes de conditions. Une route peut les combiner.
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: Accueil
            item: 'https://dxpr.com/fr'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
      inLanguage: fr
---
[Centre d’aide](/fr/hc)/[Documentation](/fr/hc/documentation) /[Apprendre DXPR Builder](/fr/hc/documentation/learn-dxpr-builder) /[Référence](/fr/hc/documentation/learn-dxpr-builder/reference) /[Configuration et API](/fr/hc/documentation/learn-dxpr-builder/reference/config-and-api) # Points de terminaison d’API.

 Apprendre DXPR BuilderRéférenceConfiguration et API

   ## Dans ce guide

 Guides associés

- [Référence de configuration](/fr/hc/documentation/apprendre-dxpr-builder/reference/reference-de-configuration)
- [Référence de l’API](/fr/hc/documentation/learn-dxpr-builder/development/api)
- [Référence de l’API des hooks](/fr/hc/documentation/apprendre-dxpr-builder/developpement/api-des-hooks)

Cette page répertorie chaque route que DXPR Builder déclare dans `dxpr_builder.routing.yml`, avec les méthodes HTTP, les conditions d’accès, les paramètres de requête et les formes de réponse tels qu’implémentés dans les contrôleurs. Le JavaScript de l’éditeur est le client prévu pour les points de terminaison AJAX ; rien sur cette page n’est une API publique stable, et les noms de paramètres peuvent changer entre les versions.

## Conditions d’accès

Les routes utilisent trois sortes de conditions. Une route peut les combiner.

| Requirement | Meaning |
|---|---|
| `_permission` | L’utilisateur doit disposer de l’autorisation Drupal nommée. DXPR Builder définit `administer dxpr builder configuration`, `edit with dxpr builder` et `administer dxpr_builder_profile` dans `dxpr_builder.permissions.yml` ; `view media` et `administer site configuration` viennent du cœur. |
| `_csrf_token` | La requête doit porter un jeton CSRF valide dans le paramètre de requête `token`. Pour le gestionnaire AJAX principal, l’éditeur récupère une URL avec le jeton depuis `/dxpr_builder/csrf` (ou depuis l’opération `dxpr_builder_csrf`). Pour les autres routes, le formateur de champ place des URL avec jeton dans `drupalSettings.dxprBuilder`, par exemple `fileUploadUrl`, `entityLinkSuggestionsUrl`, `userSettingsUrl` et `aiAgent.endpointUrl`. |
| `_dxpr_builder_billable_user` | L’utilisateur doit être un utilisateur facturable, comme défini ci-dessous. |

### Ce que « utilisateur facturable » signifie

`DxprBuilderBillableUserAccessCheck` autorise l’accès quand `DxprBuilderLicenseService::isBillableUser()` retourne vrai pour le compte courant. Cette méthode retourne faux pour les comptes bloqués et pour les comptes dont le champ `dxpr_user_is_disavowed` est défini (un administrateur exclut un utilisateur de la modification sur la page User Licenses). Sinon elle retourne vrai pour l’utilisateur 1 et pour tout compte qui détient l’autorisation `edit with dxpr builder`. En bref : un utilisateur facturable est un compte actif, non exclu, autorisé à modifier avec DXPR Builder, et le service de licence compte ces comptes sur votre clé de produit.

### Méthodes HTTP

Quand une route déclare `methods`, seules ces méthodes sont routées. Quand elle n’en déclare pas, la route accepte toute méthode (le `MethodFilter` de Drupal ne filtre que les routes qui déclarent des méthodes). Les tableaux ci-dessous indiquent la méthode que le JavaScript de l’éditeur utilise vraiment quand elle est visible dans le source.

## Points de terminaison AJAX de l’éditeur

### URL de jeton CSRF

|  |  |
|---|---|
| Path | `/dxpr_builder/csrf` |
| Route | `dxpr_builder.csrf_refresh` |
| Methods | Non déclarées (toute méthode). L’éditeur envoie GET (`backend-connect.js`, `fetchCsrfTokenUrl()`). |
| Requirements | Utilisateur facturable |
| Controller | `AjaxController::ajaxRefresh()` |

La requête doit porter l’en-tête `X-Requested-With: XMLHttpRequest` ; sans lui, le contrôleur retourne HTTP 403 avec le corps JSON `{"error": "Invalid request"}`.

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `enterprise` | Chaîne de requête | Facultatif | Quand défini à `true` et que le module `dxpr_builder_e` est installé, le jeton est généré pour la route `dxpr_builder_e.ajax_callback` à la place. Quand défini à `true` sans ce module, le contrôleur lève une exception. |

Réponse : une chaîne JSON avec l’URL du gestionnaire AJAX principal et un paramètre de requête `token`. L’URL est un chemin depuis la racine du site (chemin de base inclus, pas d’hôte). Le JavaScript envoie chaque opération du builder à cette URL.

### Gestionnaire AJAX principal

|  |  |
|---|---|
| Path | `/dxpr_builder/ajax` |
| Route | `dxpr_builder.ajax_callback` |
| Methods | Non déclarées (toute méthode). Le contrôleur lit chaque paramètre depuis le corps POST, et l’éditeur envoie POST. |
| Requirements | Utilisateur facturable, jeton CSRF |
| Controller | `AjaxController::ajaxCallback()` |

Le champ `action` du corps POST choisit l’opération. Chaque opération et ses paramètres sont répertoriés sous [Opérations du gestionnaire AJAX principal](#main-ajax-handler-operations). Quand `action` manque ou est inconnue, le contrôleur retourne un `AjaxResponse` Drupal vide sans commandes. La plupart des opérations qui revérifient le statut d’utilisateur facturable retournent la même réponse vide quand cette vérification échoue ; les tableaux notent les deux exceptions.

### Chat IA

|  |  |
|---|---|
| Path | `/dxpr_builder/ajax/ai/chat` |
| Route | `dxpr_builder.ai_chat` |
| Methods | POST |
| Requirements | `edit with dxpr builder`, utilisateur facturable, jeton CSRF |
| Controller | `AiChatController::chat()` |

Le corps de la requête est du JSON. Le contrôleur transmet la requête au fournisseur `dxpr` du module `ai` de Drupal, pour qu’aucune clé d’API n’atteigne le navigateur. Avant l’appel, il fusionne les domaines du réglage `ai_output_allowed_domains` dans le filtre de noms d’hôte du module `ai`, quand ce service existe. Une valeur de `*` règle le filtre sur confiance totale à la place. Le filtre est restauré ensuite.

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `messages` | Corps JSON | Obligatoire | Tableau d’objets avec `role` et `content`. |
| `stream` | Corps JSON | Facultatif | Booléen, `true` par défaut. |
| `model` | Corps JSON | Facultatif | Par défaut, `kavya-m1`. |
| `prediction` | Corps JSON | Facultatif | Transmis à la configuration du fournisseur comme tableau. |
| `providers` | Corps JSON | Facultatif | Transmis tel quel à la configuration du fournisseur. |
| `allowed_html_tags` | Corps JSON | Facultatif | Transmis tel quel à la configuration du fournisseur. |
| `allowed_html_classes` | Corps JSON | Facultatif | Transmis tel quel à la configuration du fournisseur. |
| `web_search` | Corps JSON | Facultatif | Seule la valeur `false` est transmise ; toute autre valeur est ignorée. |
| `response_format` | Corps JSON | Facultatif | Transmis à la configuration du fournisseur comme tableau. |

Réponses :

| Case | Status | Body |
|---|---|---|
| Diffusé (`stream` vrai et le fournisseur diffuse) | 200, `Content-Type: text/event-stream` | Événements envoyés par le serveur. Chaque événement est `data: <JSON>` où le JSON a `choices[0].delta.content` et, quand le fournisseur les fournit, `id`, `object`, `created`, `model`, `original_model` et `usage`. Le flux se termine par `data: [DONE]`. |
| Non diffusé | 200, `application/json` | `{"choices": [{"message": {"role": "assistant", "content": "<text>"}}]}` |
| Le corps n’est pas du JSON, ou `messages` manque ou est vide | 400, texte brut | `Invalid request: messages required` |
| `model` pas dans la liste `allowed_models` de `ai_provider_dxpr.settings` (vérifié uniquement quand le module `ai_provider_dxpr` est installé et la liste définie) | 403, `application/json` | `{"error": {"code": "model_not_allowed", "message": "The selected model is not allowed. Please refresh the page to update your model options."}}` |
| Exception du fournisseur | 500, `application/json` | `{"error": {"message": "The request could not be completed."}}` |

### Génération d’images IA

|  |  |
|---|---|
| Path | `/dxpr_builder/ajax/ai/image` |
| Route | `dxpr_builder.ai_image` |
| Methods | POST |
| Requirements | `edit with dxpr builder`, utilisateur facturable, jeton CSRF |
| Controller | `AiImageController::generate()` |

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `prompt` | Corps JSON | Obligatoire | Prompt textuel. |
| `model` | Corps JSON | Facultatif | Par défaut, `kavya-image`. |
| `size` | Corps JSON | Facultatif | Transmis à la configuration du fournisseur quand non vide. |
| `quality` | Corps JSON | Facultatif | Transmis à la configuration du fournisseur quand non vide. |
| `background` | Corps JSON | Facultatif | Transmis à la configuration du fournisseur quand non vide. |

Réponses :

| Case | Status | Body |
|---|---|---|
| Succès | 200 | `{"data": [{"b64_json": "<base64 image>"}]}` (seule la première image générée est retournée) |
| Le corps n’est pas du JSON, ou `prompt` manque | 400 | `{"error": {"message": "Invalid request: prompt required"}}` |
| Le fournisseur n’a retourné aucune image | 500 | `{"error": {"message": "No image was generated"}}` |
| Exception du fournisseur | 500 | `{"error": {"message": "Image generation failed. Please try again."}}` |

### Retouche d’images IA

|  |  |
|---|---|
| Path | `/dxpr_builder/ajax/ai/image/edit` |
| Route | `dxpr_builder.ai_image_edit` |
| Methods | POST |
| Requirements | `edit with dxpr builder`, utilisateur facturable, jeton CSRF |
| Controller | `AiImageController::edit()` |

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `prompt` | Corps JSON | Obligatoire | Consigne de retouche. |
| `image` | Corps JSON | Obligatoire | Image source encodée en base64 (décodage strict). |
| `mimeType` | Corps JSON | Facultatif | Par défaut, `image/png` ; le sous-type devient l’extension de fichier transmise au fournisseur. |
| `model` | Corps JSON | Facultatif | Par défaut, `kavya-image`. |
| `size`, `quality`, `background` | Corps JSON | Facultatif | Transmis à la configuration du fournisseur quand non vide. |

Réponses :

| Case | Status | Body |
|---|---|---|
| Succès | 200 | `{"data": [{"b64_json": "<base64 image>"}]}` |
| Le corps n’est pas du JSON, ou `prompt` ou `image` manque | 400 | `{"error": {"message": "Invalid request: prompt and image required"}}` |
| `image` n’est pas du base64 valide | 400 | `{"error": {"message": "Invalid image data: base64 decode failed"}}` |
| Le fournisseur n’a retourné aucune image | 500 | `{"error": {"message": "No image was generated"}}` |
| Exception du fournisseur | 500 | `{"error": {"message": "Image editing failed. Please try again."}}` |

### Téléversement de fichiers

|  |  |
|---|---|
| Path | `/dxpr_builder/ajax/file_upload` |
| Route | `dxpr_builder.ajax_file_upload_callback` |
| Methods | POST, DELETE (déclarées dans le routage ; le contrôleur a un seul gestionnaire de téléversement et aucune branche de suppression séparée) |
| Requirements | Utilisateur facturable, jeton CSRF |
| Controller | `UploadFileController::fileUpload()` |

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `upload` | Fichiers de formulaire multipart, envoyés comme `upload[]` | Obligatoire | Un ou plusieurs fichiers téléversés. |

Le contrôleur trie chaque fichier selon la première partie de son type MIME client vers `<default scheme>://dxpr_builder_images`, `dxpr_builder_videos` ou `dxpr_builder_files`. Une image exige une extension des types MIME `image/gif`, `jpg`, `jpeg`, `png`, `webp`, `avif` ou `svg`. Une vidéo exige un de `video/webm`, `ogv`, `ogg`, `mp4` ou `quicktime` (par exemple `.mov`). La limite de taille est le maximum de téléversement de PHP. Un fichier avec le même nom et un contenu SHA-256 identique à un fichier géré existant que l’utilisateur peut voir est réutilisé plutôt qu’enregistré à nouveau. Quand le module `media` est installé et qu’un type de média nommé `image`, `media_image`, `video` ou `media_video` existe, une entité de média publiée est créée (ou réutilisée) pour le fichier. L’usage du fichier est enregistré sous le module `dxpr_builder`.

Réponses :

| Case | Status | Body |
|---|---|---|
| Succès | 201 | Tableau JSON, un objet par fichier : `url` (URL absolue du fichier), `uuid` et `id` (de l’entité de média quand il y en a une, sinon du fichier), `fid` (ID du fichier), `entity_type` (`media` ou `file`). |
| Aucun fichier `upload` versé | 400 | `{"message": "No files were uploaded."}` |
| Téléversement invalide, destination en écriture impossible ou échec d’enregistrement | 500 | `{"message": "<reason>"}` |
| Échec de validation (extension ou taille) | 422 | `{"message": "<violation messages>"}` |
| Nom de fichier déjà verrouillé par une autre requête | 503 | `{"message": "File \"<name>\" is already locked for writing."}` |

### Boîte de dialogue de la médiathèque

|  |  |
|---|---|
| Path | `/dxpr_builder/media-library` |
| Route | `dxpr_builder.media_library` |
| Methods | Non déclarées (toute méthode). Les paramètres sont lus depuis la chaîne de requête. |
| Requirements | `view media` ; route d’administration |
| Controller | `AjaxController::openImageMediaLibrary()` |

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `media_type` | Chaîne de requête | Facultatif | `image` (par défaut) ou `video`. |
| `remaining_slots` | Chaîne de requête | Facultatif | Nombre d’éléments acceptés par l’ouvreur ; 1 par défaut. |
| `uuid` | Chaîne de requête | Facultatif | Transmis à l’ouvreur comme `opener_parameters.uuid`. |

Le type de média proposé dépend du réglage `media_browser` : `media_library` utilise directement le type de média `image` ou `video` ; `media_library_acquia_dam` utilise `acquia_dam_image_asset` ou `acquia_dam_video_asset` quand ce type de média existe.

Réponses :

| Case | Result |
|---|---|
| Succès | Un tableau de rendu construit par `MediaLibraryUiBuilder::buildUi()` avec l’ouvreur `media_library.opener.dxpr_builder`. Drupal le rend comme page HTML destinée à une iframe. |
| `media_library` (module non installé) | 403, texte brut `Media Library is not enabled. Please enable it to access this feature.` |
| Non pris en charge : `media_type` | 400, texte brut `Unsupported media type "<value>".` |
| `media_browser` (réglage sans type de média utilisable) | 400, texte brut `The "<setting>" settings is not supported.` |

### Validateur de liens d’aide

|  |  |
|---|---|
| Path | `/dxpr_builder/ajax/help_link_validator` |
| Route | `dxpr_builder.ajax_help_link_validator` |
| Methods | Non déclarées (toute méthode). Le script de développement `dxpr_builder_dev.js` envoie POST avec un corps encodé en formulaire. |
| Requirements | Utilisateur facturable |
| Controller | `AjaxController::validateHelpLink()` |

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `help_link` | Corps POST | Obligatoire pour une réponse utile | Seules les URL `http` ou `https` sur l’hôte `dxpr.com` avec un chemin commençant par `/documentation/` sont vérifiées. |

Réponse : un tableau JSON. `[true]` quand une requête HEAD vers le lien (sans suivre les redirections) retourne 200 ; `[false]` quand le client HTTP lève une exception ; `[]` dans tous les autres cas, y compris un paramètre manquant, une URL non correspondante ou un statut non-200.

### Suggestions de liens d’entités

|  |  |
|---|---|
| Path | `/dxpr_builder/entity-link-suggestions` |
| Route | `dxpr_builder.entity_link_suggestions` |
| Methods | GET |
| Requirements | `edit with dxpr builder`, jeton CSRF ; `no_cache` (option de route) |
| Controller | `EntityLinkSuggestionsController::suggestions()` |

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `q` | Chaîne de requête | Obligatoire pour des résultats | Texte de recherche, en minuscules. Une valeur comme `/node/123` charge directement cette entité. |
| `langcode` | Chaîne de requête | Facultatif | Langue de l’entité hôte ; la langue courante par défaut. Seules les entités disponibles dans cette langue sont retournées. |

Les faisceaux sont ceux avec `ckeditor5_link_suggestions` activé dans leurs infos de faisceau ; quand aucun n’est configuré, tous les faisceaux de nœuds sont recherchés. Jusqu’à 100 entités par type d’entité sont comparées avec une recherche `CONTAINS` via les plugins de sélection de références d’entités du cœur.

Réponse : `{"suggestions": [...]}` avec cacheabilité privée et un âge max de 300 secondes. Chaque suggestion a `description`, `entity_type_id`, `entity_uuid`, `group`, `label` et `path`. Quand `q` ne correspond à rien, le tableau contient une seule suggestion de lien manuel avec `description`, `label` (l’entrée en minuscules) et `path` (l’entrée quand c’est une URL valide, sinon une chaîne vide). Quand `q` est vide, `suggestions` est un tableau vide.

### Réglages d’éditeur de l’utilisateur

|  |  |
|---|---|
| Path | `/dxpr_builder/user-settings` |
| Route | `dxpr_builder.user_settings` |
| Methods | POST |
| Requirements | `edit with dxpr builder`, jeton CSRF ; `no_cache` (option de route) |
| Controller | `UserSettingsController::save()` |

L’éditeur envoie cette requête quand un utilisateur modifie ses propres réglages d’éditeur, par exemple sous **Editor settings**. Les valeurs sont stockées avec le compte utilisateur dans `user.data`, module `dxpr_builder`.

| Parameter | Source | Required | Notes |
|---|---|---|---|
| `controls_layout` | Corps JSON | Obligatoire (le seul réglage) | `element`, `breadcrumb` ou `default`. `default` supprime le choix de l’utilisateur, pour que le réglage du profil ou du site s’applique. |

Réponses :

| Case | Status | Body |
|---|---|---|
| Enregistré | 200 | `{"settings": {"controls_layout": "<value>"}}` : chaque réglage après enregistrement, `default` quand l’utilisateur n’a aucun choix enregistré. |
| Le corps n’est pas un objet JSON non vide, ou un nom ou une valeur est invalide | 400 | `{"error": "Invalid setting or value."}`. Rien n’est enregistré. |

## Opérations du gestionnaire AJAX principal

Toutes les opérations vont à `/dxpr_builder/ajax` avec le paramètre de requête de jeton obtenu depuis `/dxpr_builder/csrf`. Le nom de l’opération est envoyé dans le champ `action` du corps POST ; tous les autres paramètres sont des champs du corps POST sauf mention contraire. La colonne « Re-checks billable » marque les opérations qui appellent `isBillableUser()` à nouveau dans l’aiguillage. Quand cette vérification échoue, elles retournent le `AjaxResponse` vide décrit ci-dessus, sauf si la ligne dit le contraire.

### Session et accès

| Operation | Parameters | Re-checks billable | Returns |
|---|---|---|---|
| `dxpr_login` | Aucun | Non | Booléen JSON : si l’utilisateur courant est facturable. |
| `dxpr_builder_csrf` | Aucun | Oui | Chaîne JSON : l’URL du gestionnaire avec un paramètre de requête `token` (comme `/dxpr_builder/csrf` sans l’option `enterprise`). |

### Conteneurs (champs rendus avec le formateur DXPR Builder)

| Operation | Parameters | Re-checks billable | Returns |
|---|---|---|---|
| `dxpr_get_container_types` | Aucun | Oui | Objet JSON indexé `entity_type\|bundle` avec la valeur `entity_type - bundle`, une entrée par faisceau dont l’affichage par défaut utilise le formateur `dxpr_builder_text` sur au moins un champ. |
| `dxpr_get_container_names` | `container_type` (obligatoire, `entity_type\|bundle`) | Oui (retourne une chaîne JSON vide au lieu de la réponse vide) | Objet JSON indexé `entity_id\|field_name` (ou `entity_id\|field_name\|langcode` pour les entités traduisibles) avec la valeur `entity label\|field label`. Quand `container_type` manque, ou que la vérification de facturation échoue, la réponse est une chaîne JSON vide. |
| `dxpr_save_container` | `type` (obligatoire, `entity_type\|bundle`) ; `name` (obligatoire, `entity_id\|field_name` ou `entity_id\|revision_id\|field_name`) ; `htmlContent` (obligatoire, balisage encodé) ; `lang` (facultatif, la langue par défaut du site par défaut) | Oui | Chaîne JSON vide en cas de succès. HTTP 400 avec un message JSON quand `htmlContent` n’est pas une chaîne ou que la langue ne s’applique pas à une entité non traduisible ; 404 quand la traduction demandée n’existe pas ; 500 quand l’entité ne peut pas être chargée. |

`dxpr_save_container` fait ce qui suit :

1. Décode `htmlContent` : OU exclusif de chaque octet avec 7, puis décodage d’URL.
2. Écrit le résultat dans le premier delta du champ nommé.
3. Crée une nouvelle révision par défaut avec le message de journal `Saved with DXPR builder` quand le type d’entité est révisable.
4. Supprime tout verrou de contenu pour l’entité.
5. Met à jour `block_revision_id` dans les sections Layout Builder qui référencent le bloc en ligne enregistré.
6. Incrémente la valeur d’état `dxpr_builder.saves_count`.

L’enregistrement n’a lieu que quand l’utilisateur a l’accès `update` à l’entité. Sans lui, l’opération retourne quand même la réponse de succès en chaîne vide.

### Éléments CMS (blocs et vues)

| Operation | Parameters | Re-checks billable | Returns |
|---|---|---|---|
| `dxpr_builder_get_cms_element_names` | Aucun | Oui | Objet JSON depuis `DxprBuilderService::getCmsElementNames()` avec les clés `list`, `disallowed` et `blockCategories`. |
| `dxpr_get_cms_element_settings` | `name` (obligatoire) : `view-<view_id>-<display_id>` ou `block-<plugin_id>` ; `ajax_page_state[libraries]` (facultatif, bibliothèques déjà chargées séparées par des virgules) | Oui | Objet JSON avec `css`, `js`, `settings` et `data`. Pour une vue, `data` est le rendu des widgets de filtres exposés ; pour un bloc, `data` est le formulaire de configuration du bloc enveloppé dans des balises `<form>`, avec les éléments `provider`, `admin_label`, `label`, `label_display` et `context_mapping` supprimés et tous les éléments details ouverts. |
| `dxpr_builder_load_cms_element` | `name` (obligatoire, analysé par `parseStringForCmsElementInfo()`) ; `settings` (obligatoire) ; `data` (obligatoire, tableau) ; `ajax_page_state[libraries]` (facultatif) | Non | Objet JSON avec `css`, `js`, `settings` et `data`, où `data` est le rendu du bloc ou de l’affichage de vue. |

Dans les deux opérations qui retournent `settings`, `css` et `js` sont les balises d’assets rendues pas encore présentes dans la page, et `settings` est l’objet `drupalSettings` décodé, ou une chaîne vide quand il n’y en a pas.

### Modèles de page

| Operation | Parameters | Re-checks billable | Returns |
|---|---|---|---|
| `dxpr_get_page_templates` | Aucun | Oui | Tableau JSON des modèles de page activés, chacun avec `title`, `uuid`, `module` (toujours `null` : l’entité ne le stocke pas), `category`, `date`, `weight` (entier) et `image` (une URL `data:`, ou l’URL `not-found.png` du module). |
| `dxpr_load_page_template` | `uuid` (obligatoire) | Oui | Réponse HTML contenant le balisage du modèle avec les jetons de base remplacés ; vide quand aucun modèle activé ne correspond. |

### Modèles d’utilisateur

| Operation | Parameters | Re-checks billable | Returns |
|---|---|---|---|
| `dxpr_get_templates` | Aucun | Oui | Tableau JSON des modèles détenus par l’utilisateur courant ou marqués globaux ; les modèles dont le compte auteur n’existe plus sont exclus. Chaque entrée a `id`, `uuid`, `name`, `global`, `current_user_is_author`, `author_id`, `author_name`, `type` et, quand elle est stockée, `image` (une URL `data:`). |
| `dxpr_load_template` | `uuid` (obligatoire) | Oui | Réponse HTML contenant le balisage du modèle avec les jetons de base remplacés ; vide quand aucun modèle activé ne correspond. |
| `dxpr_save_template` | `name` (obligatoire) ; `template` (obligatoire, balisage) ; `type` (facultatif, `custom` par défaut) ; `global` (facultatif, converti en booléen) ; `image` (facultatif : une chaîne base64 ou URL `data:image` dans le corps POST, ou un champ de fichier multipart nommé `image`) | Oui | Objet JSON avec `message` et `code`. `code` 200 en cas de succès ; `code` 409 (statut HTTP 200) quand un modèle avec le même nom machine existe ; `code` 400 avec HTTP 400 quand l’image n’est pas des données d’image valides. |
| `dxpr_delete_template` | `name` (obligatoire) | Oui | Chaîne JSON vide. |

Le nom machine est dérivé de `name` en le mettant en minuscules et en remplaçant chaque suite de caractères hors `a-z0-9_` par un tiret bas. `type` se rabat sur l’attribut `data-azb` dans le balisage quand un modèle enregistré n’a pas de type.

### Images

| Operation | Parameters | Re-checks billable | Returns |
|---|---|---|---|
| `dxpr_builder_get_image_urls` | `entityIDs` (obligatoire, tableau) ; `imageStyle` (obligatoire ; `original` pour le fichier non stylé) ; `entityType` (obligatoire ; `media` résout les éléments de média, toute autre valeur est utilisée comme type d’entité des ID) | Oui | Corps de texte : URL d’images séparées par des virgules. Les fichiers donnent une URL relative à la racine avec un paramètre de requête `fid`. Les éléments de média de type `image` ou `video` se résolvent vers leur fichier source. Les éléments `acquia_dam_image_asset` donnent l’URL DAM avec `mid`, `acquiaDamAsset` et `imageStyle` ajoutés. Les autres éléments de média sont ignorés. HTTP 204 sans corps quand `entityIDs` est vide, ou quand aucun élément de média ne peut être résolu. |
| `dxpr_builder_get_image_style_url` | `imageStyle` (obligatoire) ; `entityId` (obligatoire) ; `entityTypeId` (obligatoire, `file` ou `media`) | Oui | Corps de texte. Pour un fichier : son URL relative à la racine via le style d’image (les fichiers SVG et `original` sautent le style), avec un paramètre de requête `fid`. Pour un élément de média `acquia_dam_image_asset` : l’URL DAM. HTTP 204 sans corps pour toute autre entité, ou quand l’entité est introuvable. |
| `dxpr_builder_get_image_metadata` | `entityId` (obligatoire) ; `entityType` (obligatoire, `file` ou `media`) | Oui (retourne du JSON 403 au lieu de la réponse vide) | `{"data": {"alt": "...", "title": "..."}}` depuis le champ source d’image de l’élément de média (un asset DAM Acquia donne son texte alternatif DAM et un titre vide). Pour un fichier, les valeurs viennent du premier élément de média dont le `field_media_image` le référence. `data` est un tableau vide quand l’entité n’est ni un fichier ni un élément de média, ou quand aucun média ne référence le fichier. Erreurs : 400 `{"error": "Missing required parameters"}`, 404 `{"error": "Entity not found"}`, 500 `{"error": "Failed to load entity"}`, 403 `{"error": "Access denied"}`. |

### Verrous de contenu

| Operation | Parameters | Re-checks billable | Returns |
|---|---|---|---|
| `dxpr_content_lock_status` | `entity_id`, `revision_id`, `entity_type`, `langcode` (tous obligatoires) | Non | Objet JSON avec `status` (booléen) et `label` (libellé de l’entité) ; quand verrouillé, aussi `entity_lock_author_id` et `entity_lock_author_name`. |
| `dxpr_toggle_content_lock` | `entity_id`, `revision_id`, `entity_type`, `langcode`, `toggle_action` (tous obligatoires ; `lock` crée le verrou, toute autre valeur le supprime) | Non | Objet JSON avec `label` et `status` (`true` après verrouillage, `false` après déverrouillage). Un tableau JSON vide (`[]`) quand l’entité ne peut pas être chargée ou que l’utilisateur n’a pas l’accès `update`. |

## Pages d’administration

Toutes ces routes acceptent toute méthode (pas de clé `methods`). Les chemins contenant `{...}` prennent l’ID de l’entité de configuration, ou l’ID de migration pour `{migration_id}`.

| Path | Route | Permission | Purpose |
|---|---|---|---|
| `/admin/dxpr_studio` | `dxpr_builder.admin.studio` | `administer dxpr builder configuration` | Aperçu DXPR Studio ; page de bloc du menu d’administration du cœur répertoriant les pages enfants. |
| `/admin/dxpr_studio/dxpr_builder` | `dxpr_builder.admin.studio.builder` | `administer dxpr builder configuration` | Aperçu DXPR Builder ; page de bloc du menu d’administration du cœur. |
| `/admin/dxpr_studio/dxpr_builder/settings` | `dxpr_builder.settings` | `administer dxpr builder configuration` | `DxprBuilderSettingsForm` : le formulaire des réglages du module. |
| `/admin/dxpr_studio/dxpr_builder/ai_settings` | `dxpr_builder.ai_settings` | `administer dxpr builder configuration` | `DxprBuilderAiSettingsForm` : le formulaire des réglages IA. |
| `/admin/dxpr_studio/dxpr_builder/user_templates` | `entity.dxpr_builder_user_template.collection` | `administer site configuration` | Liste des entités de configuration `dxpr_builder_user_template`. |
| `/admin/dxpr_studio/dxpr_builder/user_templates/add` | `entity.dxpr_builder_user_template.add_form` | `administer site configuration` | Ajouter un modèle d’utilisateur. |
| `/admin/dxpr_studio/dxpr_builder/user_templates/{dxpr_builder_user_template}` | `entity.dxpr_builder_user_template.edit_form` | `administer site configuration` | Modifier un modèle d’utilisateur. |
| `/admin/dxpr_studio/dxpr_builder/user_templates/{dxpr_builder_user_template}/delete` | `entity.dxpr_builder_user_template.delete_form` | `administer site configuration` | Supprimer un modèle d’utilisateur (formulaire de confirmation). |
| `/admin/dxpr_studio/dxpr_builder/page_template` | `entity.dxpr_builder_page_template.collection` | `administer site configuration` | Liste des entités de configuration `dxpr_builder_page_template`. |
| `/admin/dxpr_studio/dxpr_builder/page_template/add` | `entity.dxpr_builder_page_template.add_form` | `administer site configuration` | Ajouter un modèle de page. |
| `/admin/dxpr_studio/dxpr_builder/page_template/create` | `dxpr_builder.create_page_template` | `administer dxpr builder configuration` | `PageController::createPageTemplate()` : copie le modèle d’utilisateur activé identifié par le paramètre de requête `uuid` dans un nouveau modèle de page avec le même ID et la catégorie `DXPR`. Il définit un message de statut ou d’erreur et redirige vers la liste des modèles d’utilisateur. |
| `/admin/dxpr_studio/dxpr_builder/page_template/{dxpr_builder_page_template}` | `entity.dxpr_builder_page_template.edit_form` | `administer site configuration` | Modifier un modèle de page. |
| `/admin/dxpr_studio/dxpr_builder/page_template/{dxpr_builder_page_template}/delete` | `entity.dxpr_builder_page_template.delete_form` | `administer site configuration` | Supprimer un modèle de page (formulaire de confirmation). |
| `/admin/dxpr_studio/dxpr_builder/profile` | `entity.dxpr_builder_profile.collection` | `administer dxpr_builder_profile` | Liste des entités de configuration `dxpr_builder_profile`. |
| `/admin/dxpr_studio/dxpr_builder/profile/add` | `entity.dxpr_builder_profile.add_form` | `administer dxpr_builder_profile` | Ajouter un profil. |
| `/admin/dxpr_studio/dxpr_builder/profile/{dxpr_builder_profile}` | `entity.dxpr_builder_profile.edit_form` | `administer dxpr_builder_profile` | Modifier un profil. |
| `/admin/dxpr_studio/dxpr_builder/profile/{dxpr_builder_profile}/delete` | `entity.dxpr_builder_profile.delete_form` | `administer dxpr_builder_profile` | Supprimer un profil (formulaire de confirmation). |
| `/admin/dxpr_studio/dxpr_builder/user_licenses` | `dxpr_builder.user_licenses` | `administer dxpr builder configuration` | `PageController::userLicensesPage()` : tableau non caché des utilisateurs sous licence (colonnes User, Roles, Sites, Assigned et Operations). Au-dessus, la page affiche sa propre carte de résumé de licence (`dxpr-license-info`) quand les informations de licence sont disponibles, et, pendant qu’une licence libérée purge ses 30 jours, un avis « Next license available on ». Sur cette route, le bloc **License info** ne rend rien, pour que le résumé ne s’affiche jamais deux fois. |
| `/admin/dxpr_studio/dxpr_builder/user_licenses/sites` | `dxpr_builder.user_licenses.sites` | `administer dxpr builder configuration` | `PageController::userLicensesSitesPage()` : liste d’éléments des domaines enregistrés pour l’utilisateur donné dans le paramètre de requête `mail` ; ouverte dans une fenêtre modale depuis le tableau des licences. |
| `/admin/dxpr_studio/dxpr_builder/content` | `dxpr_builder.licensed_content` | `administer dxpr builder configuration` | `PageController::licensedContentPage()` : tableau paginé (20 par page) des éléments de contenu modifiés avec DXPR Builder, avec le résumé de licence des éléments de contenu. Le paramètre de requête `needs_migration=1` ne montre que les éléments qui exigent une migration de contenu. Vide quand aucune information de licence n’est disponible. |
| `/admin/dxpr_studio/dxpr_builder/migration-status` | `dxpr_builder.migration_status` | `administer dxpr builder configuration` | `MigrationStatusController::statusPage()` : tableau non caché des migrations de contenu enregistrées avec leurs éléments en attente. Chaque migration en attente a un lien **Run now**, et un bouton **Run all pending migrations** apparaît quand certaines sont en attente. |
| `/admin/dxpr_studio/dxpr_builder/migration-run/{migration_id}` | `dxpr_builder.migration_run_confirm` | `administer dxpr builder configuration` | `MigrationRunConfirmForm` : confirme, puis exécute une migration comme lot et retourne à la page de statut. |
| `/admin/dxpr_studio/dxpr_builder/migration-run-all` | `dxpr_builder.migration_run_all_confirm` | `administer dxpr builder configuration` | `MigrationRunAllConfirmForm` : confirme, puis exécute chaque migration enregistrée comme un seul lot et retourne à la page de statut. |
| `/dxpr-builder/disavow-user` | `dxpr_builder.disavow_user_confirm` | `administer dxpr builder configuration` | `DisavowUserConfirmForm` : confirme l’exclusion de l’utilisateur donné dans le paramètre de requête `uid` de la modification avec DXPR Builder. |
| `/dxpr-builder/delete-stale-user` | `dxpr_builder.delete_stale_user_confirm` | `administer dxpr builder configuration` | `DeleteStaleUserConfirmForm` : confirme la suppression des données de licence pour l’adresse e-mail donnée dans le paramètre de requête `email`. |

## Et ensuite ?

- [Référence de configuration](/fr/hc/documentation/apprendre-dxpr-builder/reference/reference-de-configuration) pour les réglages qui contrôlent le navigateur de médias et le comportement IA utilisés par ces points de terminaison.
- [Référence de l’API](/fr/hc/documentation/learn-dxpr-builder/development/api) pour les services qu’appellent les contrôleurs.
- [Référence de l’API des hooks](/fr/hc/documentation/apprendre-dxpr-builder/developpement/api-des-hooks) pour les hooks qui laissent les autres modules modifier le comportement du builder.