Get API key
← Code samples
Document

File Scanning

Screen uploaded PDFs and Office documents for malware, macros, and embedded threats before storing or processing them.

Screen a file before storing or processing it. Supported formats: PDF, Word (.doc, .docx), Excel (.xls, .xlsx), PowerPoint (.ppt, .pptx). Submit either a direct file upload or a URL to download from — exactly one. Each scan costs 20 credits.

Endpoint

HTTP
POST https://app.verifence.io/api/scan
API-KEY: your_api_key
Content-Type: multipart/form-data

Request fields

Provide exactly one of:

FieldTypeDescription
filebinaryThe file to scan, sent as a multipart upload
urlstringA public URL to download and scan

Response fields

FieldTypeDescription
okbooleantrue if the scan completed successfully
ratingstringok, warn, or block
scoreintegerRisk score 0–100 (85+ = ok, 70–84 = warn, below 70 = block)
reasonsarraySignals that reduced the score, each a { code, message } object
summary.has_macrosbooleanDocument contains executable macros
summary.has_embedded_filesbooleanPDF contains embedded file attachments
summary.links_foundintegerNumber of URLs extracted from the document
summary.unique_domainsarrayDistinct domains found in the document's links
file_hashstringSHA-256 of the file, prefixed sha256:
filenamestringOriginal filename
timestampstringISO 8601 timestamp of the scan

cURL

cURL — file upload
curl -X POST https://app.verifence.io/api/scan \
  -H "API-KEY: your_api_key" \
  -F "file=@/path/to/document.pdf"
cURL — remote URL
curl -X POST https://app.verifence.io/api/scan \
  -H "API-KEY: your_api_key" \
  -F "url=https://example.com/invoice.pdf"
JSON — response
{
  "ok": true,
  "rating": "block",
  "score": 45,
  "reasons": [
    { "code": "VIRUS_DETECTED", "message": "Virus detected: Trojan.PDF.Agent" },
    { "code": "BRAND_LOOKALIKE", "message": "Brand lookalike detected in paypa1.com" }
  ],
  "summary": {
    "links_found": 3,
    "unique_domains": ["paypa1.com"],
    "has_embedded_files": false,
    "has_macros": false
  },
  "file_hash": "sha256:a3f1...",
  "filename": "invoice.pdf",
  "timestamp": "2026-06-05T10:00:00+00:00"
}

PHP

PHP
function scanFile(string $filePath, string $originalName = null): array
{
    $ch = curl_init('https://app.verifence.io/api/scan');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => ['API-KEY: ' . getenv('VERIFENCE_API_KEY')],
        CURLOPT_POSTFIELDS     => [
            'file' => new CURLFile($filePath, mime_content_type($filePath), $originalName ?? basename($filePath)),
        ],
        CURLOPT_TIMEOUT        => 30,
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true) ?? [];
}

// Usage — screen a user upload before storing it
$result = scanFile($file->getRealPath(), $file->getClientOriginalName());

if (!($result['ok'] ?? false)) {
    throw new \RuntimeException('File scan failed. Please try again.');
}

match ($result['rating']) {
    'block' => throw new \RuntimeException('This file was blocked because it contains a threat.'),
    'warn'  => quarantineForReview($file, $result),
    default => storeFile($file),
};

Node.js

Node.js
import fs from 'fs';
import path from 'path';
import FormData from 'form-data'; // npm install form-data

async function scanFile(filePath) {
  const form = new FormData();
  form.append('file', fs.createReadStream(filePath), path.basename(filePath));

  const res = await fetch('https://app.verifence.io/api/scan', {
    method: 'POST',
    headers: {
      'API-KEY': process.env.VERIFENCE_API_KEY,
      ...form.getHeaders(),
    },
    body: form,
    signal: AbortSignal.timeout(30_000),
  });

  if (!res.ok) {
    throw new Error(`Verifence API error: ${res.status}`);
  }
  return res.json();
}

// Usage — e.g. in a Multer upload handler
app.post('/upload', upload.single('file'), async (req, res) => {
  const result = await scanFile(req.file.path);
  fs.unlinkSync(req.file.path);

  if (!result.ok) return res.status(422).json({ error: 'File scan failed.' });
  if (result.rating === 'block') {
    return res.status(422).json({ error: 'This file contains a threat and cannot be uploaded.' });
  }
  if (result.rating === 'warn') {
    await quarantineFile(req.file, result);
    return res.json({ status: 'queued_for_review' });
  }
  await storeFile(req.file);
  res.json({ status: 'uploaded' });
});

Python

Python
import os
import requests

def scan_file(file_path: str) -> dict:
    with open(file_path, "rb") as f:
        response = requests.post(
            "https://app.verifence.io/api/scan",
            headers={"API-KEY": os.environ["VERIFENCE_API_KEY"]},
            files={"file": (os.path.basename(file_path), f)},
            timeout=30,
        )
    response.raise_for_status()
    return response.json()


# Usage — e.g. in a Django or Flask upload view
result = scan_file(tmp_path)

if not result.get("ok"):
    return error_response("File scan failed. Please try again.")

rating = result.get("rating")
if rating == "block":
    return error_response("This file contains a threat and cannot be uploaded.")
if rating == "warn":
    quarantine_for_review(uploaded, result)
    return success_response("Your file is under review.")

store_file(uploaded)
return success_response("File uploaded successfully.")

Acting on the verdict

RatingRecommended action
okAccept and store normally
warnQuarantine for manual review; notify your security team
blockReject immediately; return an error to the user

Never store a block result. For warn, a human review step is safer than auto-rejecting, since some legitimate files (e.g. password-protected documents) can score in the warning range.

Ready to build it?

Create a free account and grab an API key in minutes.

Get started free