API (SaaS): API Definition

ActionHTTP MethodHTTP Resource / Path
Scan URL and return scan resultPOST/v1/scan/sync/download
Scan file and return scan resultPOST/v1/scan/sync/binary
Scan file and return scan resultPOST/v1/scan/sync/form
Scan S3 object and return scan resultPOST/v1/scan/sync/s3
Scan URL and invoke callback with scan resultPOST/v1/scan/async/download
Scan S3 object and invoke callback with scan resultPOST/v1/scan/async/s3
Test authenticationGET/v1/test
Get information about yourselfGET/v1/whoami

Authentication (#)

Accessing the API requires an active subscription and API key. Pass the API key via a x-api-key HTTP header.

Actions (#)

POST /v1/scan/sync/download (#)

Download a file from a remote location (HTTP/HTTPS), scan the file, and return the scan result.

Maximum file size is 200 MB. The request timeout is 60 seconds.

The request body is JSON formatted with these properties:

  • download_url (string): URL to download and scan via HTTP(S) GET.
  • download_headers: (object, optional): Headers to send when downloading the file.

The response status code is 200, and the body is JSON formatted with these properties:

  • status (string (clean, infected, no)): The scan result.
  • finding (string, optional): For infected files, the type of virus/malware that was detected.
  • size (number, optional): The file size in bytes.
  • realfiletype (string, optional): The Real File Type detected by the Sophos engine.

Example:

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

curl \
  -X POST \
  -H 'x-api-key: <API_KEY_PLACEHOLDER>' \
  -H 'Content-Type: application/json' \
  -d '{"download_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"}' \
  'https://eu.developer.attachmentav.com/v1/scan/sync/download'

{"status":"clean","size":2903045,"realfiletype":"Adobe Portable Document Format (PDF)"}

Find the latest version of the virus-scan-sdk on Maven Central and add it to the dependencies of your project.

<dependency>
  <groupId>com.attachmentav</groupId>
  <artifactId>virus-scan-sdk</artifactId>
  <version>0.4.0</version>
</dependency>

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import com.attachmentav.api.AttachmentAvApi;
import com.attachmentav.client.ApiClient;
import com.attachmentav.client.ApiException;
import com.attachmentav.client.Configuration;
import com.attachmentav.model.ScanResult;
import com.attachmentav.model.SyncDownloadScanRequest;

// ...

ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("<API_KEY_PLACEHOLDER>");
AttachmentAvApi api = new AttachmentAvApi();
SyncDownloadScanRequest request = new SyncDownloadScanRequest();
request.setDownloadUrl("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf");
ScanResult result = api.scanSyncDownloadPost(request);
System.out.println("Scan Result: " + result.getStatus());

Source: GitHub

Find the latest version of the attachmentav-virus-malware-scan-sdk on PyPI and add it to the dependencies of your project.

pip install attachmentav-virus-malware-scan-sdk

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import attachmentav

configuration = attachmentav.Configuration()
configuration.api_key['apiKeyAuth'] = "<API_KEY_PLACEHOLDER>"

with attachmentav.ApiClient(configuration) as api_client:
  api_instance = attachmentav.AttachmentAVApi(api_client)

sync_download_scan_request = attachmentav.SyncDownloadScanRequest(
  download_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
)
scan_result = api_instance.scan_sync_download_post(sync_download_scan_request)
print(scan_result)

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

ESM

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

const scanResult = await api.scanSyncDownloadPost({
  syncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
  }
});
console.log('Sync download scan result:', scanResult);

Source: GitHub

CommonJs

const { AttachmentAVApi, Configuration } = require('@attachmentav/virus-scan-sdk-ts');

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

api.scanSyncDownloadPost({
  syncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
  }
}).then(scanResult => {
  console.log('Sync download scan result:', scanResult);
});

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

const scanResult = await api.scanSyncDownloadPost({
  syncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf'
  }
});
console.log('Sync download scan result:', scanResult);

Source: GitHub

