Разработка · 6 мин чтения

API СДЭК: где взять ключи доступа и настроить вебхуки

Когда клиент просит подключить доставку СДЭК к сайту, боту или CRM, разговор всегда упирается в один и тот же вопрос: API СДЭК, где взять ключи доступа и как их не перепутать с логином от личного кабинета. На практике путаница возникает из-за того, что у СДЭК два разных контура с разными ключами, а вебхуки настраиваются не в интерфейсе, а отдельным запросом к API. Разберу по шагам, где искать client_id и client_secret, как получить токен и как подписаться на события по заказу, чтобы статусы доставки прилетали в CRM или Telegram-бот сами, без ручной проверки трек-номеров.

Где взять ключи API СДЭК: аккаунт и личный кабинет

Ключи выдаются не сразу после регистрации на сайте cdek.ru, а через отдельный личный кабинет интеграции на lk.cdek.ru. Обычному клиенту, который просто отправляет посылки через форму, эти ключи не нужны, они появляются только у тех, кто подключает СДЭК как способ доставки к своей системе.

Порядок такой:

  • Регистрируетесь как юрлицо или ИП в личном кабинете СДЭК, заключаете договор на доставку (без действующего договора боевой доступ не откроют).
  • В разделе «Интеграция» находите пункт «API» или пишете на integration@cdek.ru с просьбой выдать доступ к API v2.
  • Получаете пару account_id (он же client_id) и secure_password (client_secret) для тестового контура, обычно это происходит в течение одного рабочего дня.
  • Для боевого контура нужно отдельно запросить продакшн-ключи, приложив реквизиты и номер договора, ждать 1-3 рабочих дня.

Важный момент: client_secret показывается в кабинете один раз, дальше его можно только перевыпустить. Я всегда сразу кладу его в переменные окружения проекта (.env), а не в код, потому что это фактически пароль от вашего аккаунта в API.

Тестовый и боевой контур: чем отличаются ключи доступа

СДЭК держит две независимые площадки: тестовую (её ещё называют sandbox или интеграционной) и боевую. У них разные адреса, разные ключи и разные ограничения, и это первое, о чём забывают при переносе интеграции в продакшн.

Параметр Тестовый контур Боевой контур
Базовый URL API api.edu.cdek.ru/v2 api.cdek.ru/v2
Как получить ключи По заявке, обычно за 1 день Нужен действующий договор, 1-3 дня
Реальная отправка заказов Нет, все заказы виртуальные Да, создаются настоящие накладные
Вебхуки Работают, можно тестировать все типы событий Работают, события приходят по реальным заказам

Я всегда пишу и отлаживаю интеграцию на тестовом контуре целиком, включая вебхуки, и только потом меняю базовый URL и пару ключей на боевые. Логика запросов у обоих контуров идентична, отличаются только адрес и учётка, так что после отладки достаточно поменять две переменные в конфиге.

Бесплатный материал

🎁 Полезный скрипт в подарок

Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.

Без спама. Отписка в 1 клик.

Получение токена и первый запрос к API СДЭК

Авторизация в API СДЭК v2 идёт по протоколу OAuth 2.0, схема client_credentials. Никакого логина и пароля от личного кабинета в запросах не участвует, только client_id и client_secret.

Запрос токена выглядит так:

curl -X POST 'https://api.edu.cdek.ru/v2/oauth/token?parameters' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials&client_id=ВАШ_ACCOUNT_ID&client_secret=ВАШ_SECRET'

В ответ приходит access_token, тип bearer и срок жизни в секундах, обычно 3600. То есть токен нужно кэшировать и обновлять раз в час, а не запрашивать перед каждым вызовом API, СДЭК банит за избыточные запросы к оутентификации при высокой частоте.

Дальше токен передаётся в заголовке к любому методу, например при создании заказа или запросе стоимости доставки:

curl -X GET 'https://api.edu.cdek.ru/v2/orders/72753294-70e6-4160-9f38-9c72a1e0b8ba' \
  -H 'Authorization: Bearer ВАШ_ACCESS_TOKEN'

Одна из частых ошибок на этом шаге, путать account_id с числовым идентификатором из старого API v1, у СДЭК до сих пор встречаются примеры кода в интернете под старую версию, а v1 отключена.

Настройка вебхуков СДЭК: типы событий, подписка и защита обработчика

Вебхуки в API СДЭК не включаются переключателем в интерфейсе, их регистрируют отдельным POST-запросом, указывая свой адрес обработчика и типы событий, на которые хотите подписаться.

Основные типы событий:

  • ORDER_STATUS - смена статуса заказа (принят, в пути, вручён, возврат);
  • PRINT_FORM - готовность печатной формы накладной;
  • DOWNLOAD_PHOTO - фото подтверждения вручения;
  • RECEIPT - готовность квитанции.

Подписка регистрируется так:

curl -X POST 'https://api.edu.cdek.ru/v2/webhooks' \
  -H 'Authorization: Bearer ВАШ_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://example.com/cdek/webhook",
    "type": "ORDER_STATUS"
  }'

Если адрес обработчика недоступен по HTTPS или отвечает дольше нескольких секунд, СДЭК помечает подписку неактивной и перестаёт слать события, поэтому обработчик должен сразу отвечать 200 и уже потом заниматься логикой в фоне.

Второй момент, о котором часто забывают, доверие к входящим данным. Подписи у вебхука СДЭК нет, тело запроса ничем не заверено, и сверить его с секретом не получится. Защищаться приходится косвенно, и я делаю три вещи: принимаю событие на неочевидный адрес по HTTPS, а не на /cdek-webhook, подтверждаю событие обратным запросом к API СДЭК по uuid заказа и только после этого меняю статус у себя, и делаю обработчик идемпотентным, чтобы повторная доставка того же события не переписала заказ второй раз. На PHP при приёме события в WordPress или WooCommerce это выглядит так:

$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
http_response_code(200);

$uuid = $data['uuid'] ?? '';
$key = 'cdek_event_' . hash('sha256', $payload);
if ($uuid === '' || get_transient($key)) {
    exit;
}
set_transient($key, 1, DAY_IN_SECONDS);

$response = wp_remote_get('https://api.cdek.ru/v2/orders/' . $uuid, [
    'headers' => ['Authorization' => 'Bearer ' . $access_token],
    'timeout' => 10,
]);
$order = json_decode(wp_remote_retrieve_body($response), true);

Если вебхук нужен не для сайта, а для оповещения менеджеров, я обычно кидаю событие в Telegram-бота на aiogram, там же можно сразу отформатировать статус заказа человеческим текстом вместо технического кода СДЭК.

Интеграция СДЭК в Tilda, WordPress и n8n на практике

Tilda не умеет принимать вебхуки напрямую, у неё нет серверной части для этого, поэтому между СДЭК и Tilda всегда стоит промежуточный обработчик, свой скрипт на хостинге или сценарий в n8n, который получает вебхук, пересчитывает статус и записывает его в CRM или в свою таблицу заказов. Обратно в Tilda статус не записать: её API работает только на чтение, это семь GET-методов для выгрузки проектов и страниц, лимит 150 запросов в час и тариф Business.

На WooCommerce ситуация проще, обработчик вебхука ставится прямым PHP-эндпоинтом или плагином, и статус заказа СДЭК синхронизируется со статусом заказа в WooCommerce напрямую. Если в проекте уже подключена оплата через T‑Bank, оба вебхука, от эквайринга и от СДЭК, обычно обрабатываются одним контроллером с разными роутами, чтобы не плодить точки входа на сервере.

Когда писать отдельный бэкенд под один вебхук нецелесообразно, я собираю приём и маршрутизацию событий СДЭК в n8n: нода Webhook принимает запрос, следующая нода подтверждает событие запросом к API СДЭК, а дальше данные уходят в Google-таблицу, Telegram или CRM без единой строчки кода на сервере. Такую разработку интеграции с CRM и эквайрингом под задачу я обычно оцениваю от 40 000 ₽, если речь про комплексную связку СДЭК плюс оплата плюс CRM, а не про одну изолированную доработку скрипта.

Частые вопросы

Можно ли получить боевые ключи API СДЭК без договора?

Нет, боевой контур привязан к вашему юрлицу и действующему договору на доставку. Без договора доступен только тестовый контур, там ключи выдаются практически сразу, но заказы там виртуальные и в реальную доставку не уходят.

Почему вебхук от СДЭК не приходит на сервер?

Чаще всего проблема в трёх местах: адрес обработчика недоступен по HTTPS, сервер отвечает дольше нескольких секунд, из-за чего СДЭК считает подписку неудачной, или подписка вообще не была зарегистрирована запросом к /v2/webhooks, а не просто ожидалась по умолчанию.

Как долго живёт токен доступа к API СДЭК?

Access_token, полученный через /oauth/token, действует обычно 3600 секунд, то есть час. Дальше его нужно запросить заново по тем же client_id и client_secret, кэшировать токен и переиспользовать его на все запросы в течение этого часа, а не получать новый перед каждым вызовом.

Нужно ли хранить ключи СДЭК на своём сервере в России?

Да, если через интеграцию проходят персональные данные получателей (ФИО, адрес, телефон), хранить их и логи вебхуков стоит на серверах в РФ, а не в зарубежных таблицах или облачных сервисах, это требование 152-ФЗ о локализации персональных данных.

Есть задача?

Обсудим в мессенджере

Расскажите, что нужно сделать — отвечу в течение 4 часов в рабочее время. Первая консультация бесплатно.

Продолжая пользование настоящим сайтом Вы выражаете своё согласие на обработку Ваших персональных данных (файлов куки) с использованием Yandex.Metrika.
Понятно