Отправка результата теста
POST https://openspeedtest.ru/api.php?action=submit-result
Сохраняет результат измерения (обычно из CLI). Запрос защищён API-ключом, HMAC-подписью тела, свежестью timestamp и привязками ключа.
Заголовки
| Заголовок | Обязательный | Описание |
|---|---|---|
Content-Type | да | application/json |
X-API-KEY | да | API-ключ |
X-SIGNATURE | да | HMAC-SHA256 подписи (hex) |
Строка подписи
dl=%.2f:ul=%.2f:ping=%.2f:jitter=%.2f:timestamp=%s
Значения округляются до двух знаков после запятой. Пример:
dl=123.45:ul=67.89:ping=12.34:jitter=1.23:timestamp=1770000000
Подпись = HMAC-SHA256(строка, API-ключ) в hex. Ключом подписи служит сам API-ключ.
Тело запроса (JSON)
| Поле | Обязательное | Тип | Описание |
|---|---|---|---|
dl | да | number | Скачивание, Мбит/с |
ul | да | number | Отдача, Мбит/с |
ping | да | number | Пинг, мс |
jitter | да | number | Джиттер, мс |
timestamp | да | int/str | Unix-время; допустимо отклонение ≤ 300 с |
server_id | нет | int | ID тестового сервера |
source | нет | string | cli (по умолчанию) или widget |
Пример
bashKEY="ВАШ_КЛЮЧ"
TS="$(date +%s)"
DL="123.45"; UL="67.89"; PING="12.34"; JITTER="1.23"
SIG_STRING="dl=$(printf '%.2f' "$DL"):ul=$(printf '%.2f' "$UL"):ping=$(printf '%.2f' "$PING"):jitter=$(printf '%.2f' "$JITTER"):timestamp=$TS"
SIGNATURE=$(printf '%s' "$SIG_STRING" | openssl dgst -sha256 -hmac "$KEY" -r | awk '{print $1}')
curl -X POST "https://openspeedtest.ru/api.php?action=submit-result" \
-H "Content-Type: application/json" \
-H "X-API-KEY: $KEY" \
-H "X-SIGNATURE: $SIGNATURE" \
-d "{\"dl\":$DL,\"ul\":$UL,\"ping\":$PING,\"jitter\":$JITTER,\"timestamp\":\"$TS\",\"server_id\":12,\"source\":\"cli\"}"
Ответ (200)
json{
"success": true,
"message": "Result saved successfully. Thank you for contributing!",
"result_id": "123456"
}
Порядок проверок
- метод не
POST→ 405; - нет
X-API-KEY→ 401; - ключ не найден → 403
Invalid API Key.; - лимит по IP: 50 отправок в час → 429
You are submitting results too frequently.; - отсутствует обязательное поле → 400
Missing field in payload: <field>; - неверная подпись → 403
Invalid request signature. Data may have been tampered with.; timestampстарше 300 с → 400Request timestamp is too old.;- при
source=widgetпроверяется домен, приsource=cli— IP (если заданallowed_ip); - квота аккаунта → 429.
Техническая деталь
Подпись проверяется через сравнение, устойчивое к атакам по времени. Привязка allowed_ip действует только для source=cli, привязка allowed_domains — для source=widget. Результат сохраняется с провайдером и городом, определёнными по IP запроса. Дополнительно к квоте действует защитный лимит 50 отправок в час с одного IP.