/ip/без ключаАдрес, с которого вы стучитесь
Единственный метод, который отвечает без ключа. Полезен, когда запросы идут через прокси или балансировщик и надо понять, какой адрес сервер видит на самом деле.
{ "ip": "203.0.113.10" }
Пятнадцать методов, которые проводят покупателя от VIN до оригинального артикула. Обычный JSON поверх HTTPS: без SDK, без обязательных библиотек, без собственного формата ответа.
# Машина по VIN — один запросcurl -sG https://api.goodvin.net/v1/car/info \ -H "Authorization: $KEY" \ --data-urlencode "q=XW8AN2NE3JH035743" # В ответе то, чем пользуются все# остальные методы: catalogId "vw" carId "vw-polo-2018-cfna" criteria "AAAAAB;2018;CFNA;RUS"Три вещи, которых хватает для первого запроса.
https://api.goodvin.net/v1адресAuthorization: ваш ключзаголовокAccept-Language: ruнеобязательноGETединственный методКаталог устроен деревом, и методы вызываются не вразнобой, а цепочкой: ответ предыдущего кормит следующий.
Валидатор чинит частые опечатки (O вместо нуля, I вместо единицы) и объясняет, что именно поправил. Дешевле, чем показать покупателю пустую выдачу.
GET /cars/vin-validatorVIN или номер кузова: тип определяется сам. В ответе приходят catalogId, carId и criteria. Эта тройка нужна дальше везде.
GET /car/infoПервый вызов без groupId отдаёт верхний уровень. Дальше подставляем идентификатор выбранного узла и повторяем, пока в ответе не появится hasParts: true.
GET /catalogs/{catalogId}/groups2/Схема узла, оригинальные артикулы, применимость и координаты выносок на картинке — всё одним ответом. Остаётся сопоставить артикулы со своим складом.
GET /catalogs/{catalogId}/parts2Если номера нет, начало другое: /catalogs/ → /models/ → /cars-parameters/ → /cars2/. Дальше с третьего шага, дерево и детали те же.
Скопируйте, подставьте ключ в переменную окружения — и первый ответ придёт раньше, чем вы дочитаете справочник.
# Ключ передаётся голым значением, без слова Bearerexport KEY="ваш ключ" # 1. Правим опечатки в номере до того, как тратить запросcurl -sG https://api.goodvin.net/v1/cars/vin-validator \ -H "Authorization: $KEY" \ --data-urlencode "vin=XW8AN2NE3JH035743" # 2. Определяем машину. В ответе catalogId, carId и criteriacurl -sG https://api.goodvin.net/v1/car/info \ -H "Authorization: $KEY" \ -H "Accept-Language: ru" \ --data-urlencode "q=XW8AN2NE3JH035743" # 3. Верхний уровень узлов найденной машиныcurl -sG https://api.goodvin.net/v1/catalogs/vw/groups2/ \ -H "Authorization: $KEY" \ --data-urlencode "carId=$CAR_ID" \ --data-urlencode "criteria=$CRITERIA" # 4. Детали узла, у которого пришло hasParts: truecurl -sG https://api.goodvin.net/v1/catalogs/vw/parts2 \ -H "Authorization: $KEY" \ --data-urlencode "carId=$CAR_ID" \ --data-urlencode "groupId=$GROUP_ID" \ --data-urlencode "criteria=$CRITERIA"Заголовок Access-Control-Allow-Origin у нас открыт, так что дёрнуть API прямо из скрипта на странице технически можно. Так делать нельзя. Ключ в исходниках виден каждому посетителю и уедет вместе с первым любопытным, а привязки к домену, которая страхует виджет, здесь нет. Запрос уходит с вашего сервера, наружу отдаётся готовый результат.
Разбор ответа car/info: остальные методы устроены так же — плоский JSON без обёрток вроде data или result.
[ { "title": "VOLKSWAGEN POLO 1.6 MPI", "catalogId": "vw", "brand": "Volkswagen", "modelId": "5bb58a3cab059a189ef92be181380fd5", "carId": "vw-polo-2018-cfna", "criteria": "AAAAAB;2018;CFNA;RUS", "vin": "XW8AN2NE3JH035743", "modelName": "Polo (612)", "groupsTreeAvailable": true, "optionCodes": [ { "code": "0GC", "description": "Кондиционер" } ], "parameters": [ { "key": "year", "name": "Год выпуска", "value": "2018", "sortOrder": 1 } ] }]carIdcriteriacatalogIdgroupsTreeAvailableoptionCodesВерсия 1.18.0. Машинную спецификацию OpenAPI сервер отдаёт по тому же адресу, что и данные, и она всегда свежее любой страницы.
Любой метод из списка вызывается прямо в браузере: вставьте ключ и нажмите Execute. Без ключа сразу работают два метода — этого хватает, чтобы увидеть формат ответа.
С чего начать, когда ключ только пришёл и непонятно, доходят ли запросы вообще.
/ip/без ключаЕдинственный метод, который отвечает без ключа. Полезен, когда запросы идут через прокси или балансировщик и надо понять, какой адрес сервер видит на самом деле.
{ "ip": "203.0.113.10" }
/catalogs/Список марок с числом моделей и датой актуальности. У каждого каталога четыре флага: hasVinCheck и hasFrameCheck говорят, ищет ли марка по номеру, hasGroupTree и hasUniTree — какие деревья узлов доступны. По ним видно, что предлагать покупателю, ещё до первого поиска.
Accept-Language | заголовок | Язык названий |
|---|
Массив Catalog: id, name, modelsCount, actuality, флаги
Два пути к машине: по номеру, когда покупатель его знает, и перебором по модели, когда нет.
/cars/vin-validatorРазбирает введённый номер по общим правилам и возвращает исправленный вариант вместе со списком правок: какие символы заменены и почему. Ставьте перед поиском: так опечатка покупателя не превратится в пустую выдачу.
vin • | запрос | Номер как его ввёл покупатель |
|---|---|---|
Accept-Language | заголовок | Язык текста ошибок |
CarValidate: original, changed, errors[] с расшифровкой
/car/infoГлавный метод подбора. Тип номера определяется сам, различать VIN и FRAME на своей стороне не нужно. В ответе приходит связка catalogId + carId + criteria. Дальше все запросы идут с ней.
q • | запрос | VIN или номер кузова |
|---|---|---|
catalogs | запрос | Сузить поиск списком каталогов через запятую: kia,bmw,hyundai |
Accept-Language | заголовок | Язык ответа |
Массив CarInfo: title, brand, catalogId, carId, criteria, optionCodes, parameters
/catalogs/{catalogId}/models/Начало подбора без номера: список моделей марки с картинками.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
Accept-Language | заголовок | Язык названий |
Массив Model: id, name, img
/catalogs/{catalogId}/cars-parameters/Кузов, годы, двигатель, рынок — то, из чего собирается форма подбора. В заголовке X-Cars-Count приходит число машин, оставшихся после выбранных фильтров: можно показывать счётчик, не запрашивая сам список.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
modelId • | запрос | Идентификатор модели |
parameter | запрос | Уже выбранные значения фильтров (idx через запятую) |
Массив CarParameterInfo. Поле sortOrder задаёт порядок полей в форме: чем меньше, тем выше
/catalogs/{catalogId}/cars2/Список комплектаций, отфильтрованный параметрами. По 25 записей на страницу, общее число — в заголовке X-Total-Count.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
modelId • | запрос | Идентификатор модели |
parameter | запрос | Значения фильтров (idx) |
page | запрос | Номер страницы, больше нуля |
Массив Car2 + заголовок X-Total-Count
/catalogs/{catalogId}/cars2/{carId}Понадобится, когда покупатель вернулся по сохранённой ссылке, а разбирать её заново не хочется.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
carId • | путь | Идентификатор машины |
criteria | запрос | Строка комплектации из car/info |
Car2: name, brand, modelName, vin, frame, criteria, parameters
Каталог устроен деревом. Спускаться по нему нужно до листа — там лежат детали.
/catalogs/{catalogId}/groups2/Без groupId отдаёт верхний уровень. Дальше подставляйте идентификатор выбранного узла и спускайтесь, пока hasParts не станет true — это и есть признак, что внутри лежат артикулы, а не следующий уровень.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
carId • | запрос | Идентификатор машины |
groupId | запрос | Узел, внутрь которого спускаемся. Пусто — верхний уровень |
criteria | запрос | Строка комплектации из car/info |
Массив Group: id, name, img, hasSubgroups, hasParts
/catalogs/{catalogId}/groups-suggestПокупатель пишет «аморт» — метод предлагает узлы, где встречается амортизатор. Возвращает sid, по которому можно достать сами узлы.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
q • | запрос | Первые буквы названия |
Массив Suggest: sid, name
/catalogs/{catalogId}/groups-treeКогда нужна вся структура сразу, например для своей навигации по каталогу. Флаг cached=true отдаёт общее дерево из кеша и отвечает быстро; cached=false собирает дерево под конкретную машину, но заметно дольше.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
carId | запрос | Идентификатор машины |
criteria | запрос | Строка комплектации |
cached | запрос | true — общее дерево из кеша, false — отфильтрованное |
Дерево GroupsTreeResponse с вложенными subGroups
/catalogs/{catalogId}/schemasСхемы, каждая из которых ведёт сразу на страницу деталей, минуя спуск по дереву. Можно отфильтровать по ветке или по названию детали. По 24 схемы на страницу.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
carId • | запрос | Идентификатор машины |
branchId | запрос | Ограничить ветвью дерева |
partName | запрос | Отобрать по названию детали |
partNameIds | запрос | То же, но по идентификаторам: 56,85 |
page | запрос | Страница, по 24 элемента |
SchemasResponse: group + list[] со схемами и названиями деталей
/catalogs/{catalogId}/groups-by-sidустарелПомечен устаревшим на стороне сервера. В новых интеграциях не используйте: сузить выдачу лучше через schemas с параметром partName.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
sid • | запрос | Идентификатор из groups-suggest |
carId • | запрос | Идентификатор машины |
Массив Group
Конец пути: артикулы, схема узла и координаты выносок на ней.
/catalogs/{catalogId}/parts2Отдаёт разом всё, из чего собирается страница узла: картинку схемы, список деталей с оригинальными артикулами и координаты выносок на схеме, чтобы номер на картинке можно было связать со строкой в списке.
catalogId • | путь | Идентификатор каталога |
|---|---|---|
carId • | запрос | Идентификатор машины |
groupId • | запрос | Узел, у которого hasParts: true |
criteria | запрос | Строка комплектации |
x-redirect-template | заголовок | Шаблон ваших адресов для ссылок внутри описаний |
Parts: img, partGroups[] с деталями, positions[] с координатами выносок
/example/pricesбез ключаПоказывает, как может выглядеть ответ с ценой, остатком и сроком поставки. Данные в нём выдуманные и не меняются: метод существует, чтобы проектировщик интеграции увидел форму ответа. Свои цены вы подставляете из учётной системы.
code • | запрос | Артикул |
|---|---|---|
brand • | запрос | Бренд |
Массив ExamplePricesResponse: price, inStockQty, delivery, rating
• — обязательный параметр. Всем методам, кроме помеченных «без ключа», нужен заголовок авторизации.
Часть данных приходит не в теле, а в заголовках. Их легко не заметить и потом собирать пагинацию наугад.
X-Total-CountX-Cars-Countx-request-idНичего из этого не считается ошибкой на стороне сервера: он честно отвечает на то, о чём его спросили.
Потерянная criteriaparts2 у промежуточного узлаГрузовые каталогиСсылки внутри описанийПагинацияКеш на своей стороне| Код | Что означает | Что делать |
|---|---|---|
| 401 | Ключ не передан или недействителен | Проверьте заголовок Authorization. Значение передаётся голым, без слова Bearer |
| 403 | Ключ есть, но доступ к ресурсу закрыт | Обычно это каталог вне вашей подписки или домен вне списка. Напишите менеджеру |
| 404 | Ничего не нашлось по этим параметрам | Для parts2 чаще всего означает, что у узла hasParts: false — спуститесь глубже |
| 400 | Запрос собран неверно | Не хватает обязательного параметра или он не того типа |
| 422 | Параметр отсутствует | Возвращает cars-parameters, когда не передан modelId |
| 429 | Слишком часто | Повторите через интервал из заголовка Retry-After |
Тело ошибки одинаковое у всех методов: code, errorCode и message. Отдельного формата для каждого случая нет.
В каждом ответе есть заголовок x-request-id. Приложите его к письму — по нему поднимут ровно ваш запрос вместо того, чтобы просить повторить проблему и ждать, пока она воспроизведётся.
Запрос расходуется только на определение новой машины. Всё, что происходит внутри уже найденной, — дерево, схемы, детали — не тарифицируется.
| Параметр | Песочница | Боевой ключ |
|---|---|---|
| Запросов в сутки | 100 | по тарифу |
| Частота | 2 запроса в секунду | 10 запросов в секунду |
| Данные | полные, тестовый набор марок | полные |
| Срок | 3 дня | срок подписки |
| Действие запроса | 24 часа | 24 часа |
Повторное обращение к тому же автомобилю в течение суток отдаётся из кеша и пакет не расходует.
Европейские, японские, американские и корейские каталоги по API стоят столько же, сколько виджет: 7 590 ₽ за 1 000 запросов, 21 590 ₽ за 3 000, 33 990 ₽ за 5 000. Наценки за программный доступ нет. Китайские марки тарифицируются отдельно — 31 590 ₽ за 1 000 запросов в месяц. Объёмы от 10 000 и корпоративные условия — на отдельной странице.
Обязательной библиотеки нет: это обычный REST с JSON, любой HTTP-клиент подойдёт. Спецификацию OpenAPI сервер отдаёт по адресу api.goodvin.net/v1, так что клиент для своего языка можно сгенерировать за минуту или загрузить её в Postman и Insomnia. Готовые примеры на cURL, PHP, JavaScript и Python — выше на этой странице, а вызвать метод, ничего не устанавливая, можно в консоли.
Виджет — готовый интерфейс, который отрисовывается скриптом и в поисковый индекс не попадает. По API вы получаете данные и рисуете страницы сами, поэтому они индексируются как обычные страницы магазина. Это и есть главная причина, по которой к API переходят.
Запросы идут с вашего сервера, на клиенте не грузится ничего лишнего. В отличие от виджета со своим бандлом, здесь вы контролируете каждый килобайт и можете отдавать страницу уже с деталями, из своего кеша.
Придёт стандартный код ошибки. Показывайте покупателю форму «подберём вручную» вместо пустого экрана: заявка сохранится, даже если подбор в этот момент недоступен.
Да. Ключ для песочницы приходит на почту после заявки, привязка к домену для него не нужна. Три дня и сто запросов в сутки — этого хватает, чтобы собрать прототип подбора.
Да, он для того и сделан: показывает, с какого адреса сервер видит ваши запросы. Полезно, когда трафик идёт через прокси или балансировщик и надо понять, какой адрес добавлять в списки. Данных каталога он не отдаёт.
Приходит на почту вместе со ссылкой на документацию. Домен указывать не нужно.