
# Аутентификация по ссылке из рассылки

## Описание метода

Метод позволяет автоматически авторизовать клиента на сайте при переходе по персональной ссылке из рассылки.

Как это работает:

* В рассылке формируется персональная ссылка с [тикетом аутентификации](https://help.mindbox.ru/docs/%D1%82%D0%B8%D0%BA%D0%B5%D1%82)
* Клиент переходит по ссылке на сайт
* Сайт извлекает тикет из URL и отправляет запрос в Mindbox API
* Mindbox проверяет тикет и возвращает данные клиента, если тикет корректен
* Сайт авторизует клиента на основе полученных данных

:::info

Настройка авторизации через ссылку в чат-боте описана в [статье](https://developers.mindbox.ru/docs/chatbot-authorization).

:::
  
## Предварительная настройка

Перед началом интеграции убедитесь, что:

1. Создана операция в Mindbox со следующими шагами:

   * Клиент — Авторизованный — Получить существующего по тикету
   * Клиент — Получить данные по текущему клиенту (настройте нужные поля для возврата)

   :::info
   [Подробнее о создании операций](https://help.mindbox.ru/docs/%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8-v-%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D1%8B%D0%B5-%D1%81%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F).
   :::

2. Настроена ссылка перехода в рассылки с использованием тикета. Например универсальный тикет на 5 минут:
`https://example.com/auth?ticket=${Ticket.UniversalAuthenticationCustomizableTimeTicket(5)}`

## Формат запроса

### URL и параметры

`POST https://api.mindbox.ru/v3/operations/sync?endpointId={Идентификатор точки интеграции}&operation={Название операции}&deviceUUID={Уникальный идентификатор устройства}`

:::info
Подробнее о работе с V3 API, URL запросов и заголовках: [Документация V3 API](https://developers.mindbox.ru/docs/v3)
:::

### Заголовки

<table class="tg"><thead>
  <tr>
    <th class="tg-0lax">Заголовок</th>
    <th class="tg-0lax">Значение JSON</th>
    <th class="tg-0lax">Значение XML</th>
  </tr></thead>
<tbody>
  <tr>
    <td class="tg-0lax">Authorization</td>
    <td class="tg-0lax" colspan="2">SecretKey &lbrace;секретный_ключ_точки_интеграции&rbrace;</td>
  </tr>
  <tr>
    <td class="tg-0lax">Content-Type</td>
    <td class="tg-0lax">application/json; charset=utf-8</td>
    <td class="tg-0lax">application/xml; charset=utf-8</td>
  </tr>
  <tr>
    <td class="tg-0lax">Accept</td>
    <td class="tg-0lax">application/json</td>
    <td class="tg-0lax">application/xml</td>
  </tr>
</tbody>
</table>

### Тело запроса

<Tabs defaultValue="1" className="w-full">
  <ScrollArea className="w-full">
    <TabsList className="flex w-max gap-2">
      <TabsTrigger value="1">JSON</TabsTrigger>
      <TabsTrigger value="2">XML</TabsTrigger>
    </TabsList>
    <ScrollBar orientation="horizontal" />
  </ScrollArea>
  
  <TabsContent value="1">

  ```json
  {
    "customer": {
      "authenticationTicket": "<Тикет аутентификации клиента из ссылки>"
    }
  }
  ```
    </TabsContent>
    <TabsContent value="2">

  ```xml
  <operation>
    <customer>
      <authenticationTicket>Тикет аутентификации клиента из ссылки</authenticationTicket>
    </customer>
  </operation>
  ```
  </TabsContent>
</Tabs>

## Пример запроса

<Tabs defaultValue="1" className="w-full">
  <ScrollArea className="w-full">
    <TabsList className="flex w-max gap-2">
      <TabsTrigger value="1">JSON</TabsTrigger>
      <TabsTrigger value="2">XML</TabsTrigger>
    </TabsList>
    <ScrollBar orientation="horizontal" />
  </ScrollArea>
  
  <TabsContent value="1">

  ```json
  POST https://api.mindbox.ru/v3/operations/sync?endpointId=MindboxRu&operation=AuthenticateByTicket&deviceUUID=550e8400-e29b-41d4-a716-446655440000

  Content-Type: application/json; charset=utf-8
  Accept: application/json
  Authorization: SecretKey {Секретный ключ}

  {
    "customer": {
      "authenticationTicket": "YwQzgwMDY5Q0IwNEE5RDNFRDAyMzRBQTE4NTZCMkVENzAyNzE1MCIgc2lnbmF0dXJlPSJFREVEMkE2NzNDQjAwMEY1MTNGQzBGN0Q0NkY0NTY2MjRGMThCNjVCRUE5REM4MDMxRUJDNTZBOTJBODdGN0JBOTZBOTJBQzk3NjRBNjBGRURCNjYwRjAzRkY0NDgyMzkxMjI5MkI4NDhENEZGQTUwRDExODA2NjAwMkVCOTlBMSIgLz"
    }
  }
  ```
    </TabsContent>
    <TabsContent value="2">
  ```xml
  POST https://api.mindbox.ru/v3/operations/sync?endpointId=MindboxRu&operation=AuthenticateByTicket&deviceUUID=550e8400-e29b-41d4-a716-446655440000

  Accept: application/xml
  Content-Type: application/xml
  Authorization: SecretKey {Секретный ключ}

  <operation>
    <customer>
      <authenticationTicket>YwQzgwMDY5Q0IwNEE5RDNFRDAyMzRBQTE4NTZCMkVENzAyNzE1MCIgc2lnbmF0dXJlPSJFREVEMkE2NzNDQjAwMEY1MTNGQzBGN0Q0NkY0NTY2MjRGMThCNjVCRUE5REM4MDMxRUJDNTZBOTJBODdGN0JBOTZBOTJBQzk3NjRBNjBGRURCNjYwRjAzRkY0NDgyMzkxMjI5MkI4NDhENEZGQTUwRDExODA2NjAwMkVCOTlBMSIgLz</authenticationTicket>
    </customer>
  </operation>
  ```
  </TabsContent>
</Tabs>

## Пример ответа

:::info{title="Состав параметров"}
Параметры в узле `customer` зависят от полей, выбранных в шаге операции «Клиент — Получить данные по текущему клиенту». Уточните список у менеджера проекта или посмотрите в описании операции.
:::

### Корректный тикет

При передаче валидного тикета API возвращает данные клиента:

<Tabs defaultValue="1" className="w-full">
  <ScrollArea className="w-full">
    <TabsList className="flex w-max gap-2">
      <TabsTrigger value="1">JSON</TabsTrigger>
      <TabsTrigger value="2">XML</TabsTrigger>
    </TabsList>
    <ScrollBar orientation="horizontal" />
  </ScrollArea>
  
  <TabsContent value="1">
  ```json
  {
    "status": "Success",
    "customer": {
        "firstName": "Иван",
        "lastName": "Петров",
        "email": "test@example.com",
        "isEmailInvalid": false,
        "mobilePhone": 79991234567,
        "isMobilePhoneInvalid": false,
        "ids": {
          "mindboxId": 12345,
          "websiteID": "user-67890"
        },
        "changeDateTimeUtc": "2026-02-19T08:21:29.54Z"
    }
  }
  ```
    </TabsContent>
    <TabsContent value="2">
  ```xml
  <result>
      <status>Success</status>
      <customer>
          <firstName>Иван</firstName>
          <middleName>Петров</middleName>
          <email>test@example.com</email>
          <isEmailInvalid>false</isEmailInvalid>
          <mobilePhone>79991234567</mobilePhone>
          <isMobilePhoneInvalid>false</isMobilePhoneInvalid>
          <changeDateTimeUtc>2026-02-19 08:21:29.540</changeDateTimeUtc>
          <ids>
            <mindboxId>12345</mindboxId>
            <websiteID>user-67890</websiteID>
          </ids>
      </customer>
  </result>
  ```
  </TabsContent>
</Tabs>

### Некорректный или просроченный тикет

При передаче невалидного тикета API возвращает ответ без данных клиента:

<Tabs defaultValue="1" className="w-full">
  <ScrollArea className="w-full">
    <TabsList className="flex w-max gap-2">
      <TabsTrigger value="1">JSON</TabsTrigger>
      <TabsTrigger value="2">XML</TabsTrigger>
    </TabsList>
    <ScrollBar orientation="horizontal" />
  </ScrollArea>
  
  <TabsContent value="1">
  ```json
  {
    "status": "Success"
  }
  ```
    </TabsContent>
    <TabsContent value="2">
  ```xml
  <result>
      <status>Success</status>
  </result>
  ```
  </TabsContent>
</Tabs>

<Accordion type="single" collapsible >
  <AccordionItem value="item-1">
    <AccordionTrigger className="flex flex-1 items-center justify-start gap-2 p-2 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180 text-left"><CircleAlertIcon color="#39AA5D" /> Полный список возможных параметров ответа </AccordionTrigger>
    <AccordionContent>

    | Параметр | Описание | Присутствует | Пример |
    |---|---|---|---|
    | "/status | Результат выполнения запроса | Всегда присутствует | Success |
    | "/customer/firstName | Имя | Присутствует, если поле заполнено | Иван |
    | "/customer/middleName | Отчество | Присутствует, если поле заполнено | Иванович |
    | "/customer/lastName | Фамилия | Присутствует, если поле заполнено | Иванов |
    | "/customer/email | Адрес электронной почты | Присутствует, если поле заполнено | 64EalP@xlpshifb.qv |
    | "/customer/isEmailInvalid | Адрес электронной почты невалиден | Отсутствует, если у клиента нет адреса электронной почты | true |
    | "/customer/mobilePhone | Номер мобильного телефона | Присутствует, если поле заполнено | 79512201673 |
    | "/customer/isMobilePhoneInvalid | Мобильный телефон невалиден | Отсутствует, если у клиента нет телефона | true |
    | "/customer/birthDate | Дата рождения в формате yyyy-MM-dd | Присутствует, если поле заполнено | 1990-01-31 |
    | "/customer/sex | Пол | Присутствует, если поле заполнено | female |
    | "/customer/changeDateTimeUtc | Дата регистрации/редактирования в формате yyyy-MM-dd HH:mm:ss.fff | Всегда присутствует | 2022-12-25 08:30:33.669 |
    | "/customer/ianaTimeZone | Часовой пояс | Присутствует, если поле заполнено | Asia/Hong_Kong |
    | "/customer/timeZoneSource | Источник информации о часовом поясе | Присутствует, если поле заполнено | Определили в трекере |
    | "/customer/processingStatus | Статус обработки клиента | Всегда присутствует | Processed |
    | "/customer/ids/mindboxId | Идентификатор клиента | Всегда присутствует | 668028497 |
    | "/customer/area/name | Название географической зоны клиента | Отсутствует, если у клиента не указана зона | Москва |
    | "/customer/area/ids/externalId | Идентификатор географической зоны клиента | Отсутствует, если у клиента не указана зона | MoscowCity |
    | "/customer/subscriptions/subscription/brand | Бренд | Всегда присутствует | IZy9Vg |
    | "/customer/subscriptions/subscription/pointOfContact | Точка контакта | Может отсутствовать | uRSh |
    | "/customer/subscriptions/subscription/topic | Тематика | Может отсутствовать | 81odG |
    | "/customer/subscriptions/subscription/isSubscribed | Подписка | Всегда присутствует | true |
    | "/retailOrderStatistics/totalPaidAmount | Сумма заказов клиента | Всегда присутствует | 19096020.29 |
    | "/balances/balance/total | Суммарный баланс | Всегда присутствует | 4263407.35 |
    | "/balances/balance/available | Доступный баланс | Всегда присутствует | 16279652.34 |
    | "/balances/balance/blocked | Заблокированный баланс | Всегда присутствует | 16896236.63 |
    | "/balances/balance/systemName | Системное имя балльного счёта | Всегда присутствует | ern2HvtB2a |
    | "/balances/balance/nearestExpiration/total | Количество баллов к сгоранию | Присутствует, если поле заполнено | 6128381.84 |
    | "/balances/balance/nearestExpiration/date | Ближайщая дата сгорания баллов | Присутствует, если поле заполнено | 2024-07-15 |
    | "/balances/balance/balanceType/name | Название балльного счёта | Присутствует, если действие связано с изменением баланса | huf8fHpS |
    | "/balances/balance/balanceType/ids/systemName | Системное имя балльного счёта | Присутствует, если действие связано с изменением баланса | gx53toeP |
    | "/discountCards/discountCard/ids/mindboxId | Номер дисконтной карты в БД Mindbox | Всегда присутствует | 180040923 |
    | "/discountCards/discountCard/ids/number | Номер дисконтной карты | Всегда присутствует | 3NkoQCw |
    | "/discountCards/discountCard/status/dateTimeUtc | Время присвоения статуса | Присутствует, если время известно | 2024-06-18 08:30:33.628 |
    | "/discountCards/discountCard/status/ids/systemName | Статус дисконтной карты | Всегда присутствует | Issued |
    | "/discountCards/discountCard/type/name | Название типа дисконтной карты | Всегда присутствует | XuqAsC |
    | "/discountCards/discountCard/type/ids/externalId | Внешний идентификатор типа дисконтной карты | Всегда присутствует | 426474496 |
    | "/personalOffers/personalOfferItem/startDateTimeUtc | Дата начала действия предложения | Всегда присутствует | 2025-05-13 08:30:33.621 |
    | "/personalOffers/personalOfferItem/endDateTimeUtc | Дата окончания действия предложения | Всегда присутствует | 2025-06-14 08:30:33.621 |
    | "/personalOffers/personalOfferItem/product/ids/mindboxId | Идентификатор Mindbox | Всегда присутствует | 1802094567 |
    | "/personalOffers/personalOfferItem/benefit/amount/value | Размер скидки. Применимо к скидочной и к бальной промоакции | Всегда присутствует | 6293408.5 |
    | "/personalOffers/personalOfferItem/benefit/amount/type | Тип скидки. Возможные значения Price (стоимость продукта), Percent (значение скидки в процентах), Absolute (абсолютное значение скидки) | Всегда присутствует | Price |
    | "/productList/productListItem/count | Количество продуктов в списке | Всегда присутствует | 5342833.92 |
    | "/productList/productListItem/lastEditedDateTimeUtc | Дата последнего изменения | Всегда присутствует | 2023-07-25 08:30:33.715 |
    | "/productList/productListItem/priceOfLine | Цена за выбранное количество продуктов | Всегда присутствует | 20773196.57 |
    | "/productList/productListItem/product/name | Наименование продукта | Всегда присутствует | Напиток (арт. 400929) |
    | "/productList/productListItem/product/description | Описание | Всегда присутствует, может быть пустым | Products:ProductDescriptionExample |
    | "/productList/productListItem/product/url | Ссылка на страницу с описанием | Всегда присутствует, может быть пустым | http://grpuzzccq.com/pjazdwaoz?drearm=BX6r&ndzhqx=PXh6W |
    | "/productList/productListItem/product/pictureUrl | Ссылка на картинку | Всегда присутствует, может быть пустым | http://bsjaui.com/capsx?xmspwp=4ykAs1&vpjlystov=GuJF |
    | "/productList/productListItem/product/price | Цена продукта | Всегда присутствует | 4781726.51 |
    | "/productList/productListItem/product/oldPrice | Старая цена продукта | Всегда присутствует | 9237906.38 |
    | "/productList/productListItem/product/isAvailable | Доступность | Всегда присутствует | false |
    | "/productList/productListItem/product/ids/mindboxId | Идентификатор Mindbox | Всегда присутствует | 1856094692 |
    | "/productList/productListItem/productGroup/ids/mindboxId | Идентификатор Mindbox | Всегда присутствует | 1614672846 |


    </AccordionContent>
  </AccordionItem>
</Accordion>

## Обработка ошибок

### ProtocolError

Ошибка возникает при передаче пустого значения `authenticationTicket`:

<Tabs defaultValue="1" className="w-full">
  <ScrollArea className="w-full">
    <TabsList className="flex w-max gap-2">
      <TabsTrigger value="1">JSON</TabsTrigger>
      <TabsTrigger value="2">XML</TabsTrigger>
    </TabsList>
    <ScrollBar orientation="horizontal" />
  </ScrollArea>
  
  <TabsContent value="1">

  ```json
  {
    "status": "ProtocolError",
    "errorMessage": "/customer/authenticationTicket: Поле должно быть заполнено.",
    "errorId": "<Идентификатор ошибки. Может отсутствовать>",
    "httpStatusCode": 400
  }
  ```
    </TabsContent>
    <TabsContent value="2">
  ```xml
  <result>
      <status>ProtocolError</status>
      <errorMessage>/operation/customer/authenticationTicket: Поле должно быть заполнено.</errorMessage>
      <errorId>{Идентификатор ошибки. Может отсутствовать}</errorId>
      <httpStatusCode>400</httpStatusCode>
  </result>>
  ```
  </TabsContent>
</Tabs>

## Обработка результата на сайте

После получения ответа от API:

1. Проверьте статус ответа (`status`)
2. Проверьте наличие узла `customer` в ответе
3. Если данные клиента **получены** — авторизуйте клиента на сайте
4. Если данные клиента **отсутствуют** — перенаправьте на страницу входа

Конкретная реализация зависит от особенностей вашей интеграции.

## Связанные материалы

* [Аутентификация по паролю](https://developers.mindbox.ru/docs/password-based-authentication)
* [Аутентификация по секретному коду](https://developers.mindbox.ru/docs/secret-code-authentication)
* [Типы тикетов аутентификации](https://help.mindbox.ru/docs/%D1%82%D0%B8%D0%BA%D0%B5%D1%82)
