Для разработчиков · v1
Car2B Remote Sales API
Публичный API «Удалённого отдела продаж»: ваша система сама ведёт программу, принимает заявки, берёт сток, бронирует автомобили и фиксирует сделки — всё то, что доступно в кабинете.
https://car2b.ru/api/v1/remote-sales Формат: JSON, UTF-8 Ошибки: application/problem+json Содержание
Для кого и как это работает
Car2B — площадка: сторона сделки и расчётов — сами участники. API рассчитан на две роли, у каждой свой префикс пути и свои ключи.
| Роль | Кто это | Что делает через API | Префикс |
|---|---|---|---|
| Организатор программы | владелец стока | ведёт программу и уровни, настраивает сток, приглашает организации и принимает заявки, видит брони, подтверждает сделки по своим автомобилям | /owner/* |
| Агент | удалённый ОП | ищет программу в каталоге, подаёт заявку, синхронизирует доступный сток, бронирует, фиксирует покупки | /agent/* |
- Программа адресуется по
program_guidво всех ручках — не полагайтесь на то, что у организации ровно одна программа. - Доступ = скоуп и участие. Организатор работает только со своими программами, агент — только внутри
active-партнёрства (каталог и чтение собственных партнёрств, в том числе ожидающих и отклонённых, доступны и без него). Чужой ресурс неотличим от несуществующего:404 not_found. - Партнёрство со статусом
suspendedприостановлено модерацией площадки: чтение доступно, брони и сделки — нет. - Ресурсы и действия, созданные через API, помечаются
source: api(из интерфейса —ui).
Доступ
Ключи, назначения, обмен на токен, разрешённые IP и подпись вебхуков одинаковы для всех API Car2B и описаны в общем разделе «Ключи и доступ». Здесь — только то, что относится к Удалённому ОПу.
-
Ключ создаётся в личном кабинете: Профиль → Интеграции. Один ключ — одно назначение:
«Удалённый ОП — организатор программы» (скоупы
remote-sales:owner.read remote-sales:owner.write) или «Удалённый ОП — агент» (remote-sales:agent.read remote-sales:agent.write). Скоупwriteне включаетread. Нужны обе роли — выпустите два ключа. - Лимит — 5 активных ключей на организацию для каждого назначения.
-
Действия совершаются от имени владельца ключа. У него должен быть доступ к разделу
«Удалённый ОП» (иначе
403 permission_missing), организация должна быть верифицирована (403 organization_unverified), а при включённой платной модели — с активной подпиской (403 subscription_required): те же правила, что в кабинете. Право проверяется на каждом запросе. - Если API временно выключен на стороне площадки, ответ —
503 feature_disabledс заголовкомRetry-After.
curl -X POST https://car2b.ru/api/v1/identity/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=client_credentials"
# → { "access_token": "…", "token_type": "Bearer", "expires_in": 300, "scope": "…" } Быстрый старт: организатор
Ключ с назначением «Удалённый ОП — организатор программы». Список ваших программ и их program_guid:
curl https://car2b.ru/api/v1/remote-sales/owner/programs \
-H "Authorization: Bearer $TOKEN" Опубликовать программу и выбрать, какой сток доступен агентам:
# опубликовать программу в каталоге (повтор на опубликованной — 200 без эффекта)
curl -X POST https://car2b.ru/api/v1/remote-sales/owner/programs/$PROGRAM_GUID/publish \
-H "Authorization: Bearer $TOKEN"
# какие автомобили доступны агентам: all | include | exclude
curl -X PUT https://car2b.ru/api/v1/remote-sales/owner/programs/$PROGRAM_GUID/stock-settings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "mode": "exclude", "vehicle_guids": ["6d1f2c8e-9b7a-4c1e-8f3d-2a5b6c7d8e9f"] }' Пригласить организацию и принять заявку агента:
# пригласить организацию в программу (Idempotency-Key необязателен, но рекомендуется)
curl -X POST https://car2b.ru/api/v1/remote-sales/owner/partnerships \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: invite-2026-10-13-001" \
-H "Content-Type: application/json" \
-d '{ "program_guid": "…", "remote_org_guid": "…", "message": "Приглашаем в программу" }'
# принять заявку агента
curl -X POST https://car2b.ru/api/v1/remote-sales/owner/partnerships/$PARTNERSHIP_GUID/accept \
-H "Authorization: Bearer $TOKEN"
Приглашение неизвестной организации возвращает 422 unknown_organization; идентификатор
передаётся в теле запроса, а не в пути.
Быстрый старт: агент
Ключ с назначением «Удалённый ОП — агент». Найти программу в каталоге и подать заявку:
curl "https://car2b.ru/api/v1/remote-sales/agent/catalog/programs?q=УАЗ&limit=20" \
-H "Authorization: Bearer $TOKEN"
# заявка на программу (Idempotency-Key необязателен)
curl -X POST https://car2b.ru/api/v1/remote-sales/agent/partnerships \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "program_guid": "…", "message": "Хотим работать по вашей программе" }'
Пока организатор не принял заявку, партнёрство в статусе pending_request; статус и приход
partnership.accepted можно отслеживать через GET /agent/partnerships или вебхук.
После перехода в active доступен сток:
# полный обход стока активного партнёрства
curl "https://car2b.ru/api/v1/remote-sales/agent/partnerships/$PARTNERSHIP_GUID/stock?limit=200" \
-H "Authorization: Bearer $TOKEN"
# → { "items": [ { "vehicle_guid": "…", "removed": false, "price": 1990000, … } ],
# "next_cursor": "",
# "sync_token": "…" } # sync_token — только на последней странице Бронь и сделка:
# бронь на 2 часа; Idempotency-Key обязателен
curl -X POST https://car2b.ru/api/v1/remote-sales/agent/reservations \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: res-7f0d3c1a" \
-H "Content-Type: application/json" \
-d '{ "partnership_guid": "…", "vehicle_guid": "…" }'
# зафиксировать покупку; Idempotency-Key обязателен
curl -X POST https://car2b.ru/api/v1/remote-sales/agent/deals \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: deal-7f0d3c1a" \
-H "Content-Type: application/json" \
-d '{ "partnership_guid": "…", "vehicle_guid": "…", "price": 1890000, "currency": "RUB", "reservation_guid": "…" }' Основные сценарии
Организатор
- Подготовить программу.
PATCH /owner/programs/{program_guid}(карточка),PUT …/levels(полная замена набора уровней; уровень накопительный, прошлые сделки не пересчитываются),PUT …/stock-settings(режимall,includeилиexcludeсо спискомvehicle_guids— объявления вашей организации). - Опубликовать.
POST …/publish:draftилиunpublished→published; снять с каталога —POST …/unpublish. Заблокированную администрацией программу менять нельзя:409 program_blocked. - Принимать заявки.
GET /owner/partnerships?status=pending_request(или вебхукpartnership.requested), затемPOST /owner/partnerships/{partnership_guid}/acceptили…/decline. Активное партнёрство завершается через…/terminate. - Брони.
GET /owner/reservations,GET …/{reservation_guid}, снять бронь —POST …/cancel. - Подтверждать сделки.
GET /owner/deals, затемPOST /owner/deals/{deal_guid}/confirm; до завершения сделку можно отменить (…/cancel), при расхождении —…/dispute.
Агент
- Найти программу.
GET /agent/catalog/programsс фильтрами (q,city,region,brand,min_vehicles,reservation_enabled), карточка —GET …/{program_guid}. - Подать заявку.
POST /agent/partnershipsсprogram_guid. Возможные409:already_exists,geography_restricted,self_partnership. Если организатор сам пригласил вас — статусpending_invite, пришёл вебхукpartnership.invited. - Синхронизировать сток активного партнёрства — см. следующий раздел.
- Забронировать.
POST /agent/reservations— бесплатно, до 2 часов. Действуют правила домена, как в кабинете: брони включены у программы и не отключены партнёру, у организации не больше одной активной брони на платформе и не больше одной брони в сутки на владельца, автомобиль доступен. Нарушение —409с кодом из таблицы ошибок. Снять —POST …/cancel. - Зафиксировать сделку.
POST /agent/deals(цена договора купли-продажи между сторонами, опциональноreservation_guid— тогда бронь получит статусconverted_to_deal). Инициатор считается подтвердившим; сделка завершается после подтверждения продавцом. Дальше…/confirm,…/cancel,…/dispute.
Синхронизация стока
GET /agent/partnerships/{partnership_guid}/stock отдаёт автомобили владельца в рамках режима
стока программы, только для active-партнёрства (иначе 409 partnership_not_active).
Розничную цену задаёт владелец. Фильтры brand и model — по живым позициям.
- Первый обход — полный. Без
updated_since, постранично поnext_cursor(пустой — последняя страница). Порядок — по(updated, vehicle_guid). - Сохраните
sync_tokenс последней страницы обхода. - Следующие обходы — инкрементальные: передайте токен как
updated_sinceи в конце снова сохраните новыйsync_token.
# следующие обходы — только изменения с прошлого раза
curl "https://car2b.ru/api/v1/remote-sales/agent/partnerships/$PARTNERSHIP_GUID/stock?updated_since=$SYNC_TOKEN&limit=200" \
-H "Authorization: Bearer $TOKEN"
# живая позиция — все поля; надгробие — только идентификатор, updated и причина:
{ "vehicle_guid": "…", "removed": true, "removed_reason": "unavailable", "updated": "2026-10-13T09:30:00Z" } - Повторы возможны. Порядок инкремента задаёт журнал изменений стока партнёрства; изменения во время обхода попадут в следующий инкремент, одна позиция может прийти повторно,
updatedне обязан возрастать. Обрабатывайте позиции идемпотентно: последняя запись поvehicle_guidпобеждает. - Надгробия. Снятая позиция приходит с
removed: true, остальных полей нет.removed_reason:unavailable— продан, удалён или снят с публикации;excluded— организатор исключил автомобиль из стока программы. - Фильтры
brand/modelнадгробия не отсекают: инкремент с фильтром может содержать надгробия автомобилей, которых вы не видели — просто игнорируйте неизвестные. - Токен старше 30 дней —
410 sync_token_expired: сделайте полный обход заново и сохраните свежий токен. cursorиsync_tokenнепрозрачны и привязаны к партнёрству — не разбирайте и не переносите между партнёрствами.- Признаки брони у позиции:
reserved,reserved_by_me,reserved_until; кто бронировал — не раскрывается. - Вебхуки
stock.*ускоряют реакцию, но не заменяют сверку: для надёжности периодически запускайте инкрементальный обход.
Идемпотентность
POST /agent/reservationsиPOST /agent/dealsтребуют заголовокIdempotency-Key(до 128 символов); без него —400 idempotency_key_required.- Приглашение (
POST /owner/partnerships) и заявка (POST /agent/partnerships) принимают заголовок по желанию. - Повтор с тем же ключом в течение 24 часов возвращает первый ответ с заголовком
Idempotency-Replayed: trueи не создаёт второй ресурс; тот же ключ с другим телом —409 idempotency_key_reused, пока первый запрос выполняется —409 idempotency_in_progress. - Переходы состояний (
accept,cancel,confirmи др.) повторять безопасно: недопустимый переход —409 invalid_state.
Вебхуки
Адрес и секрет подписи задаются в карточке ключа, заголовки, подпись, повторы и таймаут — в общем разделе
«Вебхуки и подпись» (ответ 2xx за 10 секунд, повторы через 1, 5, 15, 60 и 300 секунд).
Ключ получает события тех ролей, чьи скоупы у него есть; чужие события не приходят. Возможны повторные
доставки — обработчик должен быть идемпотентным по id.
POST https://crm.example.ru/car2b/webhook
Content-Type: application/json
X-Car2B-Event: reservation.created
X-Car2B-Delivery: 7f0d3c1a-5e2b-4a7c-9d61-0b8e4f2a1c33
X-Car2B-Signature: sha256=3f5a9c…e1
{ "id": "7f0d3c1a-…", "type": "reservation.created", "occurred_at": "2026-10-13T09:30:00Z", "data": { … } } События организатора (ключ с назначением «организатор»):
| Событие | Когда |
|---|---|
partnership.requested | агент подал заявку на вашу программу |
partnership.accepted | партнёрство активно (вы приняли заявку или агент принял ваше приглашение) |
partnership.declined | ваше приглашение отклонено |
partnership.terminated | партнёрство завершено |
reservation.created | создана бронь вашего автомобиля |
reservation.cancelled | бронь снята |
reservation.expiring_soon | бронь истекает через 15 минут (однократно) |
reservation.expired | бронь истекла |
deal.created | сделку создала вторая сторона (агент зафиксировал покупку) |
deal.confirmed | сделку подтвердила одна сторона — событие получает вторая |
deal.completed | сделка завершена |
deal.cancelled | сделка отменена |
deal.disputed | заявлено расхождение по сделке |
События агента (ключ с назначением «агент»):
| Событие | Когда |
|---|---|
partnership.invited | организатор пригласил вашу организацию |
partnership.accepted | партнёрство активно (организатор принял вашу заявку или вы приняли приглашение) |
partnership.declined | ваша заявка отклонена; при удалении программы организатором — с признаком program_deleted: true |
partnership.terminated | партнёрство завершено |
reservation.created | бронь создана не через ваш ключ (например, из интерфейса) |
reservation.cancelled | бронь снята |
reservation.expiring_soon | бронь истекает через 15 минут (однократно) |
reservation.expired | бронь истекла |
deal.created | сделка создана не вами (получает сторона, не инициатор) |
deal.confirmed | сделку подтвердила одна сторона — событие получает вторая |
deal.completed | сделка завершена |
deal.cancelled | сделка отменена |
deal.disputed | заявлено расхождение по сделке |
level.changed | достигнут новый уровень программы |
stock.vehicle_added | автомобиль появился в доступном стоке |
stock.price_changed | цена автомобиля изменилась |
stock.vehicle_sold | автомобиль продан |
stock.vehicle_unavailable | автомобиль снят, в архиве или удалён |
Точный состав data каждого события — в спецификации
(раздел webhooks). Журнал доставок: GET /webhooks/deliveries — доступен ключу с любым из read-скоупов.
Лимиты
| Что | Значение |
|---|---|
| Запросов в секунду на ключ | 10, всплеск до 50 |
| Тело запроса | 64 КБ |
| Страница списка (limit) | от 1 до 200, по умолчанию 50 |
| Idempotency-Key | до 128 символов, помнится 24 часа |
| Срок брони | до 2 часов, бесплатно |
| Хранение надгробий стока | 30 дней |
| Активных ключей на организацию для каждого назначения | 5 |
При превышении лимита запросов приходит 429 с заголовком Retry-After — подождите указанное число секунд. Списки используют курсорную пагинацию: limit и cursor из next_cursor.
Ошибки
Ошибки приходят в формате application/problem+json. В errors[] — поле, машинный код
и сообщение на русском.
| HTTP | code | Когда |
|---|---|---|
| 400 | malformed, invalid_value, idempotency_key_required | невалидный JSON, неизвестное поле, неверный тип; неверный параметр запроса; не передан Idempotency-Key там, где он обязателен |
| 401 | token_invalid, token_expired, client_revoked | обновите токен через /oauth/token и повторите запрос один раз; client_revoked — ключ отозван или неизвестен |
| 403 | scope_missing, permission_missing, organization_unverified, organization_blocked, subscription_required, ip_not_allowed | нет нужного скоупа; у владельца ключа нет доступа к разделу «Удалённый ОП»; организация не верифицирована или заблокирована; нет активной подписки при включённой платной модели; запрос с неразрешённого IP |
| 404 | not_found | ресурса нет либо ваша организация не его участник — чужие ресурсы неотличимы от несуществующих; агентские операции работают только внутри active-партнёрства |
| 409 | invalid_state, already_exists, program_blocked, geography_restricted, self_partnership, partnership_not_active | недопустимый переход состояния; партнёрство уже есть; программа заблокирована площадкой; ограничение по географии; партнёрство с самим собой; партнёрство не active |
| 409 | reservation_disabled, reservations_blocked, reservation_active_limit, reservation_daily_limit, vehicle_unavailable | брони выключены или заблокированы; достигнут лимит активных или суточных броней; автомобиль недоступен — правила те же, что в кабинете |
| 409 | idempotency_in_progress, idempotency_key_reused | первый запрос с этим ключом ещё выполняется; ключ уже использован с другим телом |
| 410 | sync_token_expired | sync_token старше 30 дней — нужен полный обход стока |
| 422 | invalid_enum, invalid_value, required_field_missing, unknown_vehicle, unknown_organization | поля разобраны, но не проходят правила; unknown_organization — приглашена неизвестная организация |
| 429 | rate_limited, daily_quota_exceeded | превышен лимит, в ответе заголовок Retry-After |
| 503 | feature_disabled, temporarily_unavailable | API выключен или проверка ключа временно недоступна; в ответе Retry-After, повторите позже |
Спецификация
Точное описание ручек, тел запросов и ответов, а также вебхуков — в OpenAPI-спецификации: интерактивная версия и файл YAML для генерации клиента.
Общие вопросы про ключи — документация API; по интеграции — контакты Car2B.