# API Пресетов

[Пресет push-уведомлений](/ru/product/content/push-presets/) — это многоразовый шаблон push-уведомлений, тот же объект, который вы создаете в редакторе push-уведомлений в Панели управления. Этот API управляет только пресетами push-уведомлений; пресеты для SMS, WhatsApp, Kakao, LINE и Viber имеют свои собственные специализированные сервисы, которые здесь не рассматриваются.

Используйте `code` пресета, чтобы отправить его через [`Notify`](/ru/developer/api-reference/messaging-api-v2/notify/) (полезная нагрузка `preset`) или через точку [Send push в Customer Journey](/ru/developer/api-reference/customer-journey-api/point-reference/#messaging-points).

## Базовый URL

```
https://rpc-api.svc-nue.pushwoosh.com
```

Все эндпоинты обслуживаются по HTTPS. Запросы и ответы используют `application/json`, если не указано иное.

## Аутентификация

Каждый запрос должен включать заголовок `Authorization` с вашим [токеном Server API](/ru/developer/api-reference/api-access-token/#server-api-token):

```
Authorization: Api YOUR_API_TOKEN
```

## Соглашения

*   **Именование полей:** тела запросов и параметры query/path принимают `lowerCamelCase` (например, `sendType`, `localizedProperties`, `searchByName`) — сервер разбирает любой регистр. Ответы всегда маршалируются с использованием имен полей proto, в `snake_case` (`localized_properties`, `platform_properties`, `per_page` и так далее). В примерах ответов и в справочнике по [объекту Preset](#preset-object) ниже используется этот регистр.
*   **`code`:** каждый ответ с пресетом содержит его собственный код, сгенерированный при `Create`. Передавайте этот код в `Get`, `Update`, `UpdatePartial`, `Delete`, `Clone`, а также в вышеупомянутые API для сообщений/journey.
*   **Ключи платформ:** карты `platforms` и `open_actions` используют в качестве ключей числовой [код типа устройства](/ru/developer/api-reference/api-identifiers/#device-type) (`1` для iOS, `3` для Android и так далее). `platform_properties` использует в качестве ключа имя enum платформы (`IOS`, `ANDROID`, `HUAWEI_ANDROID`, `OSX` — единственные четыре платформы, которые он охватывает).
*   **Незаполненные поля:** ответы `Get`, `Create` и `Clone` включают все поля [объекта Preset](#preset-object), даже если они пустые или имеют нулевое значение. `List` возвращает сокращенный набор полей — см. [Список](#list) ниже. `Update` и `UpdatePartial` вообще не возвращают поля пресета — см. [предупреждение](#update) в их разделах.

### Ответы об ошибках

| HTTP-статус | Значение |
| :---- | :---- |
| `400 Bad Request` | Неверный аргумент — обязательное поле отсутствует или имеет неверный формат, или не выполнено предварительное условие (например, клонирование без `name`). |
| `401 Unauthorized` | Отсутствует или недействителен заголовок `Authorization`. |
| `403 Forbidden` | Приложение или пресет не принадлежат аккаунту вызывающей стороны. |
| `404 Not Found` | Пресет или приложение не найдены. |
| `500 Internal Server Error` | Неожиданный сбой на стороне сервера. |

`Delete` для пресета, который все еще используется точкой Send push в запущенном или приостановленном journey, также вернет `400 Bad Request` (`FailedPrecondition` на уровне протокола) — а не `409`. Сначала удалите пресет из journey.

`Create`, `Update` и `UpdatePartial` также возвращают `400 Bad Request` для неразрешимого [токена персонализации](#personalization-tokens) — см. ниже.

## Токены персонализации

`Create`, `Update` и `UpdatePartial` проверяют каждый [токен персонализации](/ru/product/personalization/dynamic-content/) (`{name|modifier|default}`) в `localizedTitle`, `localizedSubtitle` и `localizedContent` (для каждого языка в запросе), а также в полях с rich-контентом для каждой платформы, в которые отправитель подставляет значения (title, content, banner, icon, URL, параметры deep-link и т.д., для каждой платформы). Поля вне этого набора, такие как `richmedia`, `campaignCode`, `deeplink` или `filterCode`, сохраняют токен в точности как он написан — Pushwoosh не анализирует синтаксис персонализации в них.

Токен должен иметь модификатор, который Pushwoosh распознает, потому что немодифицированный или написанный с ошибкой токен не может быть отформатирован и в противном случае дойдет до пользователей в виде фигурных скобок. Токен с отсутствующим или неизвестным модификатором (`{Tag|}`, `{Tag|typo}`) приведет к сбою вызова с `InvalidArgument`:

```json
{
  "code": 3,
  "message": "токен персонализации {Tag|} не имеет известного модификатора, поэтому он будет доставлен как текст; ожидался один из [capitalizefirst capitalizeallfirst uppercase lowercase regular base64 cent dollar comma euro jpy lira M-d-y m-d-y M d y M d Y l M d H:i m-d-y H:i]"
}
```

<Aside type="caution">
При `UpdatePartial` эта проверка выполняется для всего сохраненного набора полей с подставляемым контентом пресета, а не только для полей в текущем запросе — пресет, который уже имеет неработающий токен в незатронутом поле, будет вызывать сбой каждого последующего вызова `UpdatePartial` до тех пор, пока этот токен не будет исправлен. `localizedTitle`, `localizedSubtitle` и `localizedContent` являются исключением: они проверяются только тогда, когда тот же вызов включает их.
</Aside>

### Допустимые модификаторы

Выборщик персонализации в Панели управления уже предлагает все нижеперечисленные модификаторы для тегов `INTEGER`/`PRICE` (включая форматы дат) и для строковых тегов, за исключением `base64` — этот доступен только через API. `gitlab.corp.pushwoosh.com/channels/sdk/pkg/dynamiccontent` является источником истины, по которому проверяют и Панель управления, и этот API.

| Модификатор | Тип тега | Примечания |
| :---- | :---- | :---- |
| `capitalizefirst` | string | Без учета регистра |
| `capitalizeallfirst` | string | Без учета регистра |
| `uppercase` | string | Без учета регистра |
| `lowercase` | string | Без учета регистра |
| `regular` | string или integer | Без учета регистра, форматирование не применяется |
| `base64` | string | Без учета регистра, только через API — не предлагается в CP |
| `cent` / `dollar` / `comma` / `euro` / `jpy` / `lira` | integer | Без учета регистра |
| `M-d-y`, `m-d-y`, `M d y`, `M d Y`, `l`, `M d`, `H:i`, `m-d-y H:i` | integer | Модификаторы формата даты, сопоставляются в точности как написаны, с учетом регистра |

## Эндпоинты

| Метод | Путь | Описание |
| :---- | :---- | :---- |
| `POST` | `/api/presets` | Создать новый пресет push-уведомлений |
| `GET` | `/api/presets` | Получить список пресетов push-уведомлений приложения |
| `GET` | `/api/presets/{code}` | Получить один пресет push-уведомлений |
| `PUT` | `/api/presets/{code}` | Обновить пресет push-уведомлений (полная перезапись) |
| `PUT` | `/api/presets/{code}:partial` | Обновить пресет push-уведомлений (частично) |
| `POST` | `/api/presets/{code}:clone` | Клонировать пресет push-уведомлений |
| `DELETE` | `/api/presets/{code}` | Удалить пресет push-уведомлений |

## Создать

Создает новый пресет push-уведомлений в приложении и возвращает его со сгенерированным кодом.

`POST` `/api/presets`

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

| Параметр | Тип | Обязательный | Описание |
| :---- | :---- | :---- | :---- |
| `application` | string | Да | [Код приложения](/ru/developer/api-reference/api-identifiers/#application-code), в котором создается пресет. |
| `name` | string | Да | Название пресета. |
| `sendType` | string | Нет | Канал пресета (например, `push`). |
| `isV2` | boolean | Нет | Устанавливает флаг происхождения пресета. Опустите, чтобы по умолчанию было `true` (v2); установите `false` только при воспроизведении устаревшего пресета v1. |

Все остальные поля — локализованный контент, платформы, deep link, inbox, категории и т.д. — совпадают с `Update` и документированы один раз в справочнике по [объекту Preset](#preset-object) ниже.

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

```json
{
  "application": "XXXXX-XXXXX",
  "name": "20% discount",
  "platforms": { "1": true, "3": true },
  "localizedContent": {
    "default": "Get your 20% discount right now",
    "es": "Consigue tu 20% de descuento ahora mismo"
  },
  "localizedTitle": { "default": "Hi there" },
  "openAction": { "link": { "url": "https://example.com" } },
  "categories": ["promo"]
}
```

### Ответ

Возвращает `{ "preset": { ... } }`, созданный [объект Preset](#preset-object).

## Список

Возвращает список пресетов push-уведомлений приложения — сокращенный набор полей, а не полный объект — с пагинацией, сортировкой и фильтрацией по названию или категории.

`GET` `/api/presets`

### Параметры запроса

| Параметр | Тип | Обязательный | Описание |
| :---- | :---- | :---- | :---- |
| `application` | string | Да | Код приложения, для которого нужно получить список пресетов. |
| `orderBy` | string | Нет | `NAME` (по умолчанию), `CREATED` или `UPDATED`. |
| `orderDirection` | string | Нет | `ASC` (по умолчанию) или `DESC`. |
| `page` | integer | Нет | Индекс страницы, начиная с нуля. |
| `perPage` | integer | Нет | Размер страницы. По умолчанию `100`, если опущено или `0`. |
| `searchByName` | string | Нет | Поиск подстроки без учета регистра в названии **или** коде пресета (`ILIKE %value%`). |
| `searchByCategory` | array of strings | Нет | Повторите параметр для фильтрации по нескольким категориям, например, `?searchByCategory=promo&searchByCategory=lifecycle`. |
| `showHidden` | boolean | Нет | Включить пресеты, помеченные как `hidden`. |

<Aside type="note">
`isDefault` — это устаревший фильтр, сохраненный только для старой формы отправки push-уведомлений в Панели управления — не полагайтесь на него.
</Aside>

### Ответ

Каждый элемент содержит только: `name`, `code`, `platforms`, `localized_content` (простой текст для каждого языка — **не** `localized_properties`), `localized_title`, `localized_subtitle`, `banner`, `icon`, `categories`, `journey_uuid`, `custom_data`, `is_v2`, `created`, `updated`. Все остальные поля [объекта Preset](#preset-object) — `localized_properties`, `platform_properties`, `deeplink`, `richmedia`, `url` и т.д. — опускаются, даже если они установлены в пресете.

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `presets` | array of objects | Текущая страница пресетов в сокращенном виде, описанном выше. |
| `page` | integer | Возвращенный индекс страницы. |
| `per_page` | integer | Размер страницы, использованный для этого ответа. |
| `total` | integer | Общее количество пресетов, соответствующих фильтрам, на всех страницах. |

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

```json
{
  "presets": [
    { "name": "20% discount", "code": "AAAAA-BBBBB", "platforms": { "1": true, "3": true }, "categories": ["promo"] }
  ],
  "page": 0,
  "per_page": 100,
  "total": 1
}
```

## Получить

Возвращает один пресет push-уведомлений по его коду со всеми заполненными полями [объекта Preset](#preset-object).

`GET` `/api/presets/{code}`

### Параметры пути

| Параметр | Тип | Описание |
| :---- | :---- | :---- |
| `code` | string | Код пресета. |

### Ответ

Возвращает `{ "preset": { ... } }`, полный [объект Preset](#preset-object).

## Обновить

Перезаписывает существующий пресет push-уведомлений по коду предоставленными полями.

`PUT` `/api/presets/{code}`

### Параметры пути

| Параметр | Тип | Описание |
| :---- | :---- | :---- |
| `code` | string | Код пресета для перезаписи. |

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

Те же поля, что и в [Create](#create) (минус `application`), плюс остальные поля [объекта Preset](#preset-object). `sendType` принимается, но игнорируется — канал пресета нельзя изменить после создания.

<Aside type="caution" title="Пропуск поля не всегда означает 'оставить без изменений'">
`Update` перестраивает свойства контента пресета с нуля при каждом вызове: `localizedProperties`, `platformProperties`, `openAction`/`openActions`, `deeplink`, `deeplinkParams`, `richmedia`, `url`, `campaignCode`, `filterCode`, `geoZones`, `sendRate`, `cappingCount`/`cappingDays`, три поля `notification*Url`, `remotePage`, `wnsContent`, `originalUrl`, четыре флага `*Silent`, `inboxImage`/`inboxIcon`/`inboxDays`/`inboxDate`, `banner`, `icon`, `customData` и `isV2` — если опустить любое из них, оно будет очищено (или, в случае `isV2`, сброшено на `true`).

`name`, `platforms`, `categories`, `localizedTitle`, `localizedSubtitle` и `localizedContent` являются исключением: каждое из них затрагивается только при отправке и остается без изменений, если опущено.

Используйте [UpdatePartial](#updatepartial), если вы хотите, чтобы первая группа также оставалась без изменений при пропуске.
</Aside>

<Aside type="caution" title="Ответ не содержит поля preset">
`Update` возвращает `{}` — пустой объект. Сообщение ответа технически определяет поле `preset`, но сервер никогда его не заполняет. Вызовите `Get` после, если вам нужен обновленный объект.
</Aside>

### Ответ

Пустой объект в случае успеха: `{}`.

## Частичное обновление

Обновляет только предоставленные поля существующего пресета push-уведомлений по коду, оставляя неустановленные поля без изменений.

`PUT` `/api/presets/{code}:partial`

### Параметры пути

| Параметр | Тип | Описание |
| :---- | :---- | :---- |
| `code` | string | Код пресета для частичного обновления. |

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

Те же поля, что и в [Update](#update), минус `application`. В отличие от `Update`, здесь каждое поле — включая `localizedProperties`, `platformProperties`, `categories` и остальные поля группы свойств контента, перечисленные в [предупреждении Update](#update) — остается без изменений, если опущено, и затрагивается только при отправке (поле типа map/array, которое вы отправляете, все равно полностью заменяет существующее значение для этого поля, но не влияет на то, что вы не включили). `sendType` также принимается, но игнорируется.

<Aside type="note">
`isV2` является единственным исключением даже здесь: он перезаписывается при каждом вызове `UpdatePartial`, по умолчанию становясь `true`, если опущен. Отправляйте `isV2: false` явно, если пресет должен оставаться в стиле v1.
</Aside>

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

```json
{
  "sendRate": 500,
  "cappingCount": 3,
  "cappingDays": 7
}
```

### Ответ

Также пустой объект — см. [предупреждение выше](#update).

## Клонировать

Дублирует существующий пресет push-уведомлений под новым именем в **то же** приложение.

`POST` `/api/presets/{code}:clone`

<Aside type="note">
В отличие от `Clone` в API Email Templates, этот эндпоинт не имеет параметра `application` — он всегда клонирует в пределах собственного приложения исходного пресета. Клон всегда создается с `hidden: false`, независимо от источника.
</Aside>

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

| Параметр | Тип | Обязательный | Описание |
| :---- | :---- | :---- | :---- |
| `code` | string | Да | Код исходного пресета для дублирования. |
| `name` | string | Да | Название для нового пресета. |

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

```json
{ "code": "AAAAA-BBBBB", "name": "20% discount (copy)" }
```

### Ответ

Возвращает `{ "preset": { ... } }`, новый [объект Preset](#preset-object).

## Удалить

Безвозвратно удаляет пресет push-уведомлений по коду.

`DELETE` `/api/presets/{code}`

<Aside type="caution">
Не удастся, если пресет все еще используется точкой `send_push` в запущенном или приостановленном journey — сначала удалите его из journey. Это действие нельзя отменить.
</Aside>

### Параметры пути

| Параметр | Тип | Описание |
| :---- | :---- | :---- |
| `code` | string | Код пресета для удаления. |

### Ответ

Пустой объект в случае успеха: `{}`.

## Справочник по объектам

Имена полей ниже соответствуют тому, что фактически возвращают `Get`, `Create`, `Update` и `Clone` — имена полей proto в `snake_case` (см. [Соглашения](#conventions)). Форма `lowerCamelCase`, используемая в примерах запросов выше, работает так же на входе.

### Объект Preset

#### Идентификация

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `code` | string | Генерируется при `Create`. Идентифицирует этот пресет во всем остальном API. |
| `name` | string | Название пресета. |
| `send_type` | string | Канал пресета (например, `push`). |
| `is_v2` | boolean | `true` для пресетов, созданных или перенесенных на модель контента v2. |
| `system` | boolean | Помечает пресет как системный/внутренний. |
| `hidden` | boolean | Скрывает пресет из результатов `List` (отправьте `showHidden: true`, чтобы включить его). |
| `created` | string (RFC 3339) | Временная метка создания. |
| `updated` | string (RFC 3339) | Временная метка последнего обновления. |

#### Таргетинг и контент

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `platforms` | map&lt;string, boolean&gt; | На какие платформы нацелен пресет, ключи — [код типа устройства](/ru/developer/api-reference/api-identifiers/#device-type) (например, `"1"` для iOS). |
| `localized_properties` | map&lt;string, object&gt; | Локаль → rich-контент для каждой платформы. Та же структура, что и у [`LocalizedContent`](/ru/developer/api-reference/messaging-api-v2/payload-reference/#localizedcontent) в полезной нагрузке `Notify` — одна запись на блок платформы (`ios`, `android` и т.д.). Это основной способ установки контента push-уведомлений для конкретной платформы. |
| `localized_title` / `localized_subtitle` / `localized_content` | map&lt;string, string&gt; | Локаль → простой текст. Более простая альтернатива `localized_properties` для заголовка, подзаголовка и тела, когда вам не нужны переопределения для каждой платформы. |
| `platform_properties` | map&lt;string, object&gt; | Устаревшие переопределения для каждой платформы, ключи — имя enum платформы (`IOS`, `ANDROID`, `HUAWEI_ANDROID`, `OSX`). См. [объект PlatformProperties](#platformproperties-object) ниже. |
| `open_action` | [`OpenAction`](/ru/developer/api-reference/messaging-api-v2/payload-reference/#openaction) | Действие, срабатывающее, когда пользователь открывает уведомление, применяется ко всем платформам. Взаимоисключаемо с `open_actions` — ответ устанавливает ровно одно из них. |
| `open_actions` | map&lt;string, `OpenAction`&gt; | Переопределение `open_action` для каждой платформы, ключи — [код типа устройства](/ru/developer/api-reference/api-identifiers/#device-type). |
| `deeplink` | string | Код [Deep Link](/ru/developer/guides/messaging-channels/deep-linking/). |
| `deeplink_params` | map&lt;string, string&gt; | Параметры, передаваемые в deep link. |
| `richmedia` | string | Код [Rich Media](/ru/product/content/rich-media/), открываемого уведомлением. |
| `url` | string | URL, открываемый уведомлением, если не используется deep link или Rich Media. |

#### Входящие

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `inbox_image` | string | URL изображения, отображаемого в записи [Message Inbox](/ru/developer/guides/message-inbox/mobile-message-inbox/). |
| `inbox_icon` | string | URL иконки, отображаемой в записи Message Inbox. |
| `inbox_days` | integer | Количество дней, в течение которых запись остается в Message Inbox. |
| `inbox_date` | string (RFC 3339) | Явная дата истечения срока действия для записи в Message Inbox, как альтернатива `inbox_days`. |

#### Организация и метаданные

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `categories` | array of strings | Названия категорий, которыми помечен пресет. |
| `campaign_code` | string | [Код кампании](/ru/developer/api-reference/api-identifiers/#campaign-code), к которой относится этот пресет. |
| `filter_code` | string | [Код сегмента / фильтра](/ru/developer/api-reference/api-identifiers/#segment--filter-code), на который по умолчанию нацелен этот пресет. |
| `geo_zones` | string | Таргетинг по [геозонам](/ru/developer/api-reference/geozones/), если пресет запускается по геолокации. |
| `journey_uuid` | string | UUID Customer Journey, которому принадлежит этот пресет, если он был создан из точки Send push в journey. |
| `custom_data` | object | Произвольный JSON, пересылаемый в SDK клиента как параметр `u`. |
| `banner` | string | URL большого изображения / вложения. |
| `icon` | string | URL пользовательской иконки уведомления. |

#### Ограничения доставки

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `send_rate` | integer | Ограничение скорости для отправок с использованием этого пресета, в сообщениях/секунду — эквивалент [`SendRate`](/ru/developer/api-reference/messaging-api-v2/notify/#sendrate) из `Notify` на уровне пресета. |
| `capping_count` / `capping_days` | integer | Ограничение частоты на пользователя для этого пресета — эквивалент `count` / `days` из [`FrequencyCapping`](/ru/developer/api-reference/messaging-api-v2/notify/#frequencycapping) из `Notify` на уровне пресета. |

#### Веб-хуки

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `notification_sent_url` | string | URL обратного вызова, запрашиваемый при отправке уведомления с использованием этого пресета. |
| `notification_delivered_url` | string | URL обратного вызова, запрашиваемый при доставке уведомления с использованием этого пресета. |
| `notification_click_url` | string | URL обратного вызова, запрашиваемый при клике на уведомление с использованием этого пресета. |

#### Устаревшие поля

Эти поля перенесены из модели пресетов v1. Они заполняются для совместимости с Панелью управления, а не для новых интеграций.

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `remote_page` | string | Устаревшая ссылка на удаленную страницу. |
| `wns_content` | string | Устаревший JSON шаблона всплывающего уведомления Windows, как он принимался методами v1 `createPreset`/`getPreset`. |
| `original_url` | string | Значение `url` до сокращения, когда `url` был заменен сокращенной ссылкой. |
| `ios_silent` / `android_silent` / `huawei_android_silent` | boolean | Флаги тихого (только с данными) push-уведомления для каждой платформы. |

### Объект PlatformProperties

Поля, доступные в каждой записи `platform_properties` (`IOS`, `ANDROID`, `HUAWEI_ANDROID`, `OSX`):

| Поле | Тип | Описание |
| :---- | :---- | :---- |
| `badge` | string | Переопределение количества на значке. |
| `sound` | string | Имя звукового файла. |
| `sound_off` | boolean | Отключить звук уведомления. |
| `priority` | string | Приоритет в трее (только для Android/Huawei). |
| `delivery_priority` | string | Приоритет доставки `NORMAL` или `HIGH` (только для Android/Huawei). |
| `ios_interruption_level` | string | `passive`, `active`, `time-sensitive` или `critical` (только для iOS). |

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

<CardGrid>
  <LinkCard title="Notify" href="/ru/developer/api-reference/messaging-api-v2/notify/" />
  <LinkCard title="Справочник по полезной нагрузке" href="/ru/developer/api-reference/messaging-api-v2/payload-reference/" />
  <LinkCard title="Справочник по точкам Customer Journey" href="/ru/developer/api-reference/customer-journey-api/point-reference/#messaging-points" />
</CardGrid>