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

Всё необходимое для интеграции YesSigned в ваше приложение.

Обзор

API YesSigned позволяет программно создавать и управлять соглашениями, шаблонами, вебхуками и API-токенами. Все эндпоинты возвращают JSON-ответы и используют стандартные HTTP-коды состояния.

Базовый URL
https://api.yessigned.com/api/v1

Все запросы должны содержать заголовок:

Content-Type: application/json
Accept: application/json

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

API использует аутентификацию Bearer-токеном через Laravel Sanctum. Включайте ваш API-токен в заголовок Authorization каждого запроса.

Header
Authorization: Bearer YOUR_API_TOKEN

Вы можете сгенерировать API-токены через API токенов или через Telegram-бота. Токены привязаны к вашему аккаунту и наследуют лимиты вашего тарифа.

Если токен отсутствует или недействителен, API возвращает:

401 Unauthorized
{
    "message": "Unauthenticated."
}

Лимиты запросов

API-запросы ограничены для защиты платформы. Лимит по умолчанию — 60 запросов в минуту на токен.

Заголовки лимитов включены в каждый ответ:

Response Headers
X-RateLimit-Limit: 60        // Ваш лимит в минуту
X-RateLimit-Remaining: 58    // Оставшиеся запросы в текущем окне

При превышении лимита API возвращает:

429 Too Many Requests
{
    "message": "Too Many Attempts.",
    "retry_after": 30
}

Соглашения

Создавайте, получайте, отправляйте и отменяйте соглашения программно.

Эндпоинты

GET /api/v1/agreements

Возвращает постраничный список ваших соглашений.

Параметры
pageНомер страницы (по умолчанию: 1)
per_pageЭлементов на странице (по умолчанию: 20, макс: 100)
statusФильтр по статусу: draft, pending, confirmed, disputed, expired
GET /api/v1/agreements/{id}

Возвращает одно соглашение с участниками и подтверждениями.

POST /api/v1/agreements

Создаёт новое соглашение в статусе черновика.

Параметры
titleНазвание соглашения (обязательно, макс. 255 символов)
bodyПолный текст соглашения (обязательно)
deadlineДата дедлайна в формате ISO 8601 (необязательно)
template_idID шаблона для использования (необязательно)
Запрос
{
    "title": "NDA Agreement",
    "body": "Both parties agree to...",
    "deadline": "2025-12-31T23:59:59Z"
}
POST /api/v1/agreements/{id}/send

Отправляет черновик соглашения участникам. Меняет статус на «ожидание».

POST /api/v1/agreements/{id}/cancel

Отменяет ожидающее соглашение. Только создатель может отменить.

Шаблоны

Управляйте переиспользуемыми шаблонами соглашений для вашей команды.

Эндпоинты

GET /api/v1/templates

Возвращает все шаблоны вашего аккаунта.

GET /api/v1/templates/{id}

Возвращает один шаблон по ID.

POST /api/v1/templates

Создаёт новый шаблон соглашения.

Параметры
nameНазвание шаблона (обязательно, макс. 255 символов)
bodyТело шаблона с плейсхолдерами (обязательно)
PUT /api/v1/templates/{id}

Обновляет существующий шаблон.

DELETE /api/v1/templates/{id}

Безвозвратно удаляет шаблон.

Вебхуки

Регистрируйте эндпоинты вебхуков для получения уведомлений о событиях соглашений в реальном времени.

Эндпоинты

GET /api/v1/webhooks

Возвращает все зарегистрированные эндпоинты вебхуков.

GET /api/v1/webhooks/{id}

Возвращает один эндпоинт вебхука с историей доставки.

POST /api/v1/webhooks

Регистрирует новый эндпоинт вебхука.

Параметры
urlHTTPS URL эндпоинта (обязательно)
eventsМассив типов событий для подписки (обязательно)
secretСекрет подписи для HMAC-верификации (необязательно, генерируется автоматически)
Запрос
{
    "url": "https://example.com/webhooks/yessigned",
    "events": [
        "agreement.created",
        "agreement.confirmed"
    ]
}
PUT /api/v1/webhooks/{id}

Обновляет конфигурацию эндпоинта вебхука.

DELETE /api/v1/webhooks/{id}

Удаляет эндпоинт вебхука. Ожидающие доставки будут отменены.

API-токены

Управляйте API-токенами для аутентификации. Каждый токен привязан к вашему аккаунту.

Эндпоинты

GET /api/v1/tokens

Возвращает все активные API-токены вашего аккаунта.

POST /api/v1/tokens

Создаёт новый API-токен. Токен в открытом виде возвращается только один раз.

Параметры
nameНазвание токена для идентификации (обязательно)

Сохраните токен в надёжном месте — его нельзя получить повторно.

Ответ
{
    "token": "1|a3kD9f...",
    "name": "my-integration",
    "created_at": "2025-06-15T10:30:00Z"
}
DELETE /api/v1/tokens/{id}

Отзывает API-токен. Он немедленно перестанет работать.

События вебхуков

При наступлении подписанных событий YesSigned отправляет POST-запрос на ваш URL вебхука с JSON-полезной нагрузкой.

Типы событий

agreement.created Срабатывает при создании нового соглашения.
agreement.confirmed Срабатывает, когда все участники подтвердят соглашение.
agreement.cancelled Срабатывает при отмене соглашения создателем.
agreement.disputed Срабатывает, когда участник открывает спор.

Формат полезной нагрузки

Все полезные нагрузки вебхуков имеют следующую структуру:

Webhook Payload
{
    "event": "agreement.confirmed",
    "timestamp": "2025-06-15T10:30:00Z",
    "data": {
        "id": 42,
        "title": "NDA Agreement",
        "status": "confirmed",
        "confirmed_at": "2025-06-15T10:30:00Z",
        "participants": [
            { "user_id": 1, "role": "creator" },
            { "user_id": 5, "role": "participant" }
        ]
    }
}

Проверка подписи вебхуков

Каждый запрос вебхука содержит заголовок X-Signature с HMAC-SHA256 подписью. Используйте её для проверки, что запрос отправлен YesSigned и не был изменён.

Как это работает

YesSigned подписывает тело JSON-запроса с помощью секретного ключа вашего вебхука алгоритмом HMAC-SHA256. Полученный hex-дайджест отправляется в заголовке X-Signature.

  1. Прочитайте сырое тело запроса (не парсите JSON до проверки)
  2. Вычислите HMAC-SHA256 тела с использованием секрета вебхука
  3. Сравните вычисленную подпись с заголовком X-Signature

Примеры кода

PHP
$payload = file_get_contents('php://input');
$secret  = 'your-webhook-secret';

$expected = hash_hmac('sha256', $payload, $secret);
$signature = $_SERVER['HTTP_X_SIGNATURE'];

if (!hash_equals($expected, $signature)) {
    http_response_code(403);
    exit('Invalid signature');
}

// hash_equals() is timing-safe
$data = json_decode($payload, true);
Python
import hmac, hashlib

payload   = request.get_data()
secret    = b'your-webhook-secret'
signature = request.headers.get('X-Signature')

expected = hmac.new(
    secret, payload, hashlib.sha256
).hexdigest()

if not hmac.compare_digest(expected, signature):
    abort(403)

# hmac.compare_digest() is timing-safe
data = request.get_json()
Node.js
const crypto = require('crypto');

const payload   = req.rawBody;
const secret    = 'your-webhook-secret';
const signature = req.headers['x-signature'];

const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

const valid = crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
);

if (!valid) return res.status(403).send('Invalid signature');

// crypto.timingSafeEqual() prevents timing attacks
const data = JSON.parse(payload);

Всегда используйте функцию сравнения с постоянным временем выполнения для предотвращения атак по времени. Никогда не используйте простое сравнение строк (== или ===) для сравнения подписей.