Общая схема взаимодействия
После отправки формы посетителем сайта Tilda выполняет HTTP-запрос на URL, указанный разработчиком интеграции в шаблоне в поле Эндпоинт интеграции.
- метод запроса:
POST; - формат тела:
application/json; - при сохранении endpoint и OAuth-адресов проверяется до пяти редиректов в пределах разрешённого домена; при отправке заявки этот лимит не гарантируется;
- доставка асинхронная и может выполняться повторно в случае неполучения успешного ответа;
- endpoint должен быть доступен по публичному HTTPS-адресу.
Авторизация
Способ авторизации настраивается при создании интеграции.
| Тип | Что делает пользователь | Как Tilda авторизует запрос |
|---|---|---|
| API key в заголовке | Вводит ключ | Настраиваемый HTTP-заголовок |
| API key в теле | Вводит ключ | Дополнительное поле JSON |
| OAuth 2.0 | Подтверждает доступ в приложении | Authorization: Bearer <access_token> |
Для OAuth 2.0 поддерживается только схема Bearer.
2.1. Авторизация по API key
Разработчик задаёт имя параметра API key (например, X-API-Key). Пользователь вводит значение ключа при подключении.
Тип авторизации API key, метод HEADER
X-API-Key: user-api-key
{
"Name": "Иван Иванов",
"tranid": "1111111:6161583731"
} Тип авторизации API key, метод POST
{
"Name": "Иван Иванов",
"tranid": "1111111:6161583731",
"X-API-Key": "user-api-key"
} Если ключ отсутствует, недействителен или отозван, приложение должно вернуть ошибку в формате. Все поля обязательны:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
{
"status": "error",
"error": {
"code": "invalid_api_key",
"message": "API key is missing, invalid or revoked"
}
} Для действительного ключа без необходимых прав следует вернуть 403 Forbidden с кодом ошибки:
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
{
"status": "error",
"error": {
"code": "insufficient_permissions",
"message": "API key does not have permission to create leads"
}
} 2.2. Подключение по OAuth
- Tilda добавляет необходимые OAuth-параметры к URL авторизации и перенаправляет пользователя в приложение.
- Пользователь авторизуется в приложении, если требуется, и подтверждает предоставление доступа.
- Приложение перенаправляет пользователя на callback Tilda, переданный в параметре
redirect_uri. В URL перенаправления передаютсяauthorization code, исходныйstate, а также параметрыprojectid,typeиclient_id. - Tilda обменивает
authorization codeнаaccess_tokenиrefresh_token. - После подключения Tilda перенаправляет пользователя на страницу настройки интеграции.
URL авторизации
Tilda добавляет следующие GET-параметры. После авторизации приложение должно вернуть их на callback без изменений, кроме redirect_uri:
| Параметр | Описание |
|---|---|
projectid | ID проекта Tilda |
type | Тип интеграции с префиксом ci.; возвращайте без изменений |
client_id | ID OAuth-приложения |
state | Одноразовое значение OAuth-сессии |
redirect_uri | Callback URL Tilda |
account_id | Аккаунт пользователя в приложении; при необходимости добавляется на callback |
template_id | ID шаблона приложения, если передан отдельно; идентификатор шаблона также содержится в state |
После подтверждения доступа приложение должно перенаправить пользователя на полученный redirect_uri. Параметры projectid, type, client_id и state возвращаются без изменений; дополнительно передаётся code и, если есть, account_id. Не собирайте state самостоятельно: callback требует templateId внутри него.
Callback проверяет одноразовую метку и требует templateId в конце state. Не собирайте state самостоятельно — иначе обмен кода на токены не пройдёт.
Location: https://tilda.ru/projects/forms/oauth/marketplace/?code=authorization-code&client_id=app-123&state=3333333%3A%3Aci.app_123544%3A%3Atest%3A%3AtemplateId%3D35&type=ci.app_123544&projectid=3333333&account_id=accid12312331 Пример redirect_uri (используйте фактическое значение из запроса):
https://www.tilda.cc/projects/forms/oauth/marketplace/ После авторизации приложение перенаправляет пользователя на полученный redirect_uri:
HTTP/1.1 302 Found
Location: https://tilda.ru/projects/forms/oauth/marketplace/?code=authorization-code&client_id=app-123&state=3333333%3A%3Aci.app_123544%3A%3Atest%3A%3AtemplateId%3D35&type=ci.app_123544&projectid=3333333&account_id=accid12312331 Обмен code на токены
Tilda обменивает code через настроенный tokenEndpoint:
POST /oauth/access_token HTTP/1.1
Host: integration.example.com
Content-Type: application/json
{
"code": "authorization-code",
"grant_type": "authorization_code",
"client_id": "app-123",
"client_secret": "app-secret"
} Ожидаемый ответ:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"access_token": "access-token",
"refresh_token": "refresh-token",
"expires": 1786723200
} expires — Unix timestamp окончания действия access token.
Для обновления токена Tilda отправляет JSON на настроенный refreshTokenEndpoint через POST:
{
"refresh_token": "refresh-token",
"grant_type": "refresh_token",
"client_id": "app-123",
"client_secret": "app-secret"
} В ответе нужны непустые access_token и refresh_token; expires — Unix timestamp.
Ошибки token endpoint
При ошибке token endpoint должен вернуть подходящий HTTP-код и JSON с полями title и, при наличии, detail:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
{
"title": "invalid_grant",
"detail": "Authorization code is invalid, expired or already used"
} | HTTP-код | title | Когда возвращать |
|---|---|---|
400 Bad Request | invalid_request | В запросе нет обязательного параметра или его формат неверен |
400 Bad Request | invalid_grant | Authorization code или refresh token недействителен, истёк, отозван или уже использован |
401 Unauthorized | invalid_client | client_id или client_secret неверен |
403 Forbidden | access_denied | Владелец ресурса отклонил доступ или клиенту недостаточно прав |
429 Too Many Requests | rate_limit_exceeded | Превышен лимит запросов |
500 Internal Server Error | server_error | Внутренняя ошибка приложения |
503 Service Unavailable | temporarily_unavailable | Приложение временно недоступно |
При отправке запросов access token передаётся так:
Authorization: Bearer access-token Другие OAuth-схемы сейчас не поддерживаются. Для истёкшего или отозванного токена приложение должно вернуть 401 Unauthorized:
{
"status": "error",
"error": {
"code": "invalid_token",
"message": "Access token is missing, invalid or revoked"
}
} Callback проверяет одноразовую метку и требует templateId в конце state. При 401 или invalid_token в ответе endpoint заявки Tilda пытается обновить токен через refreshTokenEndpoint и повторить отправку; успех обновления не гарантируется.
Тестовый запрос
Тест отправляет запрос на endpoint приёма данных, указанный в шаблоне интеграции, и проверяет настроенный способ авторизации.
POST /api/tilda/leads HTTP/1.1
Host: integration.example.com
Content-Type: application/json
X-API-Key: user-api-key
{
"test": "test"
} Endpoint должен вернуть 200 OK или 201 Created, в обоих случаях с непустым телом:
{
"status": "success"
} Максимальное время ожидания — 5 секунд.
Формат передачи данных
Тело запроса содержит заполненные посетителем сайта поля формы, системные поля Тильды и, если они заданы, параметры подключения, выбранные пользователем интеграции, в объекте fields.
Пользовательские поля — это поля, задаваемые в блоке «Поля для ввода». Пользователь может заполнить их при подключении интеграции.
POST /api/tilda/leads HTTP/1.1
Host: integration.example.com
Content-Type: application/json
Authorization: Bearer access-token
{
"Name": "Иван Иванов",
"Email": "ivan@example.com",
"Phone": "+79990000000",
"Comments": "Прошу связаться",
"tranid": "1111111:6161583731",
"formid": "form731613459",
"formname": "Обратная связь",
"fields": {
"pipeline_id": "42"
}
} | Поле | Тип | Описание |
|---|---|---|
tranid | string | ID обращения без оплаты; при наличии оплаты не гарантируется |
formid | string | ID формы |
formname | string | Название формы, если задано |
fields | object | Сохранённые пользовательские параметры подключения, если они заданы; OAuth-токен сюда не входит |
В запросе могут присутствовать дополнительные поля, включая данные заказа и оплаты. Неизвестные поля следует игнорировать.
tranid, если он есть, следует воспринимать как непрозрачную строку;- повторный запрос с тем же
tranidне должен создавать дубликат; для заявок безtranidзащиту от дубликатов предусмотрите отдельно; - для уже обработанного обращения нужно снова вернуть успешный ответ;
- максимальное время ожидания ответа — 20 секунд.
Для кастомных интеграций Content-Type всегда application/json, в том числе при передаче товаров не массивом.
Успешные ответы
Для нового объекта рекомендуется вернуть 201 Created:
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
{
"status": "success",
"result": {
"id": "lead-7854",
"tranid": "1111111:6161583731"
}
} Для уже обработанного tranid можно вернуть 200 OK:
{
"status": "success",
"result": {
"id": "lead-7854",
"tranid": "1111111:6161583731",
"duplicate": true
}
} При обычной отправке 200 требует непустого тела. 201 считается успехом и с пустым телом, но JSON рекомендуется. Другие 2xx, включая 202 и 204, не считаются успешной доставкой.
Как Tilda интерпретирует ответ
| Результат | Поведение Tilda |
|---|---|
200 и непустое тело | Успех |
201 | Успех |
200 с пустым телом | Ошибка, запрос будет повторён |
400, 409, 422 | Повторная доставка не выполняется |
401 или тело с invalid_token при OAuth | Попытка обновить токен и повторить отправку; при неудаче задача откладывается |
Остальные 4xx | Возможны повторы с увеличивающимся интервалом |
5xx, сетевой сбой или тайм-аут | Повторы с увеличивающимся интервалом |
| Другой итоговый код | Не считается успехом |
После серии ошибок подключение может быть автоматически приостановлено.
Ошибки
Эти ошибки разработчик может увидеть при сохранении, подключении или тестировании интеграции. Они не являются ответами на отправку заявок.
7.1. Подключение и тестирование
{
"status": "error",
"description": "This integration does not support OAuth"
} Ожидаемая ошибка может иметь HTTP-статус 200, поэтому нужно проверять status.
Возможные причины:
- некорректный проект, тип интеграции или ID подключения;
- интеграция или шаблон не найдены;
- достигнут лимит подключений;
- обязательные параметры не заполнены;
- OAuth не поддерживается;
- некорректны
client_id, code,stateили callback; - token endpoint недоступен или вернул некорректный ответ;
- в token response нет
access_tokenилиrefresh_token; - endpoint имеет неверный URL, недоступен или превысил тайм-аут;
- тест вернул ошибочный HTTP-код или пустое тело.
| Ответ тестового endpoint | Ошибка Tilda |
|---|---|
400 | Некорректный запрос |
401, 403 | Доступ запрещён |
404 | URL не найден |
405 | Метод POST не поддерживается |
409, 5xx, сетевой сбой | Endpoint недоступен |
200 или 201 с пустым телом | Пустой ответ |
7.2. Сохранение приложения разработчика
{
"status": "error",
"error": "duplicate_app_code"
} error | Описание |
|---|---|
wrong_template_id | Шаблон не найден |
auth_code_change_forbidden | Нельзя изменить код приложения |
major_changes_not_allowed | Требуется новая версия |
same_version | Версия совпадает с текущей |
draft_template_already_exists | Уже существует черновик |
max_applications_reached | Достигнут лимит приложений |
duplicate_app_code | Такой код уже существует |
status_is_not_allowed | Переход статуса запрещён |
integration_domain_mismatch | URL относятся к разным или запрещённым доменам |
integration_redirect_domain_mismatch | Редирект ведёт на другой домен |
integration_url_check_failed | URL не удалось проверить |
integration_too_many_redirects | Больше пяти редиректов |
Ошибка валидации повторяет структуру запроса:
{
"status": "error",
"error": {
"appSettings": {
"nameRU": "required"
},
"config": {
"endpoint": "invalid_format"
}
}
} Основные коды: required, invalid_format, invalid, must_be_array, must_be_object.
Динамические поля
При подключении интеграции пользователь может заполнить поля input, checkbox и select. Для select с типом списка dynamic разработчик задаёт URL endpoint вариантов и необязательный path к массиву в JSON-ответе.
Tilda отправляет GET без тела с заголовком Accept: application/json. При OAuth передаётся Authorization: Bearer <access_token>, при API key с методом HEADER — настроенный заголовок. При API key с методом POST ключ для запроса вариантов передаётся в query-параметре URL, а не в теле; учитывайте риск записи ключа в логах URL. Рекомендуем HTTPS.
Ответьте кодом 2xx и корректным JSON. Если path пуст, весь ответ должен быть массивом вариантов; иначе Tilda извлекает массив по вложенным ключам через точку, например data.options. Каждый вариант для интерфейса должен содержать value и label (не id и name):
[
{
"value": "1",
"label": "Вариант 1"
},
{
"value": "Ivanov",
"label": "Вариант 2"
}
] Сервер Tilda проверяет, что результат по path — массив, но не проверяет наличие value/label у каждого элемента: это требование интерфейса, без него варианты не отобразятся корректно. Невалидный JSON, отсутствие массива или код вне 2xx приводят к ошибке загрузки. При 401 для OAuth Tilda один раз пытается обновить токен и повторить GET.
При сохранении интеграции URL динамического поля проверяется: допускаются HTTP(S)-адреса в разрешённом домене, localhost и IP-адреса запрещены. В отличие от endpoint заявки и OAuth-адресов, цепочка редиректов для динамического поля при сохранении не проверяется; при GET редиректы не выполняются. TLS-сертификат проверяется, тайм-аут соединения и всего запроса — по 20 секунд. Endpoint должен отвечать напрямую.
