📘 API Документация FreeFormApi

FreeFormApi предоставляет REST API для управления формами, ответами и профилем пользователя.

API работает с JSON-запросами и ответами. Все даты передаются в формате ISO 8601.

🌐 Базовый URL: https://freeformapi.ru/api

📦 Формат данных: JSON

🔤 Кодировка: UTF-8

⚠️ Важно: Все примеры используют переменную $TOKEN. Замените её на реальный токен, полученный при входе.

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

Для доступа к защищённым маршрутам необходимо передавать токен в заголовке запроса.

Заголовок запроса:

Authorization: Bearer {ваш_токен}

Токен можно получить при входе через POST /login. Токен действует до момента его отзыва через DELETE /tokens/{id} или POST /logout.

📋 Коды ответов

API возвращает стандартные HTTP статусы:

200

Успешный запрос

201

Успешно создано

401

Не авторизован

403

Доступ запрещён / Лимит

404

Ресурс не найден

410

Форма удалена (истек срок)

422

Ошибка валидации

429

Слишком много запросов

200 — Успешный запрос
201 — Ресурс успешно создан
401 — Отсутствует или недействительный токен
403 — Нет прав или достигнут лимит тарифа
404 — Запрашиваемый ресурс не найден
410 — Гостевая форма удалена (срок 30 дней)
422 — Ошибки валидации данных
429 — Превышен лимит запросов

🌐 Публичные маршруты

Эти маршруты не требуют токена авторизации.

POST /login

Вход пользователя. Возвращает токен для дальнейших запросов.

📤 Тело запроса:

{
    "email": "user@example.com",
    "password": "password123"
}

📥 Успешный ответ (200):

{
    "success": true,
    "message": "Вход выполнен успешно",
    "data": {
        "user": {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
            "name": "Иван Иванов",
            "email": "ivan@example.com",
            "is_admin": false,
            "is_blocked": false,
            "email_verified_at": "2026-08-14T10:00:00.000000Z",
            "plan": {
                "name": "pro",
                "display_name": "Pro",
                "forms_used": 12,
                "forms_limit": 20
            }
        },
        "token": "1|abc123def456...",
        "token_type": "Bearer"
    }
}

❌ Ошибка: неверные данные (401):

{
    "message": "Неверный email или пароль",
    "errors": {
        "email": ["Неверный email или пароль"]
    }
}

⚠️ Аккаунт заблокирован (403):

{
    "success": false,
    "error": "account_blocked",
    "message": "Ваш аккаунт заблокирован"
}

💡 Пример cURL:

curl -X POST https://freeformapi.ru/api/login \
  -H "Content-Type: application/json" \
  -d '{"email":"ivan@example.com","password":"password123"}'
GET /forms/{slug}/schema

Получить схему формы для заполнения. Возвращает все вопросы, типы, варианты ответов и настройки.

📤 Параметры пути:

slug — короткая ссылка формы (например, abc123)

📥 Успешный ответ (200):

{
    "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
    "title": "Опрос клиентов",
    "description": "Расскажите о своём опыте использования нашего сервиса",
    "is_anonymous": false,
    "settings": {
        "theme": "light",
        "show_progress": true
    },
    "questions": [
        {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755240",
            "title": "Как вы оцениваете наш сервис?",
            "type": "radio",
            "required": true,
            "options": ["Отлично", "Хорошо", "Средне", "Плохо"],
            "placeholder": null,
            "sort_order": 0
        },
        {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755241",
            "title": "Ваши пожелания",
            "type": "textarea",
            "required": false,
            "options": null,
            "placeholder": "Напишите здесь...",
            "sort_order": 1
        }
    ]
}

❌ Ошибки:

Форма удалена (410):

{
    "error": "form_expired",
    "message": "Форма удалена (истек срок хранения 30 дней)"
}

Форма заполнена (403):

{
    "error": "form_full",
    "message": "Форма достигла лимита ответов (100)"
}

Форма не найдена (404):

{
    "message": "No query results for model [App\\Models\\Form]"
}

💡 Пример cURL:

curl -X GET https://freeformapi.ru/api/forms/abc123/schema
POST /forms/{id}/submit

