APK・URL スキャン API

URL スキャンは JSON を同期返却します。APK はファイル、完全なフィンガープリント、またはパッケージ名で非同期送信し、署名付き Webhook へ結果を配信します。

はじめに

概要

URL スキャンはリクエスト内で完了し、APK スキャンは非同期です。すべての検査エンドポイントはアカウント単位のレート枠を共有します。

01送信

検査リクエストまたは APK を送信

02審査

検証、重複排除、スキャンを実行

03通知

署名付き Webhook で結果を配信

APK API はポーリングに対応

受理応答に job_id が含まれます。GET /api/v1/jobs/{job_id} で約 24 時間ポーリングできます。callback_url は任意で、指定時は署名付き Webhook も配信します。

JSON · common APK fields
{
  "client_reference": "order-20260711-001",
  "callback_url": "https://example.com/webhooks/fvl",
  "use_cache": false
}
アクセス制御

認証

各リクエストでいずれかのヘッダーを使用します。キーは作成時に一度だけ完全表示され、サーバー側で保管する必要があります。

推奨Authorization: Bearer fvl_xxx
互換X-API-Key: fvl_xxx

API キーをブラウザー、モバイルアプリ、公開リポジトリ、ログに埋め込まないでください。

アクセス制御

クォータとレート制限

API は VIP+、SVIP、SVIP+、管理者向けです。同一アカウントの全 API キーがレート枠を共有します。

プラン最短間隔R2 日次アップロード
VIP+10 分2 GiB
Pro3 分5 GiB
SVIP5 分10 GiB
SVIP+1 分30 GiB
管理者無制限無制限
URL、アップロードセッション作成、APK 特徴、パッケージ検査はアカウントのレートを共有します。キャッシュヒット、冪等リプレイ、進行中タスクの統合は新しい枠を開始しません。
有効な未完了アップロードはユーザーごとに 1 件までです。R2 セッション作成時に再検査 1 回を前払いし、発行後は返却されません。
API

エンドポイント

署名済み R2 PUT を除き、リクエストとレスポンスは JSON です。

POST/api/v1/url-scanURL を同期スキャン

url を送り、リスク結果と課金後の quota を同じ応答で受け取ります。Webhook は使用しません。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/url-scan \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/path"}'
HTTP 200
{
  "code": 0,
  "message": "success",
  "data": {
    "result": {
      "status": "completed",
      "url": "https://example.com/path",
      "domain": "example.com",
      "flagged": false,
      "mainType": 0,
      "mainTypeName": "安全",
      "provider": "OPPO",
      "websiteType": 0,
      "matchUrl": "",
      "riskDetail": "",
      "cacheStatus": "live",
      "checkedAt": 1783765471000,
      "createdAt": 1783765471000
    },
    "quota": {
      "identity_label": "VIP+",
      "daily_limit": 20,
      "daily_used": 1,
      "daily_remaining": 19,
      "scan_credits": 0,
      "total_remaining": 19,
      "usage_date": "2026-07-11"
    }
  }
}
POST/api/v1/apk/uploadsAPK アップロードセッションを作成

Idempotency-Key、.apk 名、size、file_md5、expected_sha256、共通コールバック項目が必要です。URL は 30 分有効です。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/apk/uploads \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: upload-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "order-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": false,
    "filename": "release.apk",
    "size": 24117384,
    "file_md5": "0123456789abcdef0123456789abcdef",
    "expected_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
  }'
PUT · R2 required_headers
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/vnd.android.package-archive" \
  -H "Content-Length: 24117384" \
  -H "Content-MD5: ASNFZ4mrze8BI0VniavN7w==" \
  -H "If-None-Match: *" \
  --upload-file ./release.apk
POST/api/v1/apk/uploads/completeアップロードを完了して審査へ送信

upload_token と Idempotency-Key を送信します。オブジェクトを検証し、再課金せず前払い済み審査を送信します。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/apk/uploads/complete \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: order-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{"upload_token":"upl_xxxxxxxxxxxxxxxx"}'
POST/api/v1/apk/fingerprintsAPK フィンガープリントを送信

package_name、sha256、file_md5、cert_md5 と共通コールバック項目を送り、APK の再アップロードを省けます。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/apk/fingerprints \
  -H "Authorization: Bearer fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: fingerprint-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "fingerprint-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": true,
    "package_name": "com.example.app",
    "sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
    "file_md5": "0123456789abcdef0123456789abcdef",
    "cert_md5": "abcdef0123456789abcdef0123456789",
    "version_code": 108,
    "version_name": "1.0.8",
    "size": 24117384,
    "filename": "release.apk"
  }'
POST/api/v1/packages/checkパッケージ名を検査

端末側のパッケージリスクを簡易確認します。ハッシュと証明書を含む完全 APK スキャンではありません。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/packages/check \
  -H "X-API-Key: fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: package-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "package-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": false,
    "package_name": "com.example.app"
  }'
HTTP 202
{
  "code": 0,
  "message": "accepted",
  "data": {
    "client_reference": "order-20260711-001",
    "job_id": "acd_xxxxxxxxxxxxxxxx",
    "delivery": "webhook_and_poll",
    "poll_path": "/api/v1/jobs/acd_xxxxxxxxxxxxxxxx"
  }
}
GET/api/v1/jobs/{job_id}非同期ジョブをポーリング

受理応答の job_id で pending / processing / completed / failed を確認します。結果は約 24 時間保持されます。

cURL
curl -X POST https://www.fuckviruslabel.com/api/v1/packages/check \
  -H "X-API-Key: fvl_xxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: package-20260711-001" \
  -H "Content-Type: application/json" \
  -d '{
    "client_reference": "package-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": false,
    "package_name": "com.example.app"
  }'
HTTP 202
{
  "code": 0,
  "message": "accepted",
  "data": {
    "client_reference": "order-20260711-001",
    "job_id": "acd_xxxxxxxxxxxxxxxx",
    "delivery": "webhook_and_poll",
    "poll_path": "/api/v1/jobs/acd_xxxxxxxxxxxxxxxx"
  }
}
API

発行前に前払い、発行後は返金なし

発行前に前払い、発行後は返金なし

会員資格、レート、再検査枠、日次バイト上限、未完了セッション数を確認後、再検査 1 回を引いて URL を発行します。未完了、期限切れ、ハッシュ不一致、不正 APK、キュー失敗でも返却されません。一時的な投入失敗はサンプルを保持し、自動再試行します。

サンプル保持

有効 APK は SHA-256 で重複排除して保存し、不正または不一致のサンプルは quarantine に移します。どちらも 90 日保持し、未完了アップロードは 1 日後に削除します。

リクエスト制御

use_cache の意味

use_cache は JSON ルートに置き、既定値は false です。R2 は値にかかわらず URL 発行前に前払いし、完了後の結果再利用だけを制御します。

false強制再検査

false は既存結果を迂回し、実際にスキャンを開始した時に 1 回消費します。

cache_status = bypass
trueキャッシュを許可

true は有効なキャッシュを無課金で返し、ミスまたは期限切れ時に再検査します。

cache_status = hit | miss
結果配信

署名付き Webhook

Webhook は非同期 APK 検査の唯一の結果経路です。生の JSON、タイムスタンプ、HMAC-SHA256 署名を送信します。

X-FVL-TimestampX-FVL-Timestamp: 1720000000
X-FVL-SignatureX-FVL-Signature: sha256=<hex>
  1. webhook_secret = lowercase_hex(SHA-256(raw_api_key)) を計算します。
  2. X-FVL-Timestamp + "." + raw_body を署名します。
  3. webhook_secret の UTF-8 バイトを HMAC-SHA256 キーに使い、定数時間で比較します。
  4. タイムスタンプを確認して任意の 2xx を返します。非 2xx は再試行されます。
Webhook JSON
{
  "event": "apk.scan.completed",
  "client_reference": "order-20260711-001",
  "operation": "apk_upload",
  "status": "completed",
  "cache_status": "bypass",
  "result": { "flagged": false, "result_type_name": "安全" },
  "quota": { "refresh_daily_remaining": 29, "total_remaining": 29 },
  "checked_at": "2026-07-11T10:24:31.000Z"
}
Node.js · HMAC-SHA256
import crypto from "node:crypto";

export function verifyFvlWebhook(rawBody, timestamp, signature, apiKey) {
  const webhookSecret = crypto
    .createHash("sha256")
    .update(apiKey, "utf8")
    .digest("hex");
  const expected = "sha256=" + crypto
    .createHmac("sha256", webhookSecret)
    .update(timestamp + "." + rawBody)
    .digest("hex");

  const expectedBytes = Buffer.from(expected, "utf8");
  const signatureBytes = Buffer.from(signature, "utf8");

  return expectedBytes.length === signatureBytes.length &&
    crypto.timingSafeEqual(expectedBytes, signatureBytes);
}

JSON 解析前に raw body を読み取ってください。再シリアライズすると署名検証に失敗します。

リクエスト制御

冪等性と重複排除

アップロード作成・完了、特徴検査、パッケージ検査には Idempotency-Key が必要です。

同じキーとリクエストは 24 時間同じ結果を返し、再課金しません。
同じキーを別のリクエストに使うと HTTP 409 です。
同一資産の同時再検査は 1 回に統合され、各呼び出しには個別の Webhook が届きます。
リファレンス

エラー

同期エラーは HTTP と統一 JSON を使います。非同期 APK 審査エラーは scan.failed Webhook で通知します。

HTTP意味対応
400リクエストまたは項目が不正JSON、ハッシュ、パッケージ名、コールバック URL を修正します。
401認証失敗API キーを確認します。
403アクセス拒否プランと有効期限を確認します。
409状態競合冪等キーまたはアップロード状態を確認します。
429クォータまたはレート超過Retry-After に従って再試行します。
503サービス利用不可同じ冪等キーで端点規則に従い再試行します。
Node.js
const body = {
  client_reference: "package-20260711-001",
  callback_url: "https://api.example.com/webhooks/fvl",
  use_cache: true,
  package_name: "com.example.app"
};

const response = await fetch(
  "https://www.fuckviruslabel.com/api/v1/packages/check",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer " + process.env.FVL_API_KEY,
      "Content-Type": "application/json",
      "Idempotency-Key": body.client_reference
    },
    body: JSON.stringify(body)
  }
);

if (!response.ok) throw new Error(await response.text());
console.log(await response.json());
Python
import os
import requests

payload = {
    "client_reference": "package-20260711-001",
    "callback_url": "https://api.example.com/webhooks/fvl",
    "use_cache": True,
    "package_name": "com.example.app",
}

response = requests.post(
    "https://www.fuckviruslabel.com/api/v1/packages/check",
    headers={
        "Authorization": f"Bearer {os.environ['FVL_API_KEY']}",
        "Idempotency-Key": payload["client_reference"],
    },
    json=payload,
    timeout=20,
)
response.raise_for_status()
print(response.json())
機械可読 OpenAPI 3.1クライアント生成、リクエスト検証、API ツールへの取り込みに利用できます。
リファレンス

変更履歴

v1.0.0

初回リリース:URL、R2 アップロード、APK 特徴、パッケージ、キャッシュ、冪等性、署名付き Webhook。