POST /v1/scan/sync/binary (#)

Upload a file, scan the file, and return the scan result.

Maximum file size is 10 MB. The request timeout is 60 seconds.

The request body contains the binary data (application/octet-stream).

The response status code is 200, and the body is JSON formatted with these properties:

  • status (string (clean, infected, no)): The scan result.
  • finding (string, optional): For infected files, the type of virus/malware that was detected.
  • size (number, optional): The file size in bytes.
  • realfiletype (string, optional): The Real File Type detected by the Sophos engine.

Example:

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

curl \
  -X POST \
  -H 'x-api-key: <API_KEY_PLACEHOLDER>' \
  -H 'Content-Type: application/octet-stream' \
  -d '@path/to/file' \
  https://eu.developer.attachmentav.com/v1/scan/sync/binary

{"status":"clean","size":73928372,"realfiletype":"Adobe Portable Document Format (PDF)"}

Find the latest version of the virus-scan-sdk on Maven Central and add it to the dependencies of your project.

<dependency>
  <groupId>com.attachmentav</groupId>
  <artifactId>virus-scan-sdk</artifactId>
  <version>0.4.0</version>
</dependency>

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import com.attachmentav.api.AttachmentAvApi;
import com.attachmentav.client.ApiClient;
import com.attachmentav.client.ApiException;
import com.attachmentav.client.Configuration;
import com.attachmentav.model.ScanResult;
import java.io.File;

// ...

ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("<API_KEY_PLACEHOLDER>");
AttachmentAvApi api = new AttachmentAvApi();
ScanResult result = api.scanSyncBinaryPost(new File("/path/to/file"));
System.out.println("Scan Result: " + result.getStatus());

Source: GitHub

Find the latest version of the attachmentav-virus-malware-scan-sdk on PyPI and add it to the dependencies of your project.

pip install attachmentav-virus-malware-scan-sdk

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import attachmentav

configuration = attachmentav.Configuration()
configuration.api_key['apiKeyAuth'] = "<API_KEY_PLACEHOLDER>"

with attachmentav.ApiClient(configuration) as api_client:
  api_instance = attachmentav.AttachmentAVApi(api_client)

with open("/path/to/file", "rb") as file:
    file_content = file.read()
    scan_result = api_instance.scan_sync_binary_post(file_content)
    print(scan_result)

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

ESM

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';
import { readFileSync } from 'node:fs';
import { Blob } from 'node:buffer';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

const scanResult = await api.scanSyncBinaryPost({
  body: new Blob([readFileSync('/path/to/file')])
});
console.log('Sync binary scan result:', scanResult);

Source: GitHub

CommonJs

const { AttachmentAVApi, Configuration } = require('@attachmentav/virus-scan-sdk-ts');
const { readFileSync } = require('node:fs');
const { Blob } = require('node:buffer');

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

api.scanSyncBinaryPost({
  body: new Blob([readFileSync('/path/to/file')])
}).then(scanResult => {
  console.log('Sync binary scan result:', scanResult);
});

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';
import { readFileSync } from 'node:fs';
import { Blob } from 'node:buffer';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

const scanResult = await api.scanSyncBinaryPost({
  body: new Blob([readFileSync('/path/to/file')])
});
console.log('Sync binary scan result:', scanResult);

Source: GitHub

POST /v1/scan/sync/form (#)

Upload a file, scan the file, and return the scan result.

Maximum file size is 10 MB. The request timeout is 60 seconds.

The request body is multipart/form-data formatted and contains one file.

The response status code is 200, and the body is JSON formatted with these properties:

  • status (string (clean, infected, no)): The scan result.
  • finding (string, optional): For infected files, the type of virus/malware that was detected.
  • size (number, optional): The file size in bytes.
  • realfiletype (string, optional): The Real File Type detected by the Sophos engine.

Example:

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

curl \
  -H 'x-api-key: <API_KEY_PLACEHOLDER>' \
  -F file=@path/to/file \
  https://eu.developer.attachmentav.com/v1/scan/sync/form

{"status":"clean","size":73928372,"realfiletype":"Adobe Portable Document Format (PDF)"}

POST /v1/scan/sync/s3 (#)

Download a file from S3, scan the file, and return the scan result.

A bucket policy is required to grant attachmentAV access to the S3 objects.

Maximum file size is 200 MB. The request timeout is 60 seconds.

The request body is JSON formatted with these properties:

  • bucket (string): The bucket name.
  • key (string): The object key.
  • version (string, optional): If versioning is turned on, the object version.

The response status code is 200, and the body is JSON formatted with these properties:

  • status (string (clean, infected, no)): The scan result.
  • finding (string, optional): For infected files, the type of virus/malware that was detected.
  • size (number, optional): The file size in bytes.
  • realfiletype (string, optional): The Real File Type detected by the Sophos engine.

Example:

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

curl \
  -X POST \
  -H 'x-api-key: <API_KEY_PLACEHOLDER>' \
  -H 'Content-Type: application/json' \
  -d '{"bucket": "your-bucket", "key": "path/to/file.pdf"}' \
  'https://eu.developer.attachmentav.com/v1/scan/sync/s3'

{"status":"clean","size":105255200,"realfiletype":"Adobe Portable Document Format (PDF)"}

Find the latest version of the virus-scan-sdk on Maven Central and add it to the dependencies of your project.

<dependency>
  <groupId>com.attachmentav</groupId>
  <artifactId>virus-scan-sdk</artifactId>
  <version>0.4.0</version>
</dependency>

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import com.attachmentav.api.AttachmentAvApi;
import com.attachmentav.client.ApiClient;
import com.attachmentav.client.ApiException;
import com.attachmentav.client.Configuration;
import com.attachmentav.model.ScanResult;
import com.attachmentav.model.SyncS3ScanRequest;

// ...

ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("<API_KEY_PLACEHOLDER>");
AttachmentAvApi api = new AttachmentAvApi();
SyncS3ScanRequest request = new SyncS3ScanRequest();
request.setBucket("<BUCKET_NAME_PLACEHOLDER>");
request.setKey("<OBJECT_KEY_PLACEHOLDER>");
//request.setVersion("<OBJECT_VERSION_PLACEHOLDER>"); // for versioned buckets only
ScanResult result = api.scanSyncS3Post(request);
System.out.println("Scan Result: " + result.getStatus());n

Source: GitHub

Find the latest version of the attachmentav-virus-malware-scan-sdk on PyPI and add it to the dependencies of your project.

pip install attachmentav-virus-malware-scan-sdk

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import attachmentav

configuration = attachmentav.Configuration()
configuration.api_key['apiKeyAuth'] = "<API_KEY_PLACEHOLDER>"

with attachmentav.ApiClient(configuration) as api_client:
  api_instance = attachmentav.AttachmentAVApi(api_client)

sync_s3_scan_request = attachmentav.SyncS3ScanRequest(
  bucket = "<BUCKET_NAME_PLACEHOLDER>",
  key = "<OBJECT_KEY_PLACEHOLDER>"
)
scan_result = api_instance.scan_sync_s3_post(sync_s3_scan_request)
print(scan_result)

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

ESM

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

const scanResult = await api.scanSyncS3Post({
  syncS3ScanRequest: {
    bucket: '<BUCKET_NAME_PLACEHOLDER>',
    key: '<OBJECT_KEY_PLACEHOLDER>'
  }
});
console.log('Sync S3 scan result:', scanResult);

Source: GitHub

CommonJs

const { AttachmentAVApi, Configuration } = require('@attachmentav/virus-scan-sdk-ts');

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

api.scanSyncS3Post({
  syncS3ScanRequest: {
    bucket: '<BUCKET_NAME_PLACEHOLDER>',
    key: '<OBJECT_KEY_PLACEHOLDER>'
  }
}).then(scanResult => {
  console.log('Sync S3 scan result:', scanResult);
});

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

const scanResult = await api.scanSyncS3Post({
  syncS3ScanRequest: {
    bucket: '<BUCKET_NAME_PLACEHOLDER>',
    key: '<OBJECT_KEY_PLACEHOLDER>'
  }
});
console.log('Sync S3 scan result:', scanResult);

Source: GitHub

POST /v1/scan/async/download (#)

Download a file from a remote location (HTTP/HTTPS), scan the file, and send the scan result.

Maximum file size is 5 GB. The request timeout is 29 seconds, the asynchronous scan job is not affected by this limit.

The request body is JSON formatted with these properties:

  • download_url (string): URL to download and scan via HTTP(S) GET.
  • download_headers: (object, optional): Headers to send when downloading the file.
  • callback_url (string): URL to receive the scan result via HTTPS POST (see Callback).
  • callback_headers: (object, optional): Headers to send when invoking the callback. The headers Content-Type and Content-Length are always added and can not be changed.
  • trace_id (string, optional): ID allowing you to trace the scan request with a custom ID.
  • custom_data (string, optional): Custom data that attachmentAV passes through-maximum of 16 KB in UTF-8.

The response status code is 204.

Example:

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

curl \
  -vvv \
  -X POST \
  -H 'x-api-key: <API_KEY_PLACEHOLDER>' \
  -H 'Content-Type: application/json' \
  -d '{"download_url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", "callback_url": "https://api.yourcompany.com/attachmentav/callback"}' \
  'https://eu.developer.attachmentav.com/v1/scan/async/download'

The scan result is send to your callback via an HTTPS POST request to your callback_url.

Find the latest version of the virus-scan-sdk on Maven Central and add it to the dependencies of your project.

<dependency>
  <groupId>com.attachmentav</groupId>
  <artifactId>virus-scan-sdk</artifactId>
  <version>0.4.0</version>
</dependency>

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

package com.attachmentav.api.examples;

import com.attachmentav.api.AttachmentAvApi;
import com.attachmentav.client.ApiClient;
import com.attachmentav.client.ApiException;
import com.attachmentav.client.Configuration;
import com.attachmentav.model.AsyncDownloadScanRequest;

// ...

ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("<API_KEY_PLACEHOLDER>");
AttachmentAvApi api = new AttachmentAvApi();
AsyncDownloadScanRequest request = new AsyncDownloadScanRequest();
request.setCallbackUrl("https://api.yourcompany.com/attachmentav/callback");
request.setDownloadUrl("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf");
api.scanAsyncDownloadPost(request);

The scan result is send to your callback via an HTTPS POST request to your CallbackUrl.

Source: GitHub

Find the latest version of the attachmentav-virus-malware-scan-sdk on PyPI and add it to the dependencies of your project.

pip install attachmentav-virus-malware-scan-sdk

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

import attachmentav

configuration = attachmentav.Configuration()
configuration.api_key['apiKeyAuth'] = "<API_KEY_PLACEHOLDER>"

with attachmentav.ApiClient(configuration) as api_client:
  api_instance = attachmentav.AttachmentAVApi(api_client)

async_download_scan_request = attachmentav.AsyncDownloadScanRequest(
  download_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
  callback_url = "https://api.yourcompany.com/attachmentav/callback"
)
api_instance.scan_async_download_post(async_download_scan_request)

The scan result is send to your callback via an HTTPS POST request to your callback_url.

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

ESM

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

await api.scanAsyncDownloadPost({
  asyncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
    callbackUrl: 'https://api.yourcompany.com/attachmentav/callback'
  }
});
console.log('Async download submitted');

The scan result is send to your callback via an HTTPS POST request to your callbackUrl.

Source: GitHub

CommonJs

const { AttachmentAVApi, Configuration } = require('@attachmentav/virus-scan-sdk-ts');

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

api.scanAsyncDownloadPost({
  asyncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
    callbackUrl: 'https://api.yourcompany.com/attachmentav/callback'
  }
}).then(() => {
  console.log('Async download submitted');
});

The scan result is send to your callback via an HTTPS POST request to your callbackUrl.

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

await api.scanAsyncDownloadPost({
  asyncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
    callbackUrl: 'https://api.yourcompany.com/attachmentav/callback'
  }
});
console.log('Async download submitted');

The scan result is send to your callback via an HTTPS POST request to your callbackUrl.

Source: GitHub

POST /v1/scan/async/s3 (#)

Download a file from S3, scan the file, and send the scan result.

A bucket policy is required to grant attachmentAV access to the S3 objects.

Maximum file size is 5 GB. The request timeout is 29 seconds, the asynchronous scan job is not affected by this limit.

The request body is JSON formatted with these properties:

  • bucket (string): The bucket name.
  • key (string): The object key.
  • version (string, optional): If versioning is turned on, the object version.
  • callback_url (string): URL to receive the scan result via HTTPS POST (see Callback).
  • callback_headers: (object, optional): Headers to send when invoking the callback. The headers Content-Type and Content-Length are always added and can not be changed.
  • trace_id (string, optional): ID allowing you to trace the scan request with a custom ID.
  • custom_data (string, optional): Custom data that attachmentAV passes through-maximum of 16 KB in UTF-8.

The response status code is 204.

Example:

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

curl \
  -vvv \
  -X POST \
  -H 'x-api-key: <API_KEY_PLACEHOLDER>' \
  -H 'Content-Type: application/json' \
  -d '{"bucket": "your-bucket", "key": "path/to/file.pdf", "callback_url": "https://api.yourcompany.com/attachmentav/callback"}' \
  'https://eu.developer.attachmentav.com/v1/scan/async/s3'

The scan result is send to your callback via an HTTPS POST request to your callback_url.

Find the latest version of the virus-scan-sdk on Maven Central and add it to the dependencies of your project.

<dependency>
  <groupId>com.attachmentav</groupId>
  <artifactId>virus-scan-sdk</artifactId>
  <version>0.4.0</version>
</dependency>

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

import com.attachmentav.api.AttachmentAvApi;
import com.attachmentav.client.ApiClient;
import com.attachmentav.client.ApiException;
import com.attachmentav.client.Configuration;
import com.attachmentav.model.AsyncS3ScanRequest;

// ...

ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("<API_KEY_PLACEHOLDER>");
AttachmentAvApi api = new AttachmentAvApi();
AsyncS3ScanRequest request = new AsyncS3ScanRequest();
request.setCallbackUrl("https://api.yourcompany.com/attachmentav/callback");
request.setBucket("<BUCKET_NAME_PLACEHOLDER>");
request.setKey("<OBJECT_KEY_PLACEHOLDER>");
//request.setVersion("<OBJECT_VERSION_PLACEHOLDER>"); // for versioned buckets only
api.scanAsyncS3Post(request);
System.out.println("Async S3 submitted");

The scan result is send to your callback via an HTTPS POST request to your CallbackUrl.

Source: GitHub

Find the latest version of the attachmentav-virus-malware-scan-sdk on PyPI and add it to the dependencies of your project.

pip install attachmentav-virus-malware-scan-sdk

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

import attachmentav

configuration = attachmentav.Configuration()
configuration.api_key['apiKeyAuth'] = "<API_KEY_PLACEHOLDER>"

with attachmentav.ApiClient(configuration) as api_client:
  api_instance = attachmentav.AttachmentAVApi(api_client)

async_s3_scan_request = attachmentav.AsyncS3ScanRequest(
  bucket = "<BUCKET_NAME_PLACEHOLDER>",
  key = "<OBJECT_KEY_PLACEHOLDER>",
  callback_url = "https://api.yourcompany.com/attachmentav/callback"
)
api_instance.scan_async_s3_post(async_s3_scan_request)
print("Async S3 submitted")

The scan result is send to your callback via an HTTPS POST request to your callback_url.

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

ESM

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

await api.scanAsyncS3Post({
  asyncS3ScanRequest: {
    bucket: '<BUCKET_NAME_PLACEHOLDER>',
    key: '<OBJECT_KEY_PLACEHOLDER>',
    callbackUrl: 'https://api.yourcompany.com/attachmentav/callback'
  }
});
console.log('Async S3 submitted');

The scan result is send to your callback via an HTTPS POST request to your callback_url.

Source: GitHub

CommonJs

const { AttachmentAVApi, Configuration } = require('@attachmentav/virus-scan-sdk-ts');

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

api.scanAsyncS3Post({
  asyncS3ScanRequest: {
    bucket: '<BUCKET_NAME_PLACEHOLDER>',
    key: '<OBJECT_KEY_PLACEHOLDER>',
    callbackUrl: 'https://api.yourcompany.com/attachmentav/callback'
  }
}).then(() => {
  console.log('Async S3 submitted');
});

The scan result is send to your callback via an HTTPS POST request to your callback_url.

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace https://api.yourcompany.com/attachmentav/callback with your callback URL.

import { AttachmentAVApi, Configuration } from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});

const api = new AttachmentAVApi(config);

await api.scanAsyncS3Post({
  asyncS3ScanRequest: {
    bucket: '<BUCKET_NAME_PLACEHOLDER>',
    key: '<OBJECT_KEY_PLACEHOLDER>',
    callbackUrl: 'https://api.yourcompany.com/attachmentav/callback'
  }
});
console.log('Async S3 submitted');

The scan result is send to your callback via an HTTPS POST request to your callback_url.

Source: GitHub

GET/v1/test (#)

Check if your API key is valid.

The response status code is 204.

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

curl \
  -X GET \
  -H 'x-api-key: xxx' \
  'https://eu.developer.attachmentav.com/v1/test'

GET/v1/whoami (#)

Get information abour yourself.

The response status code is 200, and the body is JSON formatted with these properties:

  • tenantId (string): The tenant ID.

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

curl \
  -X GET \
  -H 'x-api-key: xxx' \
  'https://eu.developer.attachmentav.com/v1/whoami'

{"tenantId":"f15gulb49i"}

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

ESM

import {AttachmentAVApi, Configuration} from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});
const api = new AttachmentAVApi(config);

const res = await api.whoamiGet();
console.log('Who am I?', res);

Source: GitHub

CommonJs

const { AttachmentAVApi, Configuration } = require('@attachmentav/virus-scan-sdk-ts');

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});
const api = new AttachmentAVApi(config);

api.whoamiGet().then(res => {
  console.log('Who am I?', res);
});

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

import {AttachmentAVApi, Configuration} from '@attachmentav/virus-scan-sdk-ts';

const config = new Configuration({
  apiKey: '<API_KEY_PLACEHOLDER>'
});
const api = new AttachmentAVApi(config);

const res = await api.whoamiGet();
console.log('Who am I?', res);

Source: GitHub

Callback (#)

The callback URL is called by attachmentAV via an HTTPS POST request with a JSON payload with this properties:

  • status (string (clean, infected, no)): The scan result.
  • finding (string, optional): For infected files, the type of virus/malware that was detected.
  • size (number): The file size in bytes.
  • download_time (number): Time to download the file in seconds.
  • scan_time (number): Time to scan the file in seconds.
  • download_url (string): The downloaded URL.
  • trace_id (string, optional): ID to trace custom scan jobs.
  • custom_data (string, optional): Custom data defined when submitting a custom scan job.
  • realfiletype (string, optional): The Real File Type detected by the Sophos engine.

For security reasons, we recommend verifying callbacks to ensure that the callback was made by attachmentAV.

Verify (#)

attachmentAV signs callback invocations by adding the following headers to callback invocations:

  • X-Signature: RSA-SHA25 signature hex encoded.
  • X-Timestamp: Unix time in milliseconds.

To verify the signature:

  1. Get public key from attachmentAV.
  2. Parse public key.
  3. Construct verification string: ${timestamp}.${tenantId}.${callbackUrl}.${body}.
    1. Replace ${timestamp} with the X-Timestamp header value.
    2. Replace ${tenantId} with your tenant ID. Get your tenant ID from GET /v1/whoami.
    3. Replace ${callbackUrl} with the value you used for callback_url when sending the scan job.
    4. Replace ${body} with the raw callback body.
  4. Initialize RSA-SHA256 verifier with public key.
  5. Verify that the verification string produces the same signature as the X-Signature header value.
  6. Validate the timestamp is within an acceptable window (we recommend ± 5 minutes) to prevent replay attacks.

The following snippets implement the logic described above.

Find the latest version of the virus-scan-sdk on Maven Central and add it to the dependencies of your project.

<dependency>
  <groupId>com.attachmentav</groupId>
  <artifactId>virus-scan-sdk</artifactId>
  <version>0.4.0</version>
</dependency>

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key.

package com.attachmentav;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.security.KeyFactory;
import java.nio.charset.StandardCharsets;
import javax.xml.bind.DatatypeConverter;

public class CallbackSignatureX509 {

    private static final long SIGNATURE_TOLERANCE_IN_MILLIS = 5 * 60 * 1000; // 5 minutes

    /**
     * Verifies the signature of a callback.
     *
     * @param unixtimeInMillis Current unixtime in milliseconds (System.currentTimeMillis())
     * @param publicKeyPEM     The public key in PEM X509 format (available at https://attachmentav.com/help/virus-malware-scan-api/developer/publickey.html)
     * @param timestamp        The value of the X-Timestamp header of the callback
     * @param tenantId         Your tenant ID (get your tenant ID from https://attachmentav.com/help/virus-malware-scan-api/developer/definition.html#action-whoami)
     * @param callbackUrl      The callback URL used when submitting the scan job
     * @param body             The body of the callback
     * @param signature        The value of the X-Signature header of the callback
     * @return true if the callback is valid
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    static boolean verify(final long unixtimeInMillis, final String publicKeyPEM, final String timestamp, final String tenantId, final String callbackUrl, final String body, final String signature) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        final Signature verifier = Signature.getInstance("SHA256withRSA");
        final PublicKey pubKey = parsePublicKey(publicKeyPEM);
        verifier.initVerify(pubKey);
        final String dataToVerify = timestamp + "." + tenantId + "." + callbackUrl + "." + body;
        verifier.update(dataToVerify.getBytes(StandardCharsets.UTF_8));
        final byte[] signatureBytes = DatatypeConverter.parseHexBinary(signature);
        final boolean valid = verifier.verify(signatureBytes);
        final boolean withinTolerance = Math.abs(unixtimeInMillis - Long.parseLong(timestamp)) <= SIGNATURE_TOLERANCE_IN_MILLIS;
        return valid && withinTolerance;
    }

    private static PublicKey parsePublicKey(final String publicKeyPEM) throws NoSuchAlgorithmException, InvalidKeySpecException {
        final String cleanKey = publicKeyPEM
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s", "");
        final byte[] keyBytes = DatatypeConverter.parseBase64Binary(cleanKey);
        final X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(spec);
    }
}

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace <CALLBACK_URL_PLACEHOLDER> as described in the code.

ESM

import {createPublicKey, createVerify} from 'node:crypto';

const SIGNATURE_TOLERANCE_IN_MILLIS = 5 * 60 * 1000;

/**
 * Verifies the signature of a callback.
 * 
 * @param {number} unixtimeInMillis - Current unixtime in milliseconds (Date.now())
 * @param {string} publicKeyPEM -  The public key in PEM PKCS1 format (available at https://attachmentav.com/help/virus-malware-scan-api/developer/publickey.html)
 * @param {string} timestamp - The value of the X-Timestamp header of the callback
 * @param {string} tenantId - Your tenant ID (get your tenant ID from https://attachmentav.com/help/virus-malware-scan-api/developer/definition.html#action-whoami)
 * @param {string} callbackUrl - The callback URL used when submitting the scan job
 * @param {string} body - The body of the callback
 * @param {string} signature - The value of the X-Signature header of the callback
 * @return {boolean} - true if the callback is valid
 */
function verify(unixtimeInMillis, publicKeyPEM, timestamp, tenantId, callbackUrl, body, signature) {
  const publicKey = createPublicKey({
    key: publicKeyPEM,
    format: 'pem',
    type: 'pkcs1'
  });
  const verify = createVerify('sha256');
  verify.update(timestamp);
  verify.update('.');
  verify.update(tenantId);
  verify.update('.');
  verify.update(callbackUrl);
  verify.update('.');
  verify.update(body);
  verify.end();
  const valid = verify.verify(publicKey, signature, 'hex');
  return valid && Math.abs(unixtimeInMillis-parseInt(timestamp, 10)) <= SIGNATURE_TOLERANCE_IN_MILLIS;
}

Usage example:

import {AttachmentAVApi, Configuration} from '@attachmentav/virus-scan-sdk-ts';
import {createServer} from 'node:http';

const API_KEY = '<API_KEY_PLACEHOLDER>';

// To make your server runmning on localhost accessible from the Internet, we recommend to use ngrok.
// 1. Install and configure it as described here: https://ngrok.com/docs/getting-started
// 2. In your terminal, run:
// ngrok http 8081
// 3. Insert the ngrok URL (e.g. https://42d3a8497f95.ngrok-free.app) below:
const CALLBACK_URL = '<CALLBACK_URL_PLACEHOLDER>';

const PUBLIC_KEY_PEM = `-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAyLoZzjo1cQV9ZN2TH/alrxWiQ3u/ndT0HMrLMdBTVO3Tz1nUjLt6
SqKZsN8dQhvPoEjfyhCTEg7MPWopG3n0cf3NRxtoeXy/Z62b1zdUd426kMuKOQP8
Yy6cxa/RtK2tkHCnTGxjfvNmMK+m68sFmsilR88LnIN71my4cG8bIDGDftWublvK
AEOWhxSECYn1XEtyrQL5lm8HFnHdE9ys56xTJkdr5Mmkvanrnd/hXzTHzjruGcLv
bjciI82+Z335AzYgJcnmH4/zsBuyPL2FJSfQF9NsPaTJuQgkw1usAKBQcujcEriY
UDNWgTe1a+LOnCEMb+9mAYw8lMRYRd3CBwIDAQAB
-----END RSA PUBLIC KEY-----`;

const config = new Configuration({
  apiKey: API_KEY
});
const api = new AttachmentAVApi(config);

const {tenantId: TENANT_ID} = await api.whoamiGet(); // the tenantId never changes. we recommend to hard code it to avoid yet another HTTPS call.
//const TENANT_ID = '<TENANT_ID_PLACEHOLDER>';

const server = createServer((req, res) => {
  const chunks = [];
  req.on('data', (chunk) => {
    chunks.push(chunk);
  });
  req.on('end', () => {
    const body = Buffer.concat(chunks).toString();
    if (verify(Date.now(), PUBLIC_KEY_PEM, req.headers['x-timestamp'], TENANT_ID, CALLBACK_URL, body, req.headers['x-signature'])) {
      res.writeHead(204);
      res.end();
      console.log('Received valid callback', body);
    } else {
      res.writeHead(403);
      res.end();
      console.error('Received invalid callback', body);
    }
    server.close();
  });

});
server.listen(8081);

await api.scanAsyncDownloadPost({
  asyncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
    callbackUrl: CALLBACK_URL
  }
});
console.log('Async download submitted');

Source: GitHub

CommonJs

Source: GitHub

Find the latest version of the virus-scan-sdk-ts on npm and add it to the dependencies of your project.

npm i @attachmentav/virus-scan-sdk-ts

An active subscription and API key is required. Replace <API_KEY_PLACEHOLDER> with your API key. Replace <CALLBACK_URL_PLACEHOLDER> as described in the code.

import {createPublicKey, createVerify} from 'node:crypto';

const SIGNATURE_TOLERANCE_IN_MILLIS = 5 * 60 * 1000;

/**
 * Verifies the signature of a callback.
 * 
 * @param {number} unixtimeInMillis - Current unixtime in milliseconds (Date.now())
 * @param {string} publicKeyPEM -  The public key in PEM PKCS1 format (available at https://attachmentav.com/help/virus-malware-scan-api/developer/publickey.html)
 * @param {string} timestamp - The value of the X-Timestamp header of the callback
 * @param {string} tenantId - Your tenant ID (get your tenant ID from https://attachmentav.com/help/virus-malware-scan-api/developer/definition.html#action-whoami)
 * @param {string} callbackUrl - The callback URL used when submitting the scan job
 * @param {string} body - The body of the callback
 * @param {string} signature - The value of the X-Signature header of the callback
 * @return {boolean} - true if the callback is valid
 */
function verify(unixtimeInMillis, publicKeyPEM, timestamp, tenantId, callbackUrl, body, signature) {
  const publicKey = createPublicKey({
    key: publicKeyPEM,
    format: 'pem',
    type: 'pkcs1'
  });
  const verify = createVerify('sha256');
  verify.update(timestamp);
  verify.update('.');
  verify.update(tenantId);
  verify.update('.');
  verify.update(callbackUrl);
  verify.update('.');
  verify.update(body);
  verify.end();
  const valid = verify.verify(publicKey, signature, 'hex');
  return valid && Math.abs(unixtimeInMillis-parseInt(timestamp, 10)) <= SIGNATURE_TOLERANCE_IN_MILLIS;
}

Usage example:

import {AttachmentAVApi, Configuration} from '@attachmentav/virus-scan-sdk-ts';
import {createServer} from 'node:http';

const API_KEY = '<API_KEY_PLACEHOLDER>';

// To make your server runmning on localhost accessible from the Internet, we recommend to use ngrok.
// 1. Install and configure it as described here: https://ngrok.com/docs/getting-started
// 2. In your terminal, run:
// ngrok http 8081
// 3. Insert the ngrok URL (e.g. https://42d3a8497f95.ngrok-free.app) below:
const CALLBACK_URL = '<CALLBACK_URL_PLACEHOLDER>';

const PUBLIC_KEY_PEM = `-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAyLoZzjo1cQV9ZN2TH/alrxWiQ3u/ndT0HMrLMdBTVO3Tz1nUjLt6
SqKZsN8dQhvPoEjfyhCTEg7MPWopG3n0cf3NRxtoeXy/Z62b1zdUd426kMuKOQP8
Yy6cxa/RtK2tkHCnTGxjfvNmMK+m68sFmsilR88LnIN71my4cG8bIDGDftWublvK
AEOWhxSECYn1XEtyrQL5lm8HFnHdE9ys56xTJkdr5Mmkvanrnd/hXzTHzjruGcLv
bjciI82+Z335AzYgJcnmH4/zsBuyPL2FJSfQF9NsPaTJuQgkw1usAKBQcujcEriY
UDNWgTe1a+LOnCEMb+9mAYw8lMRYRd3CBwIDAQAB
-----END RSA PUBLIC KEY-----`;

const config = new Configuration({
  apiKey: API_KEY
});
const api = new AttachmentAVApi(config);

const {tenantId: TENANT_ID} = await api.whoamiGet(); // the tenantId never changes. we recommend to hard code it to avoid yet another HTTPS call.
//const TENANT_ID = '<TENANT_ID_PLACEHOLDER>';

const server = createServer((req, res) => {
  const chunks: Buffer[] = [];
  req.on('data', (chunk) => {
    chunks.push(chunk);
  });
  req.on('end', () => {
    const body = Buffer.concat(chunks).toString();
    if (verify(Date.now(), PUBLIC_KEY_PEM, req.headers['x-timestamp'], TENANT_ID, CALLBACK_URL, body, req.headers['x-signature'])) {
      res.writeHead(204);
      res.end();
      console.log('Received valid callback', body);
    } else {
      res.writeHead(403);
      res.end();
      console.error('Received invalid callback', body);
    }
    server.close();
  });

});
server.listen(8081);

await api.scanAsyncDownloadPost({
  asyncDownloadScanRequest: {
    downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
    callbackUrl: CALLBACK_URL
  }
});
console.log('Async download submitted');

Source: GitHub

S3 Bucket Policy (#)

In case you want to use POST /api/v1/scan/async/s3 or POST /api/v1/scan/sync/s3 it is neccessary to grant attachmentAV access to download the object from S3. Therefore, you need to attach the following bucket policy. Ensure to replace BUCKET_NAME with the name of the bucket.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "attachmentAV",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::450892694845:root"
    },
    "Action": "s3:GetObject*",
    "Resource": "arn:aws:s3:::BUCKET_NAME/*"
  }]
}

Please note, attachmentAV does not support scanning S3 objects encrypted with KMS.

Need more help?

Write us, and we'll get back to you as soon as we can.

Send us an email