Техническое описание для разработчиков интеграций
01

Общая схема взаимодействия

После отправки формы посетителем сайта Tilda выполняет HTTP-запрос на URL, указанный разработчиком интеграции в шаблоне в поле Эндпоинт интеграции.

  • метод запроса: POST;
  • формат тела: application/json;
  • при сохранении endpoint и OAuth-адресов проверяется до пяти редиректов в пределах разрешённого домена; при отправке заявки этот лимит не гарантируется;
  • доставка асинхронная и может выполняться повторно в случае неполучения успешного ответа;
  • endpoint должен быть доступен по публичному HTTPS-адресу.
02

Авторизация

Способ авторизации настраивается при создании интеграции.

ТипЧто делает пользовательКак 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

HTTP Запрос
X-API-Key: user-api-key
{
  "Name": "Иван Иванов",
  "tranid": "1111111:6161583731"
}

Тип авторизации API key, метод POST

JSON Тело запроса
{
  "Name": "Иван Иванов",
  "tranid": "1111111:6161583731",
  "X-API-Key": "user-api-key"
}

Если ключ отсутствует, недействителен или отозван, приложение должно вернуть ошибку в формате. Все поля обязательны:

401 Unauthorized
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 с кодом ошибки:

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

  1. Tilda добавляет необходимые OAuth-параметры к URL авторизации и перенаправляет пользователя в приложение.
  2. Пользователь авторизуется в приложении, если требуется, и подтверждает предоставление доступа.
  3. Приложение перенаправляет пользователя на callback Tilda, переданный в параметре redirect_uri. В URL перенаправления передаются authorization code, исходный state, а также параметры projectid, type и client_id.
  4. Tilda обменивает authorization code на access_token и refresh_token.
  5. После подключения Tilda перенаправляет пользователя на страницу настройки интеграции.

URL авторизации

Tilda добавляет следующие GET-параметры. После авторизации приложение должно вернуть их на callback без изменений, кроме redirect_uri:

ПараметрОписание
projectidID проекта Tilda
typeТип интеграции с префиксом ci.; возвращайте без изменений
client_idID OAuth-приложения
stateОдноразовое значение OAuth-сессии
redirect_uriCallback URL Tilda
account_idАккаунт пользователя в приложении; при необходимости добавляется на callback
template_idID шаблона приложения, если передан отдельно; идентификатор шаблона также содержится в state

После подтверждения доступа приложение должно перенаправить пользователя на полученный redirect_uri. Параметры projectid, type, client_id и state возвращаются без изменений; дополнительно передаётся code и, если есть, account_id. Не собирайте state самостоятельно: callback требует templateId внутри него.

Callback и state

Callback проверяет одноразовую метку и требует templateId в конце state. Не собирайте state самостоятельно — иначе обмен кода на токены не пройдёт.

HTTP Редирект после авторизации
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 (используйте фактическое значение из запроса):

URL Callback URL
https://www.tilda.cc/projects/forms/oauth/marketplace/

После авторизации приложение перенаправляет пользователя на полученный redirect_uri:

HTTP 302 Found
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:

JSON Запрос токенов
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"
}

Ожидаемый ответ:

200 OK
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:

JSON Запрос refresh
{
  "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:

400 Bad Request
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 Requestinvalid_requestВ запросе нет обязательного параметра или его формат неверен
400 Bad Requestinvalid_grantAuthorization code или refresh token недействителен, истёк, отозван или уже использован
401 Unauthorizedinvalid_clientclient_id или client_secret неверен
403 Forbiddenaccess_deniedВладелец ресурса отклонил доступ или клиенту недостаточно прав
429 Too Many Requestsrate_limit_exceededПревышен лимит запросов
500 Internal Server Errorserver_errorВнутренняя ошибка приложения
503 Service Unavailabletemporarily_unavailableПриложение временно недоступно

При отправке запросов access token передаётся так:

HTTP Authorization header
Authorization: Bearer access-token

Другие OAuth-схемы сейчас не поддерживаются. Для истёкшего или отозванного токена приложение должно вернуть 401 Unauthorized:

401 invalid_token
{
  "status": "error",
  "error": {
    "code": "invalid_token",
    "message": "Access token is missing, invalid or revoked"
  }
}
Ограничения текущей OAuth-реализации

Callback проверяет одноразовую метку и требует templateId в конце state. При 401 или invalid_token в ответе endpoint заявки Tilda пытается обновить токен через refreshTokenEndpoint и повторить отправку; успех обновления не гарантируется.

03

Тестовый запрос

Тест отправляет запрос на endpoint приёма данных, указанный в шаблоне интеграции, и проверяет настроенный способ авторизации.

HTTP Тестовый POST
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, в обоих случаях с непустым телом:

2xx Успешный ответ
{
  "status": "success"
}

Максимальное время ожидания — 5 секунд.

04

Формат передачи данных

Тело запроса содержит заполненные посетителем сайта поля формы, системные поля Тильды и, если они заданы, параметры подключения, выбранные пользователем интеграции, в объекте fields.

Пользовательские поля — это поля, задаваемые в блоке «Поля для ввода». Пользователь может заполнить их при подключении интеграции.

JSON Полный пример запроса
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"
  }
}
ПолеТипОписание
tranidstringID обращения без оплаты; при наличии оплаты не гарантируется
formidstringID формы
formnamestringНазвание формы, если задано
fieldsobjectСохранённые пользовательские параметры подключения, если они заданы; OAuth-токен сюда не входит

В запросе могут присутствовать дополнительные поля, включая данные заказа и оплаты. Неизвестные поля следует игнорировать.

  • tranid, если он есть, следует воспринимать как непрозрачную строку;
  • повторный запрос с тем же tranid не должен создавать дубликат; для заявок без tranid защиту от дубликатов предусмотрите отдельно;
  • для уже обработанного обращения нужно снова вернуть успешный ответ;
  • максимальное время ожидания ответа — 20 секунд.

Для кастомных интеграций Content-Type всегда application/json, в том числе при передаче товаров не массивом.

05

Успешные ответы

Для нового объекта рекомендуется вернуть 201 Created:

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:

200 OK (идемпотентно)
{
  "status": "success",
  "result": {
    "id": "lead-7854",
    "tranid": "1111111:6161583731",
    "duplicate": true
  }
}

При обычной отправке 200 требует непустого тела. 201 считается успехом и с пустым телом, но JSON рекомендуется. Другие 2xx, включая 202 и 204, не считаются успешной доставкой.

06

Как Tilda интерпретирует ответ

РезультатПоведение Tilda
200 и непустое телоУспех
201Успех
200 с пустым теломОшибка, запрос будет повторён
400, 409, 422Повторная доставка не выполняется
401 или тело с invalid_token при OAuthПопытка обновить токен и повторить отправку; при неудаче задача откладывается
Остальные 4xxВозможны повторы с увеличивающимся интервалом
5xx, сетевой сбой или тайм-аутПовторы с увеличивающимся интервалом
Другой итоговый кодНе считается успехом

После серии ошибок подключение может быть автоматически приостановлено.

07

Ошибки

Эти ошибки разработчик может увидеть при сохранении, подключении или тестировании интеграции. Они не являются ответами на отправку заявок.

7.1. Подключение и тестирование

JSON Формат ошибки
{
  "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Доступ запрещён
404URL не найден
405Метод POST не поддерживается
409, 5xx, сетевой сбойEndpoint недоступен
200 или 201 с пустым теломПустой ответ

7.2. Сохранение приложения разработчика

ERR duplicate_app_code
{
  "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_mismatchURL относятся к разным или запрещённым доменам
integration_redirect_domain_mismatchРедирект ведёт на другой домен
integration_url_check_failedURL не удалось проверить
integration_too_many_redirectsБольше пяти редиректов

Ошибка валидации повторяет структуру запроса:

JSON Валидация
{
  "status": "error",
  "error": {
    "appSettings": {
      "nameRU": "required"
    },
    "config": {
      "endpoint": "invalid_format"
    }
  }
}

Основные коды: required, invalid_format, invalid, must_be_array, must_be_object.

08

Динамические поля

При подключении интеграции пользователь может заполнить поля 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):

JSON Варианты для select
[
  {
    "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 должен отвечать напрямую.

Made on
Tilda