Списки событий

Календарь платформы и события вашего аккаунта, карточка одного события, фильтры, пагинация, синхронизация.

Два списка событий с разным охватом и один эндпоинт для карточки конкретного события. Все три требуют токен — см. Авторизация. Токен один и тот же для всех эндпоинтов, в том числе для календаря платформы, хотя его данные не привязаны к вашему аккаунту.

Какие события попадают в выдачу

Только опубликованные и не скрытые события — та же логика, что и у каталога на сайте: событие должно быть активно (опубликовано организатором) и не иметь отметки «скрыто». Черновики и скрытые события не появляются ни в одном из списков и не отдаются по прямому id — в том числе если это ваш собственный черновик.

Календарь платформы

GET /api/1.0/calendar

Все опубликованные события всей платформы, всех организаторов — не только ваши. Без параметра from возвращает события с end_date не раньше сегодняшнего дня: прошедшие события по умолчанию не показываются.

Пример запроса

curl -s "https://myrace.info/api/1.0/calendar?sport=trail,running&country=RU&limit=20" \
  -H "Authorization: Bearer <ВАШ_ТОКЕН>"

События вашего аккаунта

GET /api/1.0/events

Только события, принадлежащие аккаунту, которому выдан токен, — scope неявный, по токену. Параметра, чтобы указать «чужой» аккаунт, нет.

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

Пример запроса

curl -s "https://myrace.info/api/1.0/events?sport=trail,running&from=2026-01-01&limit=20" \
  -H "Authorization: Bearer <ВАШ_ТОКЕН>"

Пример ответа (сокращённо, формат общий для обоих списков)

{
  "events": [
    {
      "id": "1994",
      "name": "Горный трейл 2026",
      "sports": [
        { "code": "trail", "name": "Трейл" }
      ],
      "start_date": "2026-05-16",
      "end_date": "2026-05-17",
      "location": {
        "id": "42",
        "country": "RU",
        "city": "Сочи",
        "latitude": 43.6028,
        "longitude": 39.7342
      },
      "url": "https://myrace.info/events/48213",
      "activities": [
        {
          "id": "5021",
          "name": "42 км",
          "sport": { "code": "trail", "name": "Трейл" },
          "start_date": "2026-05-16",
          "end_date": "2026-05-16"
        }
      ],
      "updated_at": "2026-04-01T10:15:30.000Z"
    }
  ],
  "next_page_token": "MjAyNi0wNS0xNnw0ODIxMw=="
}

Параметры

Оба списка принимают одинаковый набор параметров.

ПараметрТипОбязателенОписание
sportстроканетКоды видов спорта через запятую, см. Виды спорта. Событие попадает в выдачу, если совпадает хотя бы один код (логика ИЛИ). Пример: sport=trail,running
countryстроканетКод страны локации события, ISO 3166-1 alpha-2, без учёта регистра. Пример: country=RU
fromстрока, дата YYYY-MM-DDнетНижняя граница диапазона. У календаря платформы по умолчанию — сегодняшняя дата; у событий вашего аккаунта дефолта нет (см. выше)
toстрока, дата YYYY-MM-DDнетВерхняя граница диапазона, включительно. Возвращаются события, которые начинаются не позже этой даты — событие, стартовавшее до to, но продолжающееся после, всё равно попадёт в выдачу
updated_sinceстрока, дата-время ISO 8601 UTCнетВозвращает события, изменённые не раньше указанного момента. Подробнее — в разделе Инкрементальная синхронизация
limitцелое числонетРазмер страницы, от 1 до 100. По умолчанию 50
page_tokenстроканетНепрозрачный токен страницы из next_page_token предыдущего ответа

Если to указан раньше from, запрос вернёт 400.

Поведение фильтров

  • sport. Если среди переданных кодов есть хотя бы один, не совпадающий ни с одним активным видом спорта из каталога (см. Виды спорта), запрос вернёт 400 с перечислением неизвестных кодов в message и именем параметра sport в param. Регистр и пробелы вокруг кода не важны.
  • country. Если код не похож на двухбуквенный код страны (например, трёхбуквенный или с цифрами), запрос вернёт 400. А если код синтаксически корректен, но такой страны нет в справочнике платформы, ошибки не будет — запрос вернёт 200 OK с пустым списком events.

Пагинация

Пагинация курсорная (keyset), не по номеру страницы. Запросите первую страницу без page_token; если в ответе есть поле next_page_token, подставьте его значение в page_token следующего запроса. На последней странице поле next_page_token в ответе отсутствует (его нет в JSON, это не null). Токен — непрозрачная строка, не пытайтесь разобрать её формат.

Инкрементальная синхронизация

Параметр updated_since отбирает события, у которых дата изменения не раньше указанной. Учитывается:

  • собственное время изменения события;
  • время изменения любой из его активностей.

В ответе используется большее из этих двух значений — поле updated_at в карточке события (см. таблицу полей ниже).

⚠️ Известное ограничение. Изменение адреса, города или координат локации события не обновляет updated_at самого события. Если вы синхронизируетесь по updated_since, точечное изменение локации без других изменений в событии или его активностях может остаться незамеченным. Периодически делайте полную синхронизацию без updated_since, чтобы подхватить такие изменения.

Одно событие

GET /api/1.0/events/{id}

{id} — id события (значение поля id из одного из списков).

Эндпоинт отдаёт только события вашего аккаунта. Ответ — объект события в том же формате, что внутри массива events у списков, но без обёртки: прямо на верхнем уровне ответа, без ключа events.

Если событие не найдено, не распознано как id, принадлежит другому организатору или является вашим неопубликованным черновиком — во всех случаях одинаковый 404:

{
  "error": {
    "code": "not_found",
    "message": "Event not found: 999999"
  }
}

⚠️ По ответу нельзя отличить «это не ваше событие» от «такого события не существует» — это сделано специально, чтобы не раскрывать чужие данные.

Язык ответа

Все эндпоинты понимают заголовок Accept-Language (ru, en, es или fr). Если заголовок не передан или язык не поддерживается, ответ возвращается на русском. Используемый язык приходит обратно в заголовке Content-Language.

Кэширование

Все эндпоинты отдают заголовок ETag. Передайте его значение из предыдущего ответа в заголовке If-None-Match — если данные не изменились, API ответит 304 Not Modified без тела.

Значение Cache-Control зависит от эндпоинта — ответ календаря платформы не привязан к аккаунту и кешируется дольше:

ЭндпоинтCache-Control
/calendar, /sportspublic, max-age=300
/events, /events/{id}private, max-age=60

Поля события

ПолеТипОписание
idстрокаСуществующий публичный id события, как есть, без преобразований
nameстрокаНазвание события
sportsмассив SportВиды спорта события. Собираются из видов спорта активностей события (без повторов); если ни у одной активности вид спорта не указан, берётся вид спорта самого события. Если и он не указан — пустой массив
start_dateстрока, датаДата начала события
end_dateстрока, датаДата окончания события. Если дата окончания не задана, равна дате начала
locationобъект Location или nullЛокация события. null, если локация не указана
urlстрока, URLСсылка на страницу события на сайте MyRace
activitiesмассив ActivityАктивности события. Не у каждого события есть активности — массив может быть пустым
updated_atстрока, дата-время ISO 8601 UTCВремя последнего изменения — см. Инкрементальная синхронизация

Поля активности (Activity)

ПолеТипОписание
idстрокаСуществующий публичный id активности, как есть, без преобразований
nameстрокаНазвание активности
sportобъект Sport или nullВид спорта активности, если указан
start_dateстрока, датаДата начала активности. Если не задана отдельно, равна дате начала события
end_dateстрока, датаДата окончания активности. Если не задана, равна дате начала активности

Поля локации (Location)

ПолеТипОписание
idстрокаВнутренний id локации — у локации нет отдельного публичного id, поэтому отдаётся он
countryстрока или nullКод страны, ISO 3166-1 alpha-2
cityстрока или nullНазвание города
latitudeчисло или nullШирота
longitudeчисло или nullДолгота