API статуса PIN
GET /v1/pins/:pinCode/status
API статуса PIN позволяет следить за ходом сканирования в реальном времени. Он возвращает текущий статус, процент выполнения, сообщение о статусе и сводные результаты после завершения. Подходит для индикаторов прогресса, живых дашбордов и интеграций с Discord-ботами.
- Базовый URL
https://api.anticheat.ac/v1- Аутентификация
- Требуется API-ключ с разрешением
pins:status
Получить статус PIN
Получите текущий статус сканирования для конкретного PIN, включая процент выполнения и сообщение о статусе. Доступ есть только к статусу PIN, которыми вы владеете (созданным вашим аккаунтом). После завершения сканирования ответ также содержит сводку результатов с количеством детектов.
GET/v1/pins/:pinCode/status
Параметры
| Название | Тип | Описание |
|---|---|---|
| pinCode | string | 8-символьный код PIN (например, A7K3M2P9) |
Заголовки
x-api-key: your_api_key_here
Ответ (ожидание)
{
"pin": "A7K3M2P9",
"pinName": "Tournament Match #42",
"type": "Java",
"status": "pending",
"progress": 0,
"statusMessage": null,
"result": null,
"used": false,
"lastStatusUpdate": null,
"createdAt": "2026-02-11T15:25:00.000Z",
"isFinished": false,
"isScanning": false,
"isPending": true
}Ответ (сканирование — в процессе)
{
"pin": "A7K3M2P9",
"pinName": "Tournament Match #42",
"type": "Java",
"status": "scanning",
"progress": 45,
"statusMessage": "Scanning system files... (45%)",
"result": null,
"used": true,
"lastStatusUpdate": "2026-02-11T15:30:00.000Z",
"createdAt": "2026-02-11T15:25:00.000Z",
"isFinished": false,
"isScanning": true,
"isPending": false
}Ответ (завершено)
После завершения сканирования ответ содержит data объект со сводкой количества детектов. Полные данные об обнаружениях смотрите в эндпоинте результатов PIN.
{
"pin": "A7K3M2P9",
"pinName": "Tournament Match #42",
"type": "Java",
"status": "finished",
"progress": 100,
"statusMessage": "Scan completed",
"result": "cheating",
"used": true,
"lastStatusUpdate": "2026-02-11T15:35:00.000Z",
"createdAt": "2026-02-11T15:25:00.000Z",
"isFinished": true,
"isScanning": false,
"isPending": false,
"data": {
"cheating": "cheating",
"vpn": "No",
"country": "US",
"scantime": "45 seconds",
"windows": "Windows 11 Pro 23H2",
"detectionsCount": 3,
"warningsCount": 1,
"suspiciousCount": 2,
"discord": [
{ "id": "123456789012345678", "username": "player123" }
]
}
}Поля ответа
| Поле | Тип | Описание |
|---|---|---|
| pin | string | 8-символьный код PIN |
| pinName | string | null | Своё название, присвоенное PIN |
| type | string | Тип сканирования (Java, Bedrock, FiveM и т. д.) |
| status | string | Текущий статус: pending, scanning, finished, expired или error |
| progress | number | Ход сканирования от 0 до 100 |
| statusMessage | string | null | Понятное сообщение о текущем этапе сканирования |
| result | string | null | Вердикт сканирования: legit, cheating, suspicious или null, если не завершено |
| used | boolean | Использован ли PIN (началось ли сканирование) |
| lastStatusUpdate | string | null | Метка времени ISO 8601 последнего обновления статуса |
| createdAt | string | Метка времени ISO 8601, когда был создан PIN |
| isFinished | boolean | Удобный флаг: true, когда статус равен "finished" |
| isScanning | boolean | Удобный флаг: true, когда статус равен "scanning" |
| isPending | boolean | Удобный флаг: true, когда статус равен "pending" |
Поля данных (только после завершения)
| Поле | Тип | Описание |
|---|---|---|
| cheating | string | null | Общий вердикт о читерстве |
| vpn | string | null | Статус обнаружения VPN |
| country | string | null | Страна проверяемого пользователя |
| scantime | string | null | Сколько длилось сканирование |
| windows | string | null | Информация о версии Windows |
| detectionsCount | number | Число подтверждённых детектов читов |
| warningsCount | number | Число флагов предупреждений |
| suspiciousCount | number | Число подозрительных находок |
| discord | array | Обнаруженные аккаунты Discord. Каждая запись содержит id и username |
Ответы с ошибками
| Статус | Код | Описание |
|---|---|---|
400 | Неверный запрос | Код PIN пуст или недействителен |
403 | Доступ запрещён | Этот PIN не принадлежит вашему аккаунту |
404 | Не найдено | Код PIN не существует |
Нужно быть владельцем
Вы можете получать статус только для PIN, созданных вашим аккаунтом. При попытке получить доступ к PIN другого пользователя API вернёт ошибку 403 Forbidden.
Отличие от результатов PIN
Этот эндпоинт оптимизирован для опроса во время сканирования. Он возвращает данные о ходе выполнения и лёгкую сводку после завершения. Полные данные об обнаружениях (отдельные детекты, подозрительные элементы, предупреждения, проверки целостности) смотрите в эндпоинте результатов PIN после завершения сканирования.
Стратегия опроса
Поскольку сканирование занимает время, опрашивайте этот эндпоинт периодически, чтобы отслеживать прогресс. Рекомендуемые стратегии:
| Стратегия | Интервал | Применение |
|---|---|---|
| Индикатор прогресса | 3–5 секунд | Отображение прогресса в реальном времени в интерфейсе или во встраивании Discord |
| Фоновая проверка | 10–15 секунд | Бот ждёт результатов, чтобы отправить уведомление |
| Пакетный мониторинг | 30–60 секунд | Одновременный мониторинг множества PIN |
Учёт лимита запросов
API допускает 1 000 запросов в час на API-ключ. Если опрашивать каждые 3 секунды, сканирование одного PIN расходует около 20 запросов в минуту. Выбирайте интервал опроса с учётом того, сколько PIN вы отслеживаете одновременно.
Пример использования
cURL
curl -X GET "https://api.anticheat.ac/v1/pins/A7K3M2P9/status" \ -H "x-api-key: your_api_key_here"
JavaScript / Node.js
const response = await fetch('https://api.anticheat.ac/v1/pins/A7K3M2P9/status', {
headers: { 'x-api-key': 'your_api_key_here' }
});
const data = await response.json();
console.log('Status:', data.status);
console.log('Progress:', data.progress + '%');
console.log('Message:', data.statusMessage);
if (data.isFinished) {
console.log('Result:', data.result);
console.log('Detections:', data.data.detectionsCount);
}Python
import requests
response = requests.get(
'https://api.anticheat.ac/v1/pins/A7K3M2P9/status',
headers={'x-api-key': 'your_api_key_here'}
)
data = response.json()
print(f"Status: {data['status']}")
print(f"Progress: {data['progress']}%")
print(f"Message: {data.get('statusMessage', 'N/A')}")
if data['isFinished']:
print(f"Result: {data['result']}")
print(f"Detections: {data['data']['detectionsCount']}")Опрос с индикатором прогресса (JavaScript)
async function pollPinStatus(pinCode, apiKey, onProgress) {
const url = 'https://api.anticheat.ac/v1/pins/' + pinCode + '/status';
const headers = { 'x-api-key': apiKey };
while (true) {
const res = await fetch(url, { headers });
const data = await res.json();
onProgress({
status: data.status,
progress: data.progress,
message: data.statusMessage,
});
if (data.isFinished) return data;
if (data.status === 'expired' || data.status === 'error') {
throw new Error('Scan ' + data.status);
}
await new Promise(r => setTimeout(r, 3000));
}
}
const result = await pollPinStatus('A7K3M2P9', 'your_api_key_here', (info) => {
console.log('[' + info.progress + '%] ' + info.message);
});
console.log('Final result:', result.result);
console.log('Detections:', result.data.detectionsCount);Пример Discord-бота (discord.js)
const { EmbedBuilder } = require('discord.js');
async function trackScan(channel, pinCode, apiKey) {
const url = 'https://api.anticheat.ac/v1/pins/' + pinCode + '/status';
const headers = { 'x-api-key': apiKey };
const embed = new EmbedBuilder()
.setTitle('Scan: ' + pinCode)
.setDescription('Starting scan...')
.setColor(0x3498db);
const msg = await channel.send({ embeds: [embed] });
const interval = setInterval(async () => {
try {
const res = await fetch(url, { headers });
const data = await res.json();
const bar = '\u2588'.repeat(Math.floor(data.progress / 5))
+ '\u2591'.repeat(20 - Math.floor(data.progress / 5));
embed.setDescription(
bar + ' ' + data.progress + '%\n'
+ (data.statusMessage || 'Waiting...')
);
if (data.isFinished) {
clearInterval(interval);
embed.setColor(data.result === 'legit' ? 0x2ecc71 : 0xe74c3c);
embed.addFields(
{ name: 'Result', value: data.result, inline: true },
{ name: 'Detections', value: String(data.data.detectionsCount), inline: true },
{ name: 'Warnings', value: String(data.data.warningsCount), inline: true },
);
}
await msg.edit({ embeds: [embed] });
} catch (err) {
clearInterval(interval);
embed.setDescription('Error: ' + err.message).setColor(0xe74c3c);
await msg.edit({ embeds: [embed] });
}
}, 5000);
}