OVD-Info · Public API experimental

Read-only доступ к данным о политических преследованиях в России

Legacy V1 API (repression.net) →

Обзор

API предоставляет структурированный доступ к данным о политических преследованиях в России. Данные обновляются несколько раз в сутки.

Это экспериментальный API — структура эндпоинтов и набор полей могут меняться.

Базовый URL: https://api-data.ovd.info  ·  Swagger UI: /docs

Аутентификация

Все запросы (кроме GET /datasets) требуют заголовок:

X-API-Key: <ваш_ключ>

Для получения ключа обратитесь к команде ОВД-Инфо по адресу [email protected]. Ключ выдаётся один раз — сохраните его.

Эндпоинты

МетодПутьОписаниеКлюч
GET/datasetsСхема датасетов: колонки, фильтрыНет
GET/personsСписок персон с фильтрацией и поискомДа
GET/persons/{id}Персона по UUIDДа
GET/organisationsСписок организацийДа
GET/organisations/{id}Организация по UUIDДа
GET/pp_persecutionsПолитические преследованияДа
GET/profilesКарточки персон (адрес для писем, «Весточка», имя/история/статус)Да
GET/profiles/{id}Карточка персоны по id (?subset=full — + уголовные дела, реестры, оценки правозащитников, хронология событий одним ответом)Да

Query-параметры

ПараметрТипОписание
limitintСтрок в ответе (по умолчанию 100, макс. 1000)
offsetintСмещение для пагинации. Ответ содержит total — общее число строк с учётом фильтров. Взаимоисключим с cursor
cursorstrЗначение next_cursor из предыдущего ответа — устойчивая keyset-пагинация без дублей/пропусков при обходе больших списков (в отличие от offset, не зависит от того, есть ли в данных повторяющиеся значения sort-колонки, например updated_at у пачки записей одного импорта). Переопределяет sort/order значениями, с которыми был выпущен — см. «Пагинация» ниже
qstrПоиск подстроки по всем search-полям одновременно
{col}strТочный фильтр по filter-полю. Поддерживает операторы — см. ниже
subsetstrПодмножество колонок: rfm или inoteka — подробнее ниже
sortstrИмя колонки для сортировки. Только колонки, входящие в текущий ответ
orderstrasc (по умолчанию) или desc
timelineboolТолько /persons/{id} — добавляет persecutions[] с преследованиями

Операторы фильтрации

Все filter-поля поддерживают расширенные операторы через суффикс __{оператор}:

СинтаксисОператорПример
?{col}=valТочное совпадение?persecution_status=Осуждён
?{col}__gt=valБольше чем?start_year__gt=2021
?{col}__gte=valБольше или равно?updated_at__gte=2026-08-01
?{col}__lt=valМеньше чем?verdict_date__lt=2024-01-01
?{col}__lte=valМеньше или равно?verdict_date__lte=2023-12-31
?{col}__in=a,b,cОдно из значений?region__in=Москва,Санкт-Петербург

Операторы можно комбинировать: ?start_year__gte=2020&start_year__lt=2023

Subsets для /persons

По умолчанию возвращаются только базовые поля (имя, дата рождения, ИНН). Параметр subset добавляет тематический блок:

ЗначениеДобавляет
subset=rfmФлаги источников, pp_person_id и все поля из реестра Росфинмониторинга
subset=inotekaПоля из реестра иностранных агентов: статус, основание признания, тематика, год признания/исключения, флаги прекращения работы

Для /organisations параметра subset нет — все поля возвращаются всегда. Записи с do_not_publish возвращаются, но с обнулёнными идентификаторами и описаниями.

Пагинация

Рекомендуется — курсор (cursor). Сортировка на большом списке почти всегда содержит повторяющиеся значения (например, у пачки записей, обновлённых одним импортом, совпадает updated_at) — офсетная пагинация в этом случае может отдать одну и ту же строку дважды или пропустить её при переходе между страницами. Курсор кодирует позицию последней строки (значение сортировки + внутренний id-тайбрейкер) и не зависит от такого совпадения. Задайте sort в первом запросе — дальше просто передавайте next_cursor из ответа, пока он не станет null; sort/order повторно передавать не нужно, курсор уже их несёт.

# Загрузить все записи, устойчиво к дублям/пропускам
import requests

API = "https://api-data.ovd.info"
KEY = {"X-API-Key": "<ваш_ключ>"}
params = {"limit": 1000, "sort": "updated_at", "order": "desc"}
rows = []

while True:
    r = requests.get(f"{API}/persons", headers=KEY, params=params).json()
    rows.extend(r["data"])
    if not r["next_cursor"]: break
    params = {"limit": 1000, "cursor": r["next_cursor"]}

Альтернатива — offset. Проще для разовой выгрузки небольшого списка, но не гарантирует отсутствие дублей/пропусков при сортировке с повторяющимися значениями.

# Загрузить все записи постранично (offset)
import requests

API = "https://api-data.ovd.info"
KEY = {"X-API-Key": "<ваш_ключ>"}
params = {"limit": 1000, "offset": 0}
rows = []

while True:
    r = requests.get(f"{API}/persons", headers=KEY, params=params).json()
    rows.extend(r["data"])
    if params["offset"] + 1000 >= r["total"]: break
    params["offset"] += 1000

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

persons/organisations/profiles отдают updated_at, а pp_persecutionslast_updated; обе колонки filter, то есть поддерживают операторы __gt/__gte/__lt/__lte (см. таблицу операторов выше). Для регулярного (например, ежедневного) импорта не нужно перечитывать весь датасет — достаточно отфильтровать по отметке времени последней успешной синхронизации, отсортировать по той же колонке и пройти курсором:

# Только записи, изменённые после последней синхронизации
import requests

API = "https://api-data.ovd.info"
KEY = {"X-API-Key": "<ваш_ключ>"}
params = {
    "limit": 1000,
    "updated_at__gte": "2026-08-25T00:00:00",  # отметка предыдущего запуска
    "sort": "updated_at", "order": "asc",
}
rows = []

while True:
    r = requests.get(f"{API}/profiles", headers=KEY, params=params).json()
    rows.extend(r["data"])
    if not r["next_cursor"]: break
    params = {"limit": 1000, "cursor": r["next_cursor"]}
# следующий запуск — updated_at__gte = время начала ЭТОГО запуска (не последней строки из rows)

Отметку для следующего запуска берите из времени начала текущего запуска, а не из updated_at последней полученной записи — иначе запись, изменённая в БД в момент между вашими запросами первой и последней страницы, может быть пропущена.

Примеры

# Поиск по имени
curl "https://api-data.ovd.info/persons?q=Иванов" \
  -H "X-API-Key: <ваш_ключ>"

# Персоны с полным набором полей РФМ
curl "https://api-data.ovd.info/persons?subset=rfm&in_rosfinmon=true" \
  -H "X-API-Key: <ваш_ключ>"

# Иностранные агенты — все поля + фильтр по статусу (contains-any по всем статусам записи)
curl "https://api-data.ovd.info/persons?subset=inoteka&in_inoteka=true&inoteka_statuses=Физическое лицо — иностранный агент" \
  -H "X-API-Key: <ваш_ключ>"

# Организации — иноагенты, не прекратившие работу, признанные с 2020 года
curl "https://api-data.ovd.info/organisations?inoteka_stopped_working=false&inoteka_first_recognition_year__gte=2020" \
  -H "X-API-Key: <ваш_ключ>"

# Персона с историей преследований
curl "https://api-data.ovd.info/persons/<uuid>?timeline=true" \
  -H "X-API-Key: <ваш_ключ>"

# Активные преследования
curl "https://api-data.ovd.info/pp_persecutions?is_actual=true" \
  -H "X-API-Key: <ваш_ключ>"

Внутренние интерфейсы

Административные страницы для работы с данными — доступны авторизованным сотрудникам.

СтраницаОписание
/inoteka Реестр иностранных агентов. Список физических лиц и организаций с фильтрацией по типу, статусу и тексту. Карточка справа показывает основные данные, акты признания и давления, связанных участников. Форма редактирования позволяет менять все поля записи, включая статус признания, тематику деятельности и — для организаций — флаг прекращения работы.
/politpressing База политических преследований. Список преследуемых с фильтрацией по типу преследования, актуальности и тексту. Карточка справа раскрывает полный профиль: фото, персональные данные, историю преследований с мерами пресечения, судебными заседаниями, приговорами и местами лишения свободы, а также оценки правозащитных организаций.

Схема датасетов

Актуальная схема — колонки, какие из них фильтруемые и поисковые, к какому subset относятся. Ключ не нужен.

registries и timeline сюда не попадают — это не колонки profiles.parquet, а поля, которые добавляются на лету только в ответе GET /profiles/{id}?subset=full (не в списке GET /profiles и не в этой схеме). cases/evaluations — настоящие колонки (subset: full), появятся в таблице ниже.