Отправить ответ на форму. Ограничение: 10 запросов в минуту с одного IP.

📤 Тело запроса:

{
    "answers": {
        "019e4e57-2c21-73c2-bd89-8310e3755240": "Отлично",
        "019e4e57-2c21-73c2-bd89-8310e3755241": "Всё отлично!",
        "019e4e57-2c21-73c2-bd89-8310e3755242": ["Вариант 1", "Вариант 3"]
    },
    "session_id": "optional-session-id"
}

Примечание: session_id — опционально, используется для отслеживания сессии.

📥 Успешный ответ (201):

{
    "success": true,
    "message": "Ответ успешно сохранён",
    "response_id": "019e4e57-2c21-73c2-bd89-8310e3755242",
    "warning": "Осталось всего 5 мест для ответов",
    "redirect": "https://example.com/thank-you"
}

Примечание: Поля warning и redirect появляются только при наличии соответствующих условий.

❌ Ошибки:

Форма заполнена (403):

{
    "error": "form_full",
    "message": "Эта форма достигла лимита ответов (100)"
}

Форма удалена (410):

{
    "error": "form_expired",
    "message": "Эта форма удалена, так как истёк срок хранения (30 дней)"
}

Ошибка валидации (422):

{
    "error": "validation_failed",
    "message": "Не все ответы прошли валидацию",
    "errors": [
        "Вопрос 'Ваш email' должен содержать корректный email",
        "Вопрос 'Как вы оцениваете?' обязателен для заполнения"
    ]
}

Превышен лимит запросов (429):

{
    "error": "daily_limit_reached",
    "message": "Вы достигли дневного лимита ответов (10) для этой формы",
    "limit": 10,
    "reset_at": "2026-08-15T10:00:00Z"
}

Также может вернуть rate_limit_exceeded с retry_after.

💡 Пример cURL:

curl -X POST https://freeformapi.ru/api/forms/019e4e57-2c21-73c2-bd89-8310e3755239/submit \
  -H "Content-Type: application/json" \
  -d '{
    "answers": {
        "019e4e57-2c21-73c2-bd89-8310e3755240": "Отлично",
        "019e4e57-2c21-73c2-bd89-8310e3755241": "Всё отлично!"
    }
}'

🔒 Защищённые маршруты

⚠️ Требуется авторизация: Передавайте токен в заголовке Authorization: Bearer {token}

POST /logout

Выход пользователя. Удаляет текущий токен.

📥 Успешный ответ (200):

{
    "success": true,
    "message": "Выход выполнен успешно"
}

💡 Пример cURL:

curl -X POST https://freeformapi.ru/api/logout \
  -H "Authorization: Bearer $TOKEN"
GET /me

Получить информацию о текущем пользователе.

📥 Успешный ответ (200):

{
    "success": true,
    "data": {
        "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
        "name": "Иван Иванов",
        "email": "ivan@example.com",
        "is_admin": false,
        "is_blocked": false,
        "email_verified_at": "2026-08-14T10:00:00.000000Z",
        "plan": {
            "name": "pro",
            "display_name": "Pro",
            "forms_used": 12,
            "forms_limit": 20
        },
        "created_at": "2026-08-14T10:00:00.000000Z"
    }
}

💡 Пример cURL:

curl -X GET https://freeformapi.ru/api/me \
  -H "Authorization: Bearer $TOKEN"
PUT /profile

Обновить профиль пользователя. Все поля опциональны.

📤 Тело запроса:

{
    "name": "Новое имя",
    "email": "new@example.com",
    "password": "newpassword123",
    "password_confirmation": "newpassword123"
}

Примечание: При смене email email_verified_at будет сброшен.

📥 Успешный ответ (200):

{
    "success": true,
    "message": "Профиль обновлён",
    "data": {
        "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
        "name": "Новое имя",
        "email": "new@example.com"
    }
}

💡 Пример cURL:

curl -X PUT https://freeformapi.ru/api/profile \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Новое имя","email":"new@example.com"}'
GET /tokens

Получить список всех API-токенов пользователя.

📥 Успешный ответ (200):

{
    "success": true,
    "data": [
        {
            "id": "1",
            "name": "api-token",
            "last_used_at": "2026-08-14T10:00:00.000000Z",
            "created_at": "2026-08-14T09:00:00.000000Z"
        },
        {
            "id": "2",
            "name": "mobile-app",
            "last_used_at": "2026-08-13T15:30:00.000000Z",
            "created_at": "2026-08-13T12:00:00.000000Z"
        }
    ]
}

💡 Пример cURL:

curl -X GET https://freeformapi.ru/api/tokens \
  -H "Authorization: Bearer $TOKEN"
DELETE /tokens/{tokenId}

Удалить (отозвать) конкретный токен. Токен перестанет работать.

📤 Параметры пути:

tokenId — ID токена (число, полученное из GET /tokens)

📥 Успешный ответ (200):

{
    "success": true,
    "message": "Токен удалён"
}

❌ Ошибка: токен не найден (404):

{
    "success": false,
    "message": "Токен не найден"
}

💡 Пример cURL:

curl -X DELETE https://freeformapi.ru/api/tokens/1 \
  -H "Authorization: Bearer $TOKEN"
GET /forms

Получить список всех форм пользователя. Поддерживает пагинацию.

📤 Параметры запроса (опционально):

per_page — количество форм на странице (по умолчанию 20)
page — номер страницы (по умолчанию 1)

📥 Успешный ответ (200):

{
    "success": true,
    "data": [
        {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
            "title": "Опрос клиентов",
            "description": "Расскажите о своём опыте",
            "slug": "abc123",
            "is_anonymous": false,
            "max_responses": 100,
            "current_responses": 45,
            "created_at": "2026-08-14T10:00:00.000000Z",
            "updated_at": "2026-08-14T10:00:00.000000Z",
            "group": {
                "id": "019e4e57-2c21-73c2-bd89-8310e3755240",
                "name": "Маркетинг",
                "team": {
                    "id": "019e4e57-2c21-73c2-bd89-8310e3755241",
                    "name": "Acme Inc"
                }
            }
        },
        {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755242",
            "title": "Форма обратной связи",
            "description": null,
            "slug": "def456",
            "is_anonymous": false,
            "max_responses": 50,
            "current_responses": 12,
            "created_at": "2026-08-13T15:00:00.000000Z",
            "updated_at": "2026-08-13T15:00:00.000000Z",
            "group": null
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 3,
        "per_page": 20,
        "total": 45
    }
}

💡 Пример cURL:

curl -X GET https://freeformapi.ru/api/forms?per_page=10&page=2 \
  -H "Authorization: Bearer $TOKEN"
POST /forms

Создать новую форму. Количество форм ограничено тарифом.

📤 Тело запроса:

{
    "title": "Опрос клиентов",
    "description": "Расскажите о своём опыте использования нашего сервиса",
    "group_id": "019e4e57-2c21-73c2-bd89-8310e3755240",
    "settings": {
        "theme": "light",
        "show_progress": true
    },
    "questions": [
        {
            "title": "Как вы оцениваете наш сервис?",
            "type": "radio",
            "required": true,
            "options": ["Отлично", "Хорошо", "Средне", "Плохо"],
            "placeholder": null
        },
        {
            "title": "Ваши пожелания",
            "type": "textarea",
            "required": false,
            "options": null,
            "placeholder": "Напишите здесь..."
        },
        {
            "title": "Выберите категории",
            "type": "checkbox",
            "required": false,
            "options": ["Категория А", "Категория Б", "Категория В"]
        }
    ]
}

Примечание: Поля group_id, settings и placeholder — опциональны.

📥 Успешный ответ (201):

{
    "success": true,
    "message": "Форма успешно создана",
    "data": {
        "form": {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755242",
            "title": "Опрос клиентов",
            "slug": "xyz789",
            "created_at": "2026-08-14T10:00:00.000000Z"
        },
        "fill_url": "https://freeformapi.ru/f/xyz789",
        "short_url": "https://q4m.ru/f/xyz789"
    }
}

❌ Ошибка: достигнут лимит форм (403):

{
    "success": false,
    "error": "limit_reached",
    "message": "Вы достигли лимита форм (20) для вашего тарифа",
    "max_forms": 20,
    "current_forms": 20
}

💡 Пример cURL:

curl -X POST https://freeformapi.ru/api/forms \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Опрос клиентов",
    "questions": [
        {"title": "Ваш email", "type": "email", "required": true}
    ]
}'
GET /forms/{id}

Получить полную информацию о форме для редактирования.

📤 Параметры пути:

id — UUID формы

📥 Успешный ответ (200):

{
    "success": true,
    "data": {
        "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
        "title": "Опрос клиентов",
        "description": "Расскажите о своём опыте",
        "slug": "abc123",
        "settings": {
            "theme": "light"
        },
        "is_anonymous": false,
        "expires_at": null,
        "max_responses": 100,
        "current_responses": 45,
        "created_at": "2026-08-14T10:00:00.000000Z",
        "updated_at": "2026-08-14T10:00:00.000000Z",
        "group": {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755240",
            "name": "Маркетинг"
        },
        "user": {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
            "name": "Иван Иванов",
            "email": "ivan@example.com"
        },
        "questions": [
            {
                "id": "019e4e57-2c21-73c2-bd89-8310e3755243",
                "title": "Как вы оцениваете сервис?",
                "type": "radio",
                "sort_order": 0,
                "required": true,
                "options": ["Отлично", "Хорошо", "Средне", "Плохо"],
                "placeholder": null
            }
        ]
    }
}

💡 Пример cURL:

curl -X GET https://freeformapi.ru/api/forms/019e4e57-2c21-73c2-bd89-8310e3755239 \
  -H "Authorization: Bearer $TOKEN"
PUT /forms/{id}

Обновить форму. Все поля опциональны. Можно обновлять вопросы.

📤 Тело запроса:

{
    "title": "Новое название",
    "description": "Новое описание",
    "max_responses": 200,
    "group_id": "019e4e57-2c21-73c2-bd89-8310e3755244",
    "questions": [
        {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755243",
            "title": "Обновлённый вопрос",
            "type": "text",
            "required": true
        },
        {
            "title": "Новый вопрос",
            "type": "textarea",
            "required": false
        }
    ]
}

Примечание: Если передан массив questions, старые вопросы будут удалены, а новые созданы или обновлены.

📥 Успешный ответ (200):

{
    "success": true,
    "message": "Форма успешно обновлена",
    "data": {
        "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
        "title": "Новое название",
        "updated_at": "2026-08-14T10:00:00.000000Z"
    }
}

💡 Пример cURL:

curl -X PUT https://freeformapi.ru/api/forms/019e4e57-2c21-73c2-bd89-8310e3755239 \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Новое название"}'
DELETE /forms/{id}

Удалить форму вместе со всеми ответами и вопросами. Необратимо!

📥 Успешный ответ (200):

{
    "success": true,
    "message": "Форма 'Опрос клиентов' успешно удалена"
}

💡 Пример cURL:

curl -X DELETE https://freeformapi.ru/api/forms/019e4e57-2c21-73c2-bd89-8310e3755239 \
  -H "Authorization: Bearer $TOKEN"
POST /forms/{id}/duplicate

Клонировать форму со всеми вопросами. Новая форма получает суффикс " (копия)".

📥 Успешный ответ (201):

{
    "success": true,
    "message": "Форма успешно скопирована",
    "data": {
        "form": {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755245",
            "title": "Опрос клиентов (копия)",
            "slug": "new123",
            "created_at": "2026-08-14T10:00:00.000000Z"
        },
        "fill_url": "https://freeformapi.ru/f/new123",
        "short_url": "https://q4m.ru/f/new123"
    }
}

❌ Ошибка: достигнут лимит форм (403):

{
    "success": false,
    "error": "limit_reached",
    "message": "Вы достигли лимита форм (20) для вашего тарифа",
    "max_forms": 20,
    "current_forms": 20
}

💡 Пример cURL:

curl -X POST https://freeformapi.ru/api/forms/019e4e57-2c21-73c2-bd89-8310e3755239/duplicate \
  -H "Authorization: Bearer $TOKEN"
GET /forms/{id}/responses

Получить список ответов на форму с фильтрацией и пагинацией.

📤 Параметры запроса (опционально):

date_from — дата "от" (YYYY-MM-DD)
date_to — дата "до" (YYYY-MM-DD)
sort_by — поле для сортировки (created_at, id, ip)
sort_dir — направление сортировки (asc или desc)
per_page — количество на странице (по умолчанию 20)

📥 Успешный ответ (200):

{
    "success": true,
    "data": [
        {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755246",
            "form_id": "019e4e57-2c21-73c2-bd89-8310e3755239",
            "answers": {
                "019e4e57-2c21-73c2-bd89-8310e3755240": "Отлично",
                "019e4e57-2c21-73c2-bd89-8310e3755241": "Всё отлично!"
            },
            "is_encrypted": false,
            "ip": "185.38.84.237",
            "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
            "is_read": false,
            "created_at": "2026-08-14T10:00:00.000000Z",
            "updated_at": "2026-08-14T10:00:00.000000Z"
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 3,
        "per_page": 20,
        "total": 45
    }
}

💡 Пример cURL:

curl -X GET "https://freeformapi.ru/api/forms/019e4e57-2c21-73c2-bd89-8310e3755239/responses?date_from=2026-08-01&date_to=2026-08-14&per_page=50" \
  -H "Authorization: Bearer $TOKEN"
GET /responses/{id}

Получить один ответ по ID.

📥 Успешный ответ (200):

{
    "success": true,
    "data": {
        "id": "019e4e57-2c21-73c2-bd89-8310e3755246",
        "form_id": "019e4e57-2c21-73c2-bd89-8310e3755239",
        "answers": {
            "019e4e57-2c21-73c2-bd89-8310e3755240": "Отлично"
        },
        "is_encrypted": false,
        "ip": "185.38.84.237",
        "user_agent": "Mozilla/5.0...",
        "is_read": false,
        "created_at": "2026-08-14T10:00:00.000000Z",
        "form": {
            "id": "019e4e57-2c21-73c2-bd89-8310e3755239",
            "title": "Опрос клиентов",
            "slug": "abc123"
        }
    }
}

💡 Пример cURL:

curl -X GET https://freeformapi.ru/api/responses/019e4e57-2c21-73c2-bd89-8310e3755246 \
  -H "Authorization: Bearer $TOKEN"
DELETE /responses/{id}

Удалить ответ. Счётчик ответов формы уменьшится.

📥 Успешный ответ (200):

{
    "success": true,
    "message": "Ответ успешно удалён"
}

💡 Пример cURL:

curl -X DELETE https://freeformapi.ru/api/responses/019e4e57-2c21-73c2-bd89-8310e3755246 \
  -H "Authorization: Bearer $TOKEN"
GET /forms/{id}/export/csv

Экспортировать ответы в CSV файл. Поддерживает фильтрацию по датам.

📤 Параметры запроса (опционально):

date_from — дата "от" (YYYY-MM-DD)
date_to — дата "до" (YYYY-MM-DD)

📥 Ответ:

Файл responses_{slug}_{date}.csv скачивается автоматически.

Структура CSV: ID, Дата, IP, User Agent, [вопросы формы...]

💡 Пример cURL:

curl -X GET "https://freeformapi.ru/api/forms/019e4e57-2c21-73c2-bd89-8310e3755239/export/csv?date_from=2026-08-01&date_to=2026-08-14" \
  -H "Authorization: Bearer $TOKEN" \
  --output responses.csv

🚀 Быстрый старт (пошагово)

1

Получите токен:

curl -X POST https://freeformapi.ru/api/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password123"}'

Сохраните токен из ответа: TOKEN="1|abc123..."

2

Создайте форму:

curl -X POST https://freeformapi.ru/api/forms \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Моя первая форма",
    "questions": [
        {"title": "Ваше имя", "type": "text", "required": true}
    ]
}'

Запомните slug из ответа.

3

Заполните форму (публичный маршрут):

curl -X POST https://freeformapi.ru/api/forms/{form_id}/submit \
  -H "Content-Type: application/json" \
  -d '{
    "answers": {
        "question_id": "Иван Иванов"
    }
}'
4

Получите ответы:

curl -X GET https://freeformapi.ru/api/forms/{form_id}/responses \
  -H "Authorization: Bearer $TOKEN"