API (SaaS): API Definition
| Action | HTTP Method | HTTP Resource / Path |
|---|---|---|
| Scan URL and return scan result | POST | /v1/scan/sync/download |
| Scan file and return scan result | POST | /v1/scan/sync/binary |
| Scan file and return scan result | POST | /v1/scan/sync/form |
| Scan S3 object and return scan result | POST | /v1/scan/sync/s3 |
| Scan URL and invoke callback with scan result | POST | /v1/scan/async/download |
| Scan S3 object and invoke callback with scan result | POST | /v1/scan/async/s3 |
| Test authentication | GET | /v1/test |
| Get remaining credits and quota | GET | /v1/usage |
| Get information about yourself | GET | /v1/whoami |
Authentication (#)
Accessing the API requires active subscription and API key. Pass the API key via a x-api-key HTTP header.
The following snippet shows the HTTP header. Replace <API_KEY_PLACEHOLDER> with your API key.
x-api-key: <API_KEY_PLACEHOLDER>
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.5.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.5.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.5.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 headersContent-TypeandContent-Lengthare 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.5.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.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 headersContent-TypeandContent-Lengthare 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.5.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 (#)
Even though the request does not trigger any file scans, it counts against your monthly quota.
Check if your API key is valid.
The response status code is 204.
Example:
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/usage (#)
Even though the request does not trigger any file scans, it counts against your monthly quota.
Get remaining credits and quota.
The response status code is 200, and the body is JSON formatted with these properties:
credits(number): The remaining amount of scans/request for the period.quota(object):limit(number): The maximum number of scans/requests within a period.period(string): The billing period (e.g.MONTH).
Example:
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/usage'
{"credits":981,"quota":{"limit":1000,"period":"MONTH"}}
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.5.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;
// ...
ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("<API_KEY_PLACEHOLDER>");
AttachmentAvApi api = new AttachmentAvApi();
com.attachmentav.model.Usage result = api.usageGet();
System.out.println("Usage: " + result.toString());
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)
usage_result = api_instance.usage_get()
print(usage_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 res = await api.usageGet();
console.log('Usage', 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.usageGet().then(res => {
console.log('Usage', 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.usageGet();
console.log('Usage', res);
Source: GitHub
GET/v1/whoami (#)
Even though the request does not trigger any file scans, it counts against your monthly quota.
Get information abour yourself.
The response status code is 200, and the body is JSON formatted with these properties:
tenantId(string): The tenant ID.
Example:
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 on Maven Central and add it to the dependencies of your project.
<dependency>
<groupId>com.attachmentav</groupId>
<artifactId>virus-scan-sdk</artifactId>
<version>0.5.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;
// ...
ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey("<API_KEY_PLACEHOLDER>");
AttachmentAvApi api = new AttachmentAvApi();
com.attachmentav.model.Whoami result = api.whoamiGet();
System.out.println("Who Am I: " + result.toString());
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)
whoami_result = api_instance.whoami_get()
print(whoami_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 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:
- Get public key from attachmentAV.
- Parse public key.
- Construct verification string:
${timestamp}.${tenantId}.${callbackUrl}.${body}.- Replace
${timestamp}with theX-Timestampheader value. - Replace
${tenantId}with your tenant ID. Get your tenant ID from GET /v1/whoami. - Replace
${callbackUrl}with the value you used forcallback_urlwhen sending the scan job. - Replace
${body}with the raw callback body.
- Replace
- Initialize RSA-SHA256 verifier with public key.
- Verify that the verification string produces the same signature as the
X-Signatureheader value. - Validate the timestamp is within an acceptable window (we recommend ± 5 minutes) to prevent replay attacks.
The following snippets implement the logic described above.
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);
}
}
Usage example:
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.5.0</version>
</dependency>
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 com.attachmentav.api.AttachmentAvApi;
import com.attachmentav.client.ApiClient;
import com.attachmentav.client.ApiException;
import com.attachmentav.client.Configuration;
import com.attachmentav.model.AsyncDownloadScanRequest;
import com.attachmentav.model.Whoami;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
// ...
String 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:
String CALLBACK_URL = "<CALLBACK_URL_PLACEHOLDER>";
String PUBLIC_KEY_PEM = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyLoZzjo1cQV9ZN2TH/al\n" +
"rxWiQ3u/ndT0HMrLMdBTVO3Tz1nUjLt6SqKZsN8dQhvPoEjfyhCTEg7MPWopG3n0\n" +
"cf3NRxtoeXy/Z62b1zdUd426kMuKOQP8Yy6cxa/RtK2tkHCnTGxjfvNmMK+m68sF\n" +
"msilR88LnIN71my4cG8bIDGDftWublvKAEOWhxSECYn1XEtyrQL5lm8HFnHdE9ys\n" +
"56xTJkdr5Mmkvanrnd/hXzTHzjruGcLvbjciI82+Z335AzYgJcnmH4/zsBuyPL2F\n" +
"JSfQF9NsPaTJuQgkw1usAKBQcujcEriYUDNWgTe1a+LOnCEMb+9mAYw8lMRYRd3C\n" +
"BwIDAQAB\n" +
"-----END PUBLIC KEY-----";
ApiClient client = Configuration.getDefaultApiClient();
client.setApiKey(API_KEY);
AttachmentAvApi api = new AttachmentAvApi();
{
Whoami result = api.whoamiGet();
System.err.println("Replace <TENANT_ID_PLACEHOLDER> with " + result.getTenantId() + ", and uncomment this block");
System.exit(1);
}
String TENANT_ID = "<TENANT_ID_PLACEHOLDER>";
HttpServer server = HttpServer.create(new InetSocketAddress(8081), 0);
server.createContext("/", exchange -> {
String body = new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8);
try {
if (CallbackSignatureX509.verify(System.currentTimeMillis(), PUBLIC_KEY_PEM, exchange.getRequestHeaders().getFirst("x-timestamp"), TENANT_ID, CALLBACK_URL, body, exchange.getRequestHeaders().getFirst("x-signature"))) {
exchange.sendResponseHeaders(204, -1);
exchange.close();
System.out.println("Received valid callback: " + body);
} else {
exchange.sendResponseHeaders(403, -1);
exchange.close();
System.err.println("Received invalid callback: " + body);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
server.stop(1);
}
});
server.setExecutor(null); // creates a default executor
server.start();
System.out.println("Server running on port 8081");
AsyncDownloadScanRequest request = new AsyncDownloadScanRequest();
request.setCallbackUrl(CALLBACK_URL);
request.setDownloadUrl("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf");
api.scanAsyncDownloadPost(request);
System.out.println("Async download submitted");
Source: GitHub
Find the latest version of the cryptography on PyPI and add it to the dependencies of your project.
pip install cryptography
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
SIGNATURE_TOLERANCE_IN_MILLIS = 5 * 60 * 1000
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-----"""
def verify(unixtime_in_millis, public_key_pem, timestamp, tenant_id, callback_url, body, signature):
"""Verify the signature of the callback request."""
try:
public_key = serialization.load_pem_public_key(
public_key_pem.encode(),
backend=default_backend()
)
message = f"{timestamp}.{tenant_id}.{callback_url}.{body}".encode()
signature_bytes = bytes.fromhex(signature)
try:
public_key.verify(
signature_bytes,
message,
padding.PKCS1v15(),
hashes.SHA256()
)
except Exception:
return False
return abs(unixtime_in_millis - int(timestamp)) <= SIGNATURE_TOLERANCE_IN_MILLIS
except Exception as e:
print(f"Verification error: {e}", file=sys.stderr)
return False
Usage example:
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 <CALLBACK_URL_PLACEHOLDER> as described in the code.
import http.server
import socketserver
import sys
import threading
import time
import attachmentav
API_KEY = '<API_KEY_PLACEHOLDER>'
# To make your server running 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:
CALLBACK_URL = '<CALLBACK_URL_PLACEHOLDER>'
configuration = attachmentav.Configuration()
configuration.api_key['apiKeyAuth'] = API_KEY
with attachmentav.ApiClient(configuration) as api_client:
api_instance = attachmentav.AttachmentAVApi(api_client)
whoami_result = api_instance.whoami_get()
TENANT_ID = whoami_result.tenant_id # the tenant_id never changes. we recommend to hard code it to avoid yet another HTTPS call.
# TENANT_ID = '<TENANT_ID_PLACEHOLDER>'
class CallbackHandler(http.server.BaseHTTPRequestHandler):
"""HTTP request handler for the callback server."""
def do_POST(self):
"""Handle POST requests."""
content_length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(content_length).decode('utf-8')
timestamp = self.headers.get('x-timestamp', '')
signature = self.headers.get('x-signature', '')
if verify(int(time.time() * 1000), PUBLIC_KEY_PEM, timestamp, TENANT_ID, CALLBACK_URL, body, signature):
self.send_response(204)
self.end_headers()
print('Received valid callback', body, file=sys.stderr)
else:
self.send_response(403)
self.end_headers()
print('Received invalid callback', body)
threading.Thread(target=self.server.shutdown).start()
def log_message(self, format, *args):
"""Suppress default logging."""
pass
def start_server():
"""Start the HTTP server to listen for callbacks."""
with socketserver.TCPServer(("", 8081), CallbackHandler) as httpd:
httpd.serve_forever()
server_thread = threading.Thread(target=start_server, daemon=True)
server_thread.start()
async_download_scan_request = attachmentav.AsyncDownloadScanRequest(
download_url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
callback_url = CALLBACK_URL
)
api_instance.scan_async_download_post(async_download_scan_request)
print('Async download submitted')
server_thread.join()
Source: GitHub
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:
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 {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
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:
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 {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.