Примеры использования API Яндекс Форм

В этом разделе приведены примеры скриптов на языке Python, которые используют API Яндекс Форм для управления формами и ответами.

Во всех примерах для аутентификации используется OAuth-токен. Получение токена описано в разделе Доступ к API.

1. Публикация и снятие с публикации существующей формы

Возможность опубликовать форму с помощью API полезна, если нужно реализовать более сложную логику, чем доступные в Формах опции по умолчанию (публикация по времени, снятие с публикации при достижении определенного количества набранных ответов и так далее).

См. описания методов:

Текст скрипта example_1.py
import os
import requests
import sys

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def publish_survey(survey_id: str) -> bool:
    """
    Опубликовать форму.
    Форма не будет опубликована в следующих случаях:
    - форма заблокирована;
    - форма уже набрала максимальное количество ответов;
    - у формы включен механизмом автопубликации, если заданное время публикации не наступило.
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/publish'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.post(url, headers=headers)
    return response.status_code == 200


def unpublish_survey(survey_id: str) -> bool:
    """
    Снять с публикации можно любую опубликованную форму, в том числе с включенным механизмом автопубликации, если время снятия с публикации не наступило.
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/unpublish'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.post(url, headers=headers)
    return response.status_code == 200


def main():
    if len(sys.argv) < 2:
        return

    survey_id = sys.argv[1]
    if publish_survey(survey_id):
        print(f'Форма {survey_id} опубликована')
    # if unpublish_survey(survey_id):
    #     print(f'Форма {survey_id} снята с публикации')


if __name__ == '__main__':
    main()

Пример запуска скрипта:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_1.py 6800cd9202848f10b272a9cc
Форма 6800cd9202848f10b272a9cc опубликована

2. Заполнение формы с помощью скрипта

API Яндекс Форм допускает заполнение формы анонимным пользователем (без OAuth-токена), если такая настройка не отключена явно (опция Показывать форму только авторизованным пользователям в настройках формы).

Чтобы заполнить форму от имени определенного пользователя, необходимо выполнить запрос с OAuth-токеном.

Значения полей (ответы на вопросы) формы передаются в формате JSON в виде пар идентификатор вопроса — значение.

См. описание метода Отправить ответ в форму.

Текст скрипта example_2.py
import json
import os
import requests
import sys

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def submit_survey(survey_id: str, **fields) -> int:
    """

    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/form'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.post(url, json=fields, headers=headers)
    if response.status_code == 200:
        result = response.json()
        return result.get('answer_id')


def main():
    if len(sys.argv) < 3:
        return

    survey_id = sys.argv[1]
    fields = json.loads(sys.argv[2])
    answer_id = submit_survey(survey_id, **fields)
    if answer_id:
        print(f'Заполнена форма {survey_id}, создан ответ {answer_id}')


if __name__ == '__main__':
    main()

Пример запуска скрипта:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_2.py 6800cd9202848f10b272a9cc '
{
  "id-text": "test it",
  "id-bool": true,
  "id-integer": 42,
  "id-enum": ["id-second", "id-third"]
}
'
Заполнена форма 6800cd9202848f10b272a9cc, создан ответ 2037950340

3. Получение ответа на форму

Рассмотрим пример получения ответа на форму по его идентификатору.

См. описание метода Получить ответ.

Данные ответа возвращаются в формате JSON, который при необходимости можно обработать на Python или с использованием консольной утилиты jq, а также преобразовать в формат CSV.

Текст скрипта example_3.py
import json
import os
import requests
import sys

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def get_one_answer(answer_id: int):
    """

    """
    url = f'{FORMS_PUBLIC_API}/answers'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    fields = {'answer_id': answer_id}
    response = requests.get(url, fields, headers=headers)
    if response.status_code == 200:
        return response.json()


def main():
    if len(sys.argv) < 2 or not sys.argv[1].isdigit():
        return

    answer_id = int(sys.argv[1])
    answer_data = get_one_answer(answer_id)
    if answer_data:
        survey_id = answer_data['survey']['id']
        print(f'Получен контент ответа {answer_id} для формы {survey_id}', file=sys.stderr)
        print(json.dumps(answer_data, indent=2, ensure_ascii=False))


if __name__ == '__main__':
    main()

Пример запуска скрипта с использование утилиты jq:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_3.py 2037950340 \
  | jq '.data[] | [.id, .value | if type == "array" then [.[].label] | join(", ") else . end] | @csv'
Получен контент ответа 2037950340 для формы 6800cd9202848f10b272a9cc
"\"id-text\",\"test it\""
"\"id-bool\",true"
"\"id-integer\",42"
"\"id-enum\",\"Second, Third\""

4. Постраничная выгрузка ответов на форму

API Яндекс Форм позволяет получить ответы на форму в формате JSON с постраничным доступом к результатам.

См. описание метода Получить ответ.

В примере ниже скрипт обрабатывает ответы, чтобы получить CSV-совместимый вывод результатов.

Текст скрипта example_4.py
import csv
import os
import requests
import sys

FORMS_PUBLIC_API_HOST = 'https://api.forms.yandex.net'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def get_value(item):
    value = item.get('value')
    if value is None:
        return ''
    if isinstance(value, list):
        return ', '.join(value)
    return value


def fetch_answers(survey_id: str, *, page_size: int = 50):
    """

    """
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    path = f'/v1/surveys/{survey_id}/answers?page_size={page_size}'
    columns = None
    while True:
        url = f'{FORMS_PUBLIC_API_HOST}{path}'
        response = requests.get(url, headers=headers)
        if response.status_code != 200:
            break

        result = response.json()
        if columns is None:
            columns = result.get('columns') or []
            yield ['ID', 'Created'] + [
                column.get('text')
                for column in columns
            ]

        for answer in result.get('answers') or []:
            yield [answer.get('id'), answer.get('created')] + [
                get_value(item)
                for item in answer.get('data') or []
            ]

        next_page = result.get('next')
        if not next_page:
            break

        path = next_page.get('next_url')
        if not path:
            break


def main():
    if len(sys.argv) < 2:
        return

    survey_id = sys.argv[1]
    print(f'Ответы на форму {survey_id}', file=sys.stderr)
    csvwriter = csv.writer(sys.stdout, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
    for answer in fetch_answers(survey_id):
        csvwriter.writerow(answer)


if __name__ == '__main__':
    main()

Пример запуска скрипта:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_4.py 6800cd9202848f10b272a9cc
Ответы на форму 6800cd9202848f10b272a9cc
"ID","Created","Short Text","Boolean","Integer","Enumeration"
"2037950340","2025-04-17T11:30:17Z","test it","True","42","Second, Third"
"2037859858","2025-04-17T10:14:01Z","test it","True","42","Second"

5. Выгрузка всех ответов на форму в файл

Для выгрузки ответов в файл будем использовать несколько вызовов API Яндекс Форм:

Текст скрипта example_5.py
import json
import os
import requests
import sys
import time

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def start_export(survey_id: str) -> str:
    """
    Запускает фоновый процесс экспорта ответов.
    Возвращает код запущенной операции.
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/answers/export'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    params = {'format': 'xlsx'}
    response = requests.post(url, json=params, headers=headers)
    if response.status_code == 202:
        result = response.json()
        operation_id = result.get('id')
        return operation_id
    print(response.status_code, response.json())


def check_finished(operation_id: str) -> bool:
    url = f'{FORMS_PUBLIC_API}/operations/{operation_id}'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        result = response.json()
        return result.get('status') == 'ok'


def download_result(survey_id: str, operation_id: str) -> bytes:
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/answers/export-results'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    params = {'task_id': operation_id}
    response = requests.get(url, params=params, headers=headers)
    if response.status_code == 200:
        return response.content


def main():
    if len(sys.argv) < 2:
        return

    survey_id = sys.argv[1]
    operation_id = start_export(survey_id)
    if operation_id:
        print(f'Запущена операция {operation_id}')

        while not check_finished(operation_id):
            print('...')
            time.sleep(5)

        content = download_result(survey_id, operation_id)
        if content:
            filename = f'{survey_id}.xlsx'
            with open(filename, 'wb') as f:
                f.write(content)

            print(f'Ответы выгружены в файл {filename}')


if __name__ == '__main__':
    main()

Пример запуска скрипта:

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_5.py 6800cd9202848f10b272a9cc
Запущена операция 0946779c-6a57-4070-b062-5d7ebdb65142
Ответы выгружены в файл 6800cd9202848f10b272a9cc.xlsx

6. Загрузка и получение файлов

В примере ниже скрипт загружает файл в форму и возвращает ссылку, которую можно использовать для заполнения полей типа «Файл», как показано в примере 2. Заполнение формы с помощью скрипта.

См. описание метода Загрузить файл для заполнения формы.

Рекомендуем настроить внешнее хранилище дя файлов, добавленных в ответы формы (см. Сохранять файлы из ответов в хранилище):

  • Для личных форм настройте хранение файлов на Яндекс Диске.
  • Если вы используете Формы для бизнеса, используйте хранилище S3 в Yandex Cloud.
Текст скрипта example_6.py
import os
import requests
import sys
from pathlib import Path

FORMS_PUBLIC_API = 'https://api.forms.yandex.net/v1'
FORMS_OAUTH_TOKEN = os.environ.get('FORMS_OAUTH_TOKEN')


def upload_file(survey_id: str, filename: Path) -> str:
    """
    Подгрузить файл, в результате получим ссылку для применения на сабмите
    """
    url = f'{FORMS_PUBLIC_API}/surveys/{survey_id}/files'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    with open(filename, 'rb') as f:
        files = [
            ('file', (filename.name, f.read(), 'application/octet-stream')),
        ]
    response = requests.post(url, files=files, headers=headers)
    if response.status_code == 201:
        result = response.json()
        return result.get('path')


def download_file(filepath: str) -> bytes:
    """
    Скачать подгруженный файл
    """
    url = f'{FORMS_PUBLIC_API}/files'
    headers = {'Authorization': f'OAuth {FORMS_OAUTH_TOKEN}'}
    params = {'path': filepath}
    response = requests.get(url, params=params, headers=headers)
    if response.status_code == 200:
        return response.content


def main():
    if len(sys.argv) < 3:
        return

    survey_id = sys.argv[1]
    filename = Path(sys.argv[2])
    uploaded_path = upload_file(survey_id, filename.expanduser())
    print(f'Путь подгруженного файла {uploaded_path}')

    content = download_file(uploaded_path)
    print(content)


if __name__ == '__main__':
    main()

Пример запуска скрипта:

$ echo 'Hello world' > hello.txt

$ FORMS_OAUTH_TOKEN=$(cat .user-token) python example_6.py 6800cd9202848f10b272a9cc hello.txt
Путь подгруженного файла /25871573/6800cd9202848f10b272a9cc/68061a8e381ea60011e104b3_hello.txt
b'Hello world\n'
Предыдущая
Следующая