skopio
← К тарифам

Skopio API

B2B OSINT-движок через простой REST. Bearer-авторизация, JSON in/out, единая cтоимость за тариф.

Авторизация

Все эндпоинты требуют заголовок Authorization: Bearer skopio_live_xxx. Ключи выдаются вручную после подписания договора. Хранятся в виде SHA-256 хеша; plaintext показывается один раз при выпуске.

Authorization: Bearer skopio_live_arEvkb...JU1M

Эндпоинты

POST/api/v1/scan

Создаёт запрос и ставит его в очередь движка. ETA обычно 60-180 секунд.

curl -X POST https://skopio.io/api/v1/scan \
  -H "Authorization: Bearer skopio_live_..." \
  -H "Content-Type: application/json" \
  -d '{"target":"john@example.com","kind":"email"}'

# Response 202
{
  "ok": true,
  "scan_id": "req-mp9ne00k-14242242",
  "kind": "email",
  "recipes_to_run": 6,
  "eta_seconds": 180,
  "poll_url": "https://skopio.io/api/v1/scan/req-mp9ne00k-14242242"
}
GET/api/v1/scan/{id}

Опрашивайте каждые 10-15 секунд. Когда status=completed — payload готов.

curl https://skopio.io/api/v1/scan/req-mp9ne00k-14242242 \
  -H "Authorization: Bearer skopio_live_..."

# Response (status=completed)
{
  "ok": true,
  "scan_id": "req-...",
  "status": "completed",
  "target": "john@example.com",
  "kind": "email",
  "completed_at": "2026-05-17T12:34:56Z",
  "result": {
    "risk": {"score": 65, "band": "medium"},
    "counts": {"cases": 6, "entities": 192, "findings": 187},
    "profiles": {"verified": [...], "weak": [...]},
    "contacts":  {"emails": [...], "phones": [...]},
    "breaches":  [{"name":"LinkedIn","date":"2016-05","accounts":117000000,"classes":["Email","Password"]}],
    "phone_profile": null,
    "ai_summary": "Email фигурирует в 3 утечках...",
    "artifacts": {"pdf": "...", "person_card": "..."}
  }
}

Поддерживаемые типы целей

email
john@example.com
phone
+15551234567
username
johndoe

Лимиты по тарифу

TierScans / day/ hourInflightBest for
Pro 100 20 3 Pro — индивидуальные интеграции, freelance security, журналисты.
Business 1,000 100 10 Business — агентства, HR-проверки списков кандидатов, due diligence, threat intel.
Enterprise10,00050025 Enterprise — fraud detection, SOC, мониторинг крупных баз клиентов. SLA + dedicated support.

Тарифы определяют ТОЛЬКО пропускную способность. Каждый API-вызов списывает 1 кредит с баланса аккаунта — независимо от тарифа. Превышение rate-limit возвращает 429 без списания. Балланс < 1 → 402 insufficient_balance.

Коды ошибок

HTTPerrorMeaning
401unauthorized Missing or malformed Bearer header
401invalid_token Token not found or revoked
400target_too_short target must be ≥ 3 chars
429rate_limit_inflightToo many concurrent scans
429rate_limit_hour Hourly quota exceeded
429rate_limit_day Daily quota exceeded
403forbidden Scan belongs to another customer
502engine_submit_failedEngine unreachable; retry in 30s

Bulk-поиск (до 100 целей за один вызов)

Business/Enterprise тарифы. Один POST → массив scan_id с общим bulk_id. Каждый scan завершается независимо (свой webhook), все webhooks содержат поле bulk_id чтобы вы могли группировать. Также есть aggregate GET endpoint чтобы опросить весь batch одним вызовом вместо N.

POST/api/v1/scan/bulk
curl -X POST https://skopio.io/api/v1/scan/bulk \
  -H "Authorization: Bearer skopio_live_..." \
  -H "Content-Type: application/json" \
  -d '{"targets":[
    {"target":"alice@example.com","kind":"email"},
    {"target":"bob@example.com","kind":"email"},
    {"target":"+15551234567","kind":"phone"}
  ]}'

# Response 202
{
  "ok": true,
  "bulk_id": "bulk_xxx",
  "total": 3,
  "queued": 3,
  "rejected": [],
  "scans": [
    {"scan_id":"req-aaa","target":"alice@example.com","kind":"email","poll_url":"..."},
    {"scan_id":"req-bbb","target":"bob@example.com","kind":"email","poll_url":"..."},
    {"scan_id":"req-ccc","target":"+15551234567","kind":"phone","poll_url":"..."}
  ],
  "aggregate_poll_url": "https://skopio.io/api/v1/scan/bulk/bulk_xxx"
}
GET/api/v1/scan/bulk/{bulk_id}
# Aggregate poll — one call returns all scans in the batch
curl https://skopio.io/api/v1/scan/bulk/bulk_xxx \
  -H "Authorization: Bearer skopio_live_..."

# Response 200
{
  "ok": true,
  "bulk_id": "bulk_xxx",
  "total": 3,
  "queued": 1,
  "running": 0,
  "completed": 2,
  "failed": 0,
  "all_done": false,
  "scans": [
    {"scan_id":"req-aaa","status":"completed","target":"alice@example.com","result":{...}},
    {"scan_id":"req-bbb","status":"completed","target":"bob@example.com","result":{...}},
    {"scan_id":"req-ccc","status":"queued","target":"+15551234567"}
  ]
}
  • Max 100 targets per bulk call.
  • Rate limits: bulk_size + current_inflight must fit your tier (e.g. Business = 10 inflight). Also counts against rate/hour and rate/day.
  • Invalid targets land in rejected[]; valid ones still get queued.
  • Each scan completes independently. If a webhook is configured, every per-scan webhook carries the shared bulk_id field so you can group them.

Webhooks (push, без polling)

Настройте URL в /app/api-keys/[id]. Skopio POSTит результат сразу после завершения скана. Каждый запрос подписан HMAC-SHA256 — проверьте подпись своим секретом.

Headers sent on every webhook POST:

X-Skopio-Event:     scan.completed | scan.failed
X-Skopio-Signature: sha256=<hex>
X-Skopio-Delivery:  <delivery_id>
X-Skopio-Timestamp: <unix_ms>
User-Agent:         Skopio-Webhook/1
Content-Type:       application/json

Verify the signature (Node.js):

import {createHmac, timingSafeEqual} from "node:crypto";

function verify(rawBody, sigHeader, secret) {
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(sigHeader));
}

Body shape is the same as the GET response \`result\` field:

{
  "event": "scan.completed",
  "scan_id": "req-...",
  "bulk_id": "bulk_xxx",          // only present if scan was part of a bulk submission
  "target": "john@example.com",
  "kind": "email",
  "status": "completed",
  "completed_at": "2026-05-17T12:34:56Z",
  "result": {
    "risk": {"score": 65, "band": "medium"},
    "profiles": {...}, "breaches": [...], "ai_summary": "...",
    ...
  }
}

Retries: failed deliveries retry up to 3 times (immediate, +30s, +5min). Return any 2xx to acknowledge. All attempts are logged in /app/api-keys/[id].

Стоимость и тарифы

Тарифы определяют ТОЛЬКО пропускную способность. Каждый API-вызов списывает 1 кредит с баланса аккаунта — независимо от тарифа. Превышение rate-limit возвращает 429 без списания. Балланс < 1 → 402 insufficient_balance.

Получить API-ключ →