---
url: 'https://dxpr.com/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%BD%D0%B8%D0%BA/api-%D0%BA%D1%96%D0%BD%D1%86%D0%B5%D0%B2%D1%96-%D1%82%D0%BE%D1%87%D0%BA%D0%B8'
title: 'Довідник: кінцеві точки API | DXPR'
author:
  name: Jurriaan
  url: 'https://dxpr.com/users/jurriaan'
date: '2026-10-24T19:26:57+00:00'
updated: '2026-10-24T20:03:43+00:00'
copyright: 'Copyright DXPR. All rights reserved.'
type: article
summary: |-
  Ця сторінка перелічує кожен маршрут, який DXPR Builder реєструє у
  dxpr_builder.routing.yml, з HTTP-методами, вимогами
  доступу, параметрами запитів і формами відповідей, як
  реалізовано в контролерах. JavaScript редактора це
  призначений клієнт для кінцевих точок AJAX; ніщо на цій сторінці не є
  стабільним публічним API, і імена параметрів можуть змінюватися між
  релізами.
  Вимоги доступу
  Маршрути використовують три види вимог. Маршрут може поєднувати їх.
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-24T20:03:43+0000'
  'image:alt': 'DXPR, powered by Drupal: AI-powered Drupal for marketers.'
schema:
  '@context': 'https://schema.org'
  '@graph':
    -
      mainEntity: {  }
    -
      '@type': TechArticle
      headline: 'Довідник: кінцеві точки API'
      description: |-
        Ця сторінка перелічує кожен маршрут, який DXPR Builder реєструє у
        dxpr_builder.routing.yml, з HTTP-методами, вимогами
        доступу, параметрами запитів і формами відповідей, як
        реалізовано в контролерах. JavaScript редактора це
        призначений клієнт для кінцевих точок AJAX; ніщо на цій сторінці не є
        стабільним публічним API, і імена параметрів можуть змінюватися між
        релізами.
        Вимоги доступу
        Маршрути використовують три види вимог. Маршрут може поєднувати їх.
      image:
        '@type': ImageObject
        url: 'https://dxpr.com/themes/custom/dxpr_com/images/dxpr-share-card.jpg'
        width: '1200'
        height: '630'
      datePublished: '2026-10-24T19:26:57+0000'
      dateModified: '2026-10-24T20:03:43+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/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%BD%D0%B8%D0%BA/api-%D0%BA%D1%96%D0%BD%D1%86%D0%B5%D0%B2%D1%96-%D1%82%D0%BE%D1%87%D0%BA%D0%B8'
      articleSection: 'Конфігурація та API'
    -
      '@type': WebPage
      '@id': 'https://dxpr.com/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%BD%D0%B8%D0%BA/api-%D0%BA%D1%96%D0%BD%D1%86%D0%B5%D0%B2%D1%96-%D1%82%D0%BE%D1%87%D0%BA%D0%B8'
      description: |-
        Ця сторінка перелічує кожен маршрут, який DXPR Builder реєструє у
        dxpr_builder.routing.yml, з HTTP-методами, вимогами
        доступу, параметрами запитів і формами відповідей, як
        реалізовано в контролерах. JavaScript редактора це
        призначений клієнт для кінцевих точок AJAX; ніщо на цій сторінці не є
        стабільним публічним API, і імена параметрів можуть змінюватися між
        релізами.
        Вимоги доступу
        Маршрути використовують три види вимог. Маршрут може поєднувати їх.
      breadcrumb:
        '@type': BreadcrumbList
        itemListElement:
          -
            '@type': ListItem
            position: 1
            name: Home
            item: 'https://dxpr.com/uk'
      publisher:
        '@type': Organization
        '@id': 'https://dxpr.com/#organization'
        name: DXPR
      inLanguage: uk
---
[Help Center](/uk/hc)/[Documentation](/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F) /[Вивчення DXPR Builder](/uk/hc/documentation/learn-dxpr-builder) /[Довідник](/uk/hc/documentation/learn-dxpr-builder/reference) /[Конфігурація та API](/uk/hc/documentation/learn-dxpr-builder/reference/config-and-api) # Довідник: кінцеві точки API.

 Вивчення DXPR BuilderДовідникКонфігурація та API

   ## In this guide

 Related guides

- [Довідник: параметри конфігурації](/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%BD%D0%B8%D0%BA/%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%BD%D0%B8%D0%BA-%D0%BD%D0%B0%D0%BB%D0%B0%D1%88%D1%82%D1%83%D0%B2%D0%B0%D0%BD%D1%8C)
- [Довідник API](/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D1%80%D0%BE%D0%B7%D1%80%D0%BE%D0%B1%D0%BA%D0%B0/api)
- [Довідник Hooks API](/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D1%80%D0%BE%D0%B7%D1%80%D0%BE%D0%B1%D0%BA%D0%B0/%D1%85%D1%83%D0%BA%D0%B8-api)

Ця сторінка перелічує кожен маршрут, який DXPR Builder реєструє у `dxpr_builder.routing.yml`, з HTTP-методами, вимогами доступу, параметрами запитів і формами відповідей, як реалізовано в контролерах. JavaScript редактора це призначений клієнт для кінцевих точок AJAX; ніщо на цій сторінці не є стабільним публічним API, і імена параметрів можуть змінюватися між релізами.

## Вимоги доступу

Маршрути використовують три види вимог. Маршрут може поєднувати їх.

| Вимога | Значення |
|---|---|
| `_permission` | Користувачу потрібен названий дозвіл Drupal. DXPR Builder визначає `administer dxpr builder configuration`, `edit with dxpr builder` і `administer dxpr_builder_profile` у `dxpr_builder.permissions.yml`; `view media` і `administer site configuration` надходять із ядра. |
| `_csrf_token` | Запит має містити дійсний CSRF-токен у параметрі запиту `token`. Для головного обробника AJAX редактор отримує URL із токеном з `/dxpr_builder/csrf` (або із операції `dxpr_builder_csrf`). Для інших маршрутів форматер поля кладе URL із токеном у `drupalSettings.dxprBuilder`, наприклад `fileUploadUrl`, `entityLinkSuggestionsUrl`, `userSettingsUrl` і `aiAgent.endpointUrl`. |
| `_dxpr_builder_billable_user` | Користувач має бути оплачуваним користувачем, як визначено нижче. |

### Що означає «billable user»

`DxprBuilderBillableUserAccessCheck` дозволяє доступ, коли `DxprBuilderLicenseService::isBillableUser()` повертає true для поточного облікового запису. Цей метод повертає false для заблокованих облікових записів і для облікових записів, у яких задано поле `dxpr_user_is_disavowed`(адміністратор виключає користувача з редагування на сторінці User Licenses). Інакше він повертає true для користувача 1 і для будь-якого облікового запису, що має дозвіл `edit with dxpr builder`. Коротко: оплачуваний користувач це активний, не виключений обліковий запис, якому дозволено редагувати за допомогою DXPR Builder, і служба ліцензій зараховує ці облікові записи до вашого ключа продукту.

### HTTP-методи

Де маршрут декларує `methods`, маршрутизуються лише ці методи. Де не декларує, маршрут приймає будь-який метод (`MethodFilter` у Drupal фільтрує лише маршрути, що декларують методи). Таблиці нижче вказують метод, який JavaScript редактора фактично використовує, коли це видно з вихідного коду.

## Кінцеві точки AJAX редактора

### URL CSRF-токена

|  |  |
|---|---|
| Шлях | `/dxpr_builder/csrf` |
| Маршрут | `dxpr_builder.csrf_refresh` |
| Методи | Не задекларовано (будь-який метод). Редактор надсилає GET (`backend-connect.js`, `fetchCsrfTokenUrl()`). |
| Вимоги | Оплачуваний користувач |
| Контролер | `AjaxController::ajaxRefresh()` |

Запит має містити заголовок `X-Requested-With: XMLHttpRequest`; без нього контролер повертає HTTP 403 з тілом JSON `{"error": "Invalid request"}`.

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `enterprise` | Рядок запиту | Необов’язково | Коли задано `true` і модуль `dxpr_builder_e` встановлено, токен генерується натомість для маршруту `dxpr_builder_e.ajax_callback`. Коли задано `true` без цього модуля, контролер кидає виняток. |

Відповідь: рядок JSON з URL головного обробника AJAX і параметром запиту `token`. URL це шлях від кореня сайту (базовий шлях включно, без хоста). JavaScript надсилає кожну операцію конструктора на цей URL методом POST.

### Головний обробник AJAX

|  |  |
|---|---|
| Шлях | `/dxpr_builder/ajax` |
| Маршрут | `dxpr_builder.ajax_callback` |
| Методи | Не задекларовано (будь-який метод). Контролер читає кожен параметр із тіла POST, а редактор надсилає POST. |
| Вимоги | Оплачуваний користувач, CSRF-токен |
| Контролер | `AjaxController::ajaxCallback()` |

Поле тіла POST `action` вибирає операцію. Кожну операцію та її параметри перелічено в розділі [Операції головного обробника AJAX](#main-ajax-handler-operations). Коли `action` відсутнє або невідоме, контролер повертає порожній Drupal `AjaxResponse` без команд. Більшість операцій, що перевіряють статус оплачуваного користувача знову, повертають ту саму порожню відповідь, коли ця перевірка не вдається; у таблицях зазначено два винятки.

### AI-чат

|  |  |
|---|---|
| Шлях | `/dxpr_builder/ajax/ai/chat` |
| Маршрут | `dxpr_builder.ai_chat` |
| Методи | POST |
| Вимоги | `edit with dxpr builder`, оплачуваний користувач, CSRF-токен |
| Контролер | `AiChatController::chat()` |

Тіло запиту це JSON. Контролер проксіює запит до постачальника `dxpr` модуля Drupal `ai`, тож жоден ключ API не доходить до браузера. Перед викликом він зливає домени з налаштування `ai_output_allowed_domains` у фільтр хостів модуля `ai`, коли така служба існує. Значення `*` натомість установлює фільтр на повну довіру. Після цього фільтр відновлюється.

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `messages` | Тіло JSON | Обов’язково | Масив об’єктів із `role` і `content`. |
| `stream` | Тіло JSON | Необов’язково | Логічне, стандартно `true`. |
| `model` | Тіло JSON | Необов’язково | Стандартно `kavya-m1`. |
| `prediction` | Тіло JSON | Необов’язково | Передається конфігурації постачальника як масив. |
| `providers` | Тіло JSON | Необов’язково | Передається наскрізно конфігурації постачальника. |
| `allowed_html_tags` | Тіло JSON | Необов’язково | Передається наскрізно конфігурації постачальника. |
| `allowed_html_classes` | Тіло JSON | Необов’язково | Передається наскрізно конфігурації постачальника. |
| `web_search` | Тіло JSON | Необов’язково | Пересилається лише значення `false`; будь-яке інше значення ігнорується. |
| `response_format` | Тіло JSON | Необов’язково | Передається конфігурації постачальника як масив. |

Відповіді:

| Випадок | Статус | Тіло |
|---|---|---|
| Потокова (`stream` true і постачальник передає потоком) | 200, `Content-Type: text/event-stream` | Події, надіслані сервером. Кожна подія це `data: <JSON>`, де JSON має `choices[0].delta.content` і, коли постачальник їх надає, `id`, `object`, `created`, `model`, `original_model` і `usage`. Потік закінчується `data: [DONE]`. |
| Непотокова | 200, `application/json` | `{"choices": [{"message": {"role": "assistant", "content": "<text>"}}]}` |
| Тіло не є JSON, або `messages` відсутнє чи порожнє | 400, звичайний текст | `Invalid request: messages required` |
| `model` немає у списку `allowed_models` файлу `ai_provider_dxpr.settings` (перевіряється, лише коли модуль `ai_provider_dxpr` встановлено й список задано) | 403, `application/json` | `{"error": {"code": "model_not_allowed", "message": "The selected model is not allowed. Please refresh the page to update your model options."}}` |
| Виняток постачальника | 500, `application/json` | `{"error": {"message": "The request could not be completed."}}` |

### Генерація AI-зображень

|  |  |
|---|---|
| Шлях | `/dxpr_builder/ajax/ai/image` |
| Маршрут | `dxpr_builder.ai_image` |
| Методи | POST |
| Вимоги | `edit with dxpr builder`, оплачуваний користувач, CSRF-токен |
| Контролер | `AiImageController::generate()` |

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `prompt` | Тіло JSON | Обов’язково | Текстовий запит. |
| `model` | Тіло JSON | Необов’язково | Стандартно `kavya-image`. |
| `size` | Тіло JSON | Необов’язково | Пересилається конфігурації постачальника, коли непорожнє. |
| `quality` | Тіло JSON | Необов’язково | Пересилається конфігурації постачальника, коли непорожнє. |
| `background` | Тіло JSON | Необов’язково | Пересилається конфігурації постачальника, коли непорожнє. |

Відповіді:

| Випадок | Статус | Тіло |
|---|---|---|
| Успіх | 200 | `{"data": [{"b64_json": "<base64 image>"}]}` (повертається лише перше згенероване зображення) |
| Тіло не є JSON, або `prompt` відсутній | 400 | `{"error": {"message": "Invalid request: prompt required"}}` |
| Постачальник не повернув зображення | 500 | `{"error": {"message": "No image was generated"}}` |
| Виняток постачальника | 500 | `{"error": {"message": "Image generation failed. Please try again."}}` |

### Редагування AI-зображень

|  |  |
|---|---|
| Шлях | `/dxpr_builder/ajax/ai/image/edit` |
| Маршрут | `dxpr_builder.ai_image_edit` |
| Методи | POST |
| Вимоги | `edit with dxpr builder`, оплачуваний користувач, CSRF-токен |
| Контролер | `AiImageController::edit()` |

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `prompt` | Тіло JSON | Обов’язково | Вказівка редагування. |
| `image` | Тіло JSON | Обов’язково | Вихідне зображення, закодоване Base64 (суворе декодування). |
| `mimeType` | Тіло JSON | Необов’язково | Стандартно `image/png`; підтип стає розширенням файла, переданим постачальнику. |
| `model` | Тіло JSON | Необов’язково | Стандартно `kavya-image`. |
| `size`, `quality`, `background` | Тіло JSON | Необов’язково | Пересилаються конфігурації постачальника, коли непорожні. |

Відповіді:

| Випадок | Статус | Тіло |
|---|---|---|
| Успіх | 200 | `{"data": [{"b64_json": "<base64 image>"}]}` |
| Тіло не є JSON, або `prompt` чи `image` відсутні | 400 | `{"error": {"message": "Invalid request: prompt and image required"}}` |
| `image` не є дійсним base64 | 400 | `{"error": {"message": "Invalid image data: base64 decode failed"}}` |
| Постачальник не повернув зображення | 500 | `{"error": {"message": "No image was generated"}}` |
| Виняток постачальника | 500 | `{"error": {"message": "Image editing failed. Please try again."}}` |

### Завантаження файлів

|  |  |
|---|---|
| Шлях | `/dxpr_builder/ajax/file_upload` |
| Маршрут | `dxpr_builder.ajax_file_upload_callback` |
| Методи | POST, DELETE (задекларовано в маршрутизації; контролер має один обробник завантаження й не має окремої гілки видалення) |
| Вимоги | Оплачуваний користувач, CSRF-токен |
| Контролер | `UploadFileController::fileUpload()` |

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `upload` | Файли multipart-форми, надіслані як `upload[]` | Обов’язково | Один або більше завантажених файлів. |

Контролер сортує кожен файл за першою частиною його клієнтського MIME-типу до `<default scheme>://dxpr_builder_images`, `dxpr_builder_videos` або `dxpr_builder_files`. Зображенню потрібне розширення MIME-типів `image/gif`, `jpg`, `jpeg`, `png`, `webp`, `avif` або `svg`. Відео потрібен один із `video/webm`, `ogv`, `ogg`, `mp4` або `quicktime` (наприклад `.mov`). Ліміт розміру це максимум завантаження PHP. Файл із тим самим ім’ям та ідентичним SHA-256-вмістом, що й наявний керований файл, який користувач може переглядати, використовується повторно замість збереження знову. Коли модуль `media` встановлено й існує медіатип із назвою `image`, `media_image`, `video` або `media_video`, створюється (або використовується повторно) опублікована медіасутність для файла. Використання файла записується за модулем `dxpr_builder`.

Відповіді:

| Випадок | Статус | Тіло |
|---|---|---|
| Успіх | 201 | Масив JSON, по одному об’єкту на файл: `url` (абсолютний URL файла), `uuid` і `id` (медіасутності, коли вона існує, інакше файла), `fid` (ID файла), `entity_type` (`media` або `file`). |
| Немає файлів `upload`. | 400 | `{"message": "No files were uploaded."}` |
| Недійсне завантаження, недоступне для запису місце призначення або збій збереження | 500 | `{"message": "<reason>"}` |
| Збій перевірки (розширення або розмір) | 422 | `{"message": "<violation messages>"}` |
| Ім’я файла вже заблоковано іншим запитом | 503 | `{"message": "File \"<name>\" is already locked for writing."}` |

### Діалогове вікно медіабібліотеки

|  |  |
|---|---|
| Шлях | `/dxpr_builder/media-library` |
| Маршрут | `dxpr_builder.media_library` |
| Методи | Не задекларовано (будь-який метод). Параметри читаються з рядка запиту. |
| Вимоги | `view media`; маршрут адміністрування |
| Контролер | `AjaxController::openImageMediaLibrary()` |

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `media_type` | Рядок запиту | Необов’язково | `image` (стандартно) або `video`. |
| `remaining_slots` | Рядок запиту | Необов’язково | Кількість елементів, які приймає відкривач; стандартно 1. |
| `uuid` | Рядок запиту | Необов’язково | Передається відкривачу як `opener_parameters.uuid`. |

Запропонований медіатип залежить від налаштування `media_browser`: `media_library` використовує медіатип `image` або `video` безпосередньо; `media_library_acquia_dam` використовує `acquia_dam_image_asset` або `acquia_dam_video_asset`, коли такий медіатип існує.

Відповіді:

| Випадок | Результат |
|---|---|
| Успіх | Масив рендера, побудований `MediaLibraryUiBuilder::buildUi()` з відкривачем `media_library.opener.dxpr_builder`. Drupal рендерить його як HTML-сторінку, призначену для iframe. |
| `media_library`: модуль не встановлено | 403, звичайний текст `Media Library is not enabled. Please enable it to access this feature.` |
| Непідтримуваний `media_type` | 400, звичайний текст `Unsupported media type "<value>".` |
| `media_browser`: налаштування не має придатного медіатипу | 400, звичайний текст `The "<setting>" settings is not supported.` |

### Перевірка посилань довідки

|  |  |
|---|---|
| Шлях | `/dxpr_builder/ajax/help_link_validator` |
| Маршрут | `dxpr_builder.ajax_help_link_validator` |
| Методи | Не задекларовано (будь-який метод). Скрипт розробки `dxpr_builder_dev.js` надсилає POST із тілом, закодованим як форма. |
| Вимоги | Оплачуваний користувач |
| Контролер | `AjaxController::validateHelpLink()` |

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `help_link` | Тіло POST | Обов’язково для змістовної відповіді | Перевіряються лише URL `http` або `https` на хості `dxpr.com` зі шляхом, що починається з `/documentation/`. |

Відповідь: масив JSON. `[true]`, коли HEAD-запит на посилання (без слідування перенаправленням) повертає 200; `[false]`, коли HTTP-клієнт кидає виняток; `[]` в кожному іншому випадку, включно з відсутнім параметром, невідповідним URL або статусом, відмінним від 200.

### Пропозиції посилань на сутності

|  |  |
|---|---|
| Шлях | `/dxpr_builder/entity-link-suggestions` |
| Маршрут | `dxpr_builder.entity_link_suggestions` |
| Методи | GET |
| Вимоги | `edit with dxpr builder`, CSRF-токен; опція маршруту `no_cache`. |
| Контролер | `EntityLinkSuggestionsController::suggestions()` |

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `q` | Рядок запиту | Обов’язково для результатів | Текст пошуку, малими літерами. Значення на кшталт `/node/123` завантажує цю сутність безпосередньо. |
| `langcode` | Рядок запиту | Необов’язково | Мова хост-сутності; стандартно поточна мова. Повертаються лише сутності, доступні цією мовою. |

Набори це ті, у чиїй інформації про набір увімкнено `ckeditor5_link_suggestions`; коли жодного не налаштовано, шукаються всі набори матеріалів. До 100 сутностей на тип сутності зіставляються пошуком `CONTAINS` через плагіни вибору посилань на сутності ядра.

Відповідь: `{"suggestions": [...]}` з приватною кешованістю й максимальним віком 300 секунд. Кожна пропозиція має `description`, `entity_type_id`, `entity_uuid`, `group`, `label` і `path`. Коли `q` нічого не збігає, масив містить одну пропозицію ручного посилання з `description`, `label` (введення малими літерами) і `path` (введення, коли це дійсний URL, інакше порожній рядок). Коли `q` порожнє, `suggestions` це порожній масив.

### Налаштування редактора користувача

|  |  |
|---|---|
| Шлях | `/dxpr_builder/user-settings` |
| Маршрут | `dxpr_builder.user_settings` |
| Методи | POST |
| Вимоги | `edit with dxpr builder`, CSRF-токен; опція маршруту `no_cache`. |
| Контролер | `UserSettingsController::save()` |

Редактор надсилає цей запит, коли користувач змінює власні налаштування редактора, наприклад у розділі **Editor settings**. Значення зберігаються із обліковим записом користувача в `user.data`, модуль `dxpr_builder`.

| Параметр | Джерело | Обов’язковість | Примітки |
|---|---|---|---|
| `controls_layout` | Тіло JSON | Обов’язково (єдине налаштування) | `element`, `breadcrumb` або `default`. `default` прибирає вибір користувача, тож застосовується налаштування профілю чи сайту. |

Відповіді:

| Випадок | Статус | Тіло |
|---|---|---|
| Збережено | 200 | `{"settings": {"controls_layout": "<value>"}}`: кожне налаштування після збереження, `default` там, де користувач не має збереженого вибору. |
| Тіло не є непорожнім об’єктом JSON, або ім’я чи значення недійсні | 400 | `{"error": "Invalid setting or value."}`. Нічого не зберігається. |

## Операції головного обробника AJAX

Усі операції надсилаються на `/dxpr_builder/ajax` з параметром запиту токена, отриманим з `/dxpr_builder/csrf`. Ім’я операції надсилається в полі тіла POST `action`; усі інші параметри це поля тіла POST, якщо не вказано інакше. Стовпець «Повторна перевірка billable» позначає операції, що викликають `isBillableUser()` знову всередині перемикача. Коли ця перевірка не вдається, вони повертають порожній `AjaxResponse`, описаний вище, якщо в рядку не сказано інакше.

### Сеанс і доступ

| Операція | Параметри | Повторна перевірка billable | Повертає |
|---|---|---|---|
| `dxpr_login` | Жодних | Ні | Логічне JSON: чи є поточний користувач оплачуваним. |
| `dxpr_builder_csrf` | Жодних | Так | Рядок JSON: URL обробника з параметром запиту `token` (те саме, що `/dxpr_builder/csrf` без опції `enterprise`). |

### Контейнери (поля, відрендерені з форматером DXPR Builder)

| Операція | Параметри | Повторна перевірка billable | Повертає |
|---|---|---|---|
| `dxpr_get_container_types` | Жодних | Так | Об’єкт JSON із ключами `entity_type\|bundle` зі значенням `entity_type - bundle`, по одному запису на набір, чиє стандартне відображення використовує форматер `dxpr_builder_text` принаймні на одному полі. |
| `dxpr_get_container_names` | `container_type` (обов’язково, `entity_type\|bundle`) | Так (повертає порожній рядок JSON замість порожньої відповіді) | Об’єкт JSON із ключами `entity_id\|field_name` (або `entity_id\|field_name\|langcode` для сутностей, що перекладаються) зі значенням `entity label\|field label`. Коли `container_type` відсутній або перевірка оплати не вдається, відповідь це порожній рядок JSON. |
| `dxpr_save_container` | `type` (обов’язково, `entity_type\|bundle`); `name` (обов’язково, `entity_id\|field_name` або `entity_id\|revision_id\|field_name`); `htmlContent` (обов’язково, закодована розмітка); `lang` (необов’язково, стандартно стандартна мова сайту) | Так | Порожній рядок JSON за успіху. HTTP 400 з повідомленням JSON, коли `htmlContent` не є рядком або мова не застосовується до сутності, що не перекладається; 404, коли запитаного перекладу немає; 500, коли сутність не можна завантажити. |

`dxpr_save_container` робить таке:

1. Декодує `htmlContent`: XOR кожного байта з 7, потім URL-декодування.
2. Записує результат у першу дельту названого поля.
3. Створює нову стандартну ревізію з повідомленням журналу `Saved with DXPR builder`, коли тип сутності ревізійний.
4. Прибирає будь-яке блокування вмісту для сутності.
5. Оновлює `block_revision_id` у розділах Layout Builder, що посилаються на збережений вбудований блок.
6. Збільшує значення стану `dxpr_builder.saves_count`.

Збереження відбувається, лише коли користувач має доступ `update` до сутності. Без нього операція все одно повертає успішну відповідь з порожнім рядком.

### CMS-елементи (блоки й вигляди)

| Операція | Параметри | Повторна перевірка billable | Повертає |
|---|---|---|---|
| `dxpr_builder_get_cms_element_names` | Жодних | Так | Об’єкт JSON із `DxprBuilderService::getCmsElementNames()` із ключами `list`, `disallowed` і `blockCategories`. |
| `dxpr_get_cms_element_settings` | `name` (обов’язково): `view-<view_id>-<display_id>` або `block-<plugin_id>`; `ajax_page_state[libraries]` (необов’язково, уже завантажені бібліотеки через кому) | Так | Об’єкт JSON із `css`, `js`, `settings` і `data`. Для вигляду `data` це відрендерені віджети відкритих фільтрів; для блока `data` це форма конфігурації блока, обгорнута тегами `<form>`, з видаленими елементами `provider`, `admin_label`, `label`, `label_display` і `context_mapping` та всіма відкритими елементами details. |
| `dxpr_builder_load_cms_element` | `name` (обов’язково, розбирається `parseStringForCmsElementInfo()`); `settings` (обов’язково); `data` (обов’язково, масив); `ajax_page_state[libraries]` (необов’язково) | Ні | Об’єкт JSON із `css`, `js`, `settings` і `data`, де `data` це відрендерені блок або відображення вигляду. |

В обох операціях, що повертають `settings`, `css` і `js` це відрендерені теги активів, яких ще немає на сторінці, а `settings` це декодований об’єкт `drupalSettings` або порожній рядок, коли їх немає.

### Шаблони сторінок

| Операція | Параметри | Повторна перевірка billable | Повертає |
|---|---|---|---|
| `dxpr_get_page_templates` | Жодних | Так | Масив JSON увімкнених шаблонів сторінок, кожен із `title`, `uuid`, `module` (завжди `null`: сутність його не зберігає), `category`, `date`, `weight` (ціле число) і `image` (URL `data:` або URL `not-found.png` модуля). |
| `dxpr_load_page_template` | `uuid` (обов’язково) | Так | Відповідь HTML, що містить розмітку шаблону з заміненими базовими токенами; порожня, коли жоден увімкнений шаблон не збігається. |

### Шаблони користувача

| Операція | Параметри | Повторна перевірка billable | Повертає |
|---|---|---|---|
| `dxpr_get_templates` | Жодних | Так | Масив JSON шаблонів, що належать поточному користувачу або позначені глобальними; шаблони, чий обліковий запис автора більше не існує, опускаються. Кожен запис має `id`, `uuid`, `name`, `global`, `current_user_is_author`, `author_id`, `author_name`, `type` і, коли збережено, `image` (URL `data:`). |
| `dxpr_load_template` | `uuid` (обов’язково) | Так | Відповідь HTML, що містить розмітку шаблону з заміненими базовими токенами; порожня, коли жоден увімкнений шаблон не збігається. |
| `dxpr_save_template` | `name` (обов’язково); `template` (обов’язково, розмітка); `type` (необов’язково, стандартно `custom`); `global` (необов’язково, приводиться до логічного); `image` (необов’язково: рядок base64 або URL `data:image` у тілі POST, або поле multipart-файла із ім’ям `image`) | Так | Об’єкт JSON із `message` і `code`. `code` 200 за успіху; `code` 409 (статус HTTP 200), коли існує шаблон із тим самим машинним ім’ям; `code` 400 з HTTP 400, коли зображення не є дійсними даними зображення. |
| `dxpr_delete_template` | `name` (обов’язково) | Так | Порожній рядок JSON. |

Машинне ім’я виводиться з `name` приведенням до малих літер і заміною кожного неперервного ланцюжка символів поза `a-z0-9_` на підкреслення. `type` повертається до атрибута `data-azb` у розмітці, коли збережений шаблон не має типу.

### Зображення

| Операція | Параметри | Повторна перевірка billable | Повертає |
|---|---|---|---|
| `dxpr_builder_get_image_urls` | `entityIDs` (обов’язково, масив); `imageStyle` (обов’язково; `original` для нестилізованого файла); `entityType` (обов’язково; `media` розв’язує медіаматеріали, будь-яке інше значення використовується як тип сутності ID) | Так | Текстове тіло: URL зображень через кому. Файли дають відносно-кореневий URL із параметром запиту `fid`. Медіаматеріали типу `image` або `video` розв’язуються до свого вихідного файла. Матеріали `acquia_dam_image_asset` дають URL DAM із доданими `mid`, `acquiaDamAsset` і `imageStyle`. Інші медіаматеріали пропускаються. HTTP 204 без тіла, коли `entityIDs` порожній або коли жоден медіаматеріал не можна розв’язати. |
| `dxpr_builder_get_image_style_url` | `imageStyle` (обов’язково); `entityId` (обов’язково); `entityTypeId` (обов’язково, `file` або `media`) | Так | Текстове тіло. Для файла: його відносно-кореневий URL через стиль зображень (файли SVG і `original` пропускають стиль), з параметром запиту `fid`. Для медіаматеріалу `acquia_dam_image_asset`: URL DAM. HTTP 204 без тіла для будь-якої іншої сутності або коли сутність не знайдено. |
| `dxpr_builder_get_image_metadata` | `entityId` (обов’язково); `entityType` (обов’язково, `file` або `media`) | Так (повертає 403 JSON замість порожньої відповіді) | `{"data": {"alt": "...", "title": "..."}}` з поля джерела зображення медіаматеріалу (актив Acquia DAM дає свій DAM-альтернативний текст і порожній заголовок). Для файла значення надходять із першого медіаматеріалу, чиє поле `field_media_image` посилається на нього. `data` це порожній масив, коли сутність не є ні файлом, ні медіаматеріалом, або коли жодне медіа не посилається на файл. Помилки: 400 `{"error": "Missing required parameters"}`, 404 `{"error": "Entity not found"}`, 500 `{"error": "Failed to load entity"}`, 403 `{"error": "Access denied"}`. |

### Блокування вмісту

| Операція | Параметри | Повторна перевірка billable | Повертає |
|---|---|---|---|
| `dxpr_content_lock_status` | `entity_id`, `revision_id`, `entity_type`, `langcode` (усі обов’язкові) | Ні | Об’єкт JSON із `status` (логічне) і `label` (мітка сутності); коли заблоковано, також `entity_lock_author_id` і `entity_lock_author_name`. |
| `dxpr_toggle_content_lock` | `entity_id`, `revision_id`, `entity_type`, `langcode`, `toggle_action` (усі обов’язкові; `lock` створює блокування, будь-яке інше значення його прибирає) | Ні | Об’єкт JSON із `label` і `status` (`true` після блокування, `false` після розблокування). Порожній масив JSON (`[]`), коли сутність не можна завантажити або користувач не має доступу `update`. |

## Сторінки адміністрування

Усі ці маршрути приймають будь-який метод (немає ключа `methods`). Шляхи, що містять `{...}`, приймають ID сутності конфігурації або ID міграції для `{migration_id}`.

| Шлях | Маршрут | Дозвіл | Призначення |
|---|---|---|---|
| `/admin/dxpr_studio` | `dxpr_builder.admin.studio` | `administer dxpr builder configuration` | Огляд DXPR Studio; сторінка блока адміністративного меню ядра, що перелічує дочірні сторінки. |
| `/admin/dxpr_studio/dxpr_builder` | `dxpr_builder.admin.studio.builder` | `administer dxpr builder configuration` | Огляд DXPR Builder; сторінка блока адміністративного меню ядра. |
| `/admin/dxpr_studio/dxpr_builder/settings` | `dxpr_builder.settings` | `administer dxpr builder configuration` | `DxprBuilderSettingsForm`: форма налаштувань модуля. |
| `/admin/dxpr_studio/dxpr_builder/ai_settings` | `dxpr_builder.ai_settings` | `administer dxpr builder configuration` | `DxprBuilderAiSettingsForm`: форма налаштувань AI. |
| `/admin/dxpr_studio/dxpr_builder/user_templates` | `entity.dxpr_builder_user_template.collection` | `administer site configuration` | Список сутностей конфігурації `dxpr_builder_user_template`. |
| `/admin/dxpr_studio/dxpr_builder/user_templates/add` | `entity.dxpr_builder_user_template.add_form` | `administer site configuration` | Додавання шаблону користувача. |
| `/admin/dxpr_studio/dxpr_builder/user_templates/{dxpr_builder_user_template}` | `entity.dxpr_builder_user_template.edit_form` | `administer site configuration` | Редагування шаблону користувача. |
| `/admin/dxpr_studio/dxpr_builder/user_templates/{dxpr_builder_user_template}/delete` | `entity.dxpr_builder_user_template.delete_form` | `administer site configuration` | Видалення шаблону користувача (форма підтвердження). |
| `/admin/dxpr_studio/dxpr_builder/page_template` | `entity.dxpr_builder_page_template.collection` | `administer site configuration` | Список сутностей конфігурації `dxpr_builder_page_template`. |
| `/admin/dxpr_studio/dxpr_builder/page_template/add` | `entity.dxpr_builder_page_template.add_form` | `administer site configuration` | Додавання шаблону сторінки. |
| `/admin/dxpr_studio/dxpr_builder/page_template/create` | `dxpr_builder.create_page_template` | `administer dxpr builder configuration` | `PageController::createPageTemplate()`: копіює ввімкнений шаблон користувача, ідентифікований параметром запиту `uuid`, у новий шаблон сторінки з тим самим ID і категорією `DXPR`. Установлює повідомлення статусу чи помилки й перенаправляє до списку шаблонів користувача. |
| `/admin/dxpr_studio/dxpr_builder/page_template/{dxpr_builder_page_template}` | `entity.dxpr_builder_page_template.edit_form` | `administer site configuration` | Редагування шаблону сторінки. |
| `/admin/dxpr_studio/dxpr_builder/page_template/{dxpr_builder_page_template}/delete` | `entity.dxpr_builder_page_template.delete_form` | `administer site configuration` | Видалення шаблону сторінки (форма підтвердження). |
| `/admin/dxpr_studio/dxpr_builder/profile` | `entity.dxpr_builder_profile.collection` | `administer dxpr_builder_profile` | Список сутностей конфігурації `dxpr_builder_profile`. |
| `/admin/dxpr_studio/dxpr_builder/profile/add` | `entity.dxpr_builder_profile.add_form` | `administer dxpr_builder_profile` | Додавання профілю. |
| `/admin/dxpr_studio/dxpr_builder/profile/{dxpr_builder_profile}` | `entity.dxpr_builder_profile.edit_form` | `administer dxpr_builder_profile` | Редагування профілю. |
| `/admin/dxpr_studio/dxpr_builder/profile/{dxpr_builder_profile}/delete` | `entity.dxpr_builder_profile.delete_form` | `administer dxpr_builder_profile` | Видалення профілю (форма підтвердження). |
| `/admin/dxpr_studio/dxpr_builder/user_licenses` | `dxpr_builder.user_licenses` | `administer dxpr builder configuration` | `PageController::userLicensesPage()`: некешована таблиця ліцензованих користувачів (стовпці User, Roles, Sites, Assigned і Operations). Над нею сторінка рендерить власну картку підсумку ліцензії (`dxpr-license-info`), коли доступна інформація про ліцензію, а доки звільнена ліцензія очікує свої 30 днів, сповіщення «Next license available on». На цьому маршруті блок **License info** не рендерить нічого, тож підсумок ніколи не показується двічі. |
| `/admin/dxpr_studio/dxpr_builder/user_licenses/sites` | `dxpr_builder.user_licenses.sites` | `administer dxpr builder configuration` | `PageController::userLicensesSitesPage()`: список елементів доменів, записаних для користувача, заданого параметром запиту `mail`; відкривається в діалоговому вікні з таблиці ліцензій. |
| `/admin/dxpr_studio/dxpr_builder/content` | `dxpr_builder.licensed_content` | `administer dxpr builder configuration` | `PageController::licensedContentPage()`: посторінкова таблиця (по 20 на сторінку) матеріалів, редагованих за допомогою DXPR Builder, із підсумком ліцензії матеріалів. Параметр запиту `needs_migration=1` показує лише матеріали, що потребують міграції вмісту. Порожня, коли немає доступної інформації про ліцензію. |
| `/admin/dxpr_studio/dxpr_builder/migration-status` | `dxpr_builder.migration_status` | `administer dxpr builder configuration` | `MigrationStatusController::statusPage()`: некешована таблиця зареєстрованих міграцій вмісту із їхніми очікуваними матеріалами. Кожна очікувана міграція має посилання **Run now**, а кнопка **Run all pending migrations** з’являється, коли є очікувані. |
| `/admin/dxpr_studio/dxpr_builder/migration-run/{migration_id}` | `dxpr_builder.migration_run_confirm` | `administer dxpr builder configuration` | `MigrationRunConfirmForm`: підтверджує, потім виконує одну міграцію як пакет і повертається на сторінку статусу. |
| `/admin/dxpr_studio/dxpr_builder/migration-run-all` | `dxpr_builder.migration_run_all_confirm` | `administer dxpr builder configuration` | `MigrationRunAllConfirmForm`: підтверджує, потім виконує кожну зареєстровану міграцію як один пакет і повертається на сторінку статусу. |
| `/dxpr-builder/disavow-user` | `dxpr_builder.disavow_user_confirm` | `administer dxpr builder configuration` | `DisavowUserConfirmForm`: підтверджує виключення користувача, заданого параметром запиту `uid`, з редагування DXPR Builder. |
| `/dxpr-builder/delete-stale-user` | `dxpr_builder.delete_stale_user_confirm` | `administer dxpr builder configuration` | `DeleteStaleUserConfirmForm`: підтверджує видалення даних ліцензії для адреси електронної пошти, заданої параметром запиту `email`. |

## Що далі?

- [Довідник конфігурації](/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%BD%D0%B8%D0%BA/%D0%B4%D0%BE%D0%B2%D1%96%D0%B4%D0%BD%D0%B8%D0%BA-%D0%BD%D0%B0%D0%BB%D0%B0%D1%88%D1%82%D1%83%D0%B2%D0%B0%D0%BD%D1%8C) для налаштувань, що керують поведінкою браузера медіа й AI, яку використовують ці кінцеві точки.
- [PHP API](/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D1%80%D0%BE%D0%B7%D1%80%D0%BE%D0%B1%D0%BA%D0%B0/api) для служб, які викликають контролери.
- [Hooks API](/uk/hc/%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D1%96%D1%8F/%D0%BD%D0%B0%D0%B2%D1%87%D0%B0%D0%BD%D0%BD%D1%8F-dxpr-builder/%D1%80%D0%BE%D0%B7%D1%80%D0%BE%D0%B1%D0%BA%D0%B0/%D1%85%D1%83%D0%BA%D0%B8-api) для хуків, що дають іншим модулям змінювати поведінку конструктора.