Virusdie API for third-party applications #

A complete API guide for Virusdie partners and developers.

2021-10-27

Common API request format #

Send HTTPS requests to virusdie.com.

A common request format is:

(GET|POST) https://virusdie.com/api/<method>/[param1/paramN][?query]

Authorization #

Two keys are used for authorization (further below client_api_key and client_mac_key).

client_api_key is the main authorization key. It should be transfered through the cookies as apikey=client_api_key.

client_mac_key is a shared key used for calculating the digital signature of the request (further below DS) according to the HMAC MD5 algorithm. It also transferred through the cookies as apimac=hmac_value.

The DS must be calculated for the whole query string. Eg.:

hmac_value = hash_hmac_md5('/api/methodname/path/?name=value', client_mac_key)

For some keys the DS check could be disabled. In such case you should not use client_mac_key and transfer apimac=hmac_value argument.

Common response format #

In response to each request, there will be a JSON object returned along format below:

{
version:    str  The version of the system,
keyid:      str  Authorization public key ID,
method:     str  The value of 'method' parameter in a request,
timewait:   int  Time of query execution, msec,
error:      int  Error code or 0, see "Common System Errors" for more,
message:    str  Error message, if any,
errorinfo:  str  Additional information on the causes of the error, if any,
result:     mix  Response to the request (the format depends on the requested method),
}

The format of the .result field depends on the specific method (parameter method). See Methods List.

Common System Errors #

The HTTP response status code will always be 200.

The error code is sent to the field .error of the result.

Value 0 means that there were no critical errors and you can process the .result field.

Otherwise (.error not a 0) you should not process the .result field.

In the .message field, a text message is sent about the error that occurred.

In the .errorinfo field, additional information about the causes of the error can be transmitted.

List of system-wide errors:

Errors specific for each method are described in the appropriate subsections of the Methods List.

General concepts #

Agency (hoster)
Virusdie’ partner, hosting provider, digital agency or other larger enterprises - a stack of general data about partner: name, bank account details, contact, etc.
Unit (end customer indicator)
A specific feature you can use to associate any website from your Virusdie account with end customer. To share website feature management (turn on/off scans, website firewall, etc.) from your Virusdie account with end customer you need to transfer end client email address into Unit. Each website can be associated just with one Unit.
Site
You can add sites into your Virusdie account and then associate some of them with Units (end customers).
Share site
Means share website with end client (link website to Unit), using end client email address.

Methods List #

Send the one-time password by email #

GET /api/signup/<email>/

One-time password will be sent to the specified e-mail. This password could be used to authorize/register the user. It should be used with signin method later, when it will be provided by user.

If the user with the specified address does not exists in the database then it will be automatically created later by signin method with valid one-time password.

.result field value in a response #

{
user: {             // User data
    login: "str"    // User's login
    email: "str"    // User's email
    regdate: int    // Registration date, for existing users only, UNIX timestamp
}
otp: {              // One-time password info
    length: int     // The length of one-time password you should expect
    expires_in: int // One-time password will expire in (seconds)
    expires_at: int // Expiration time of one-time password, UNIX timestamp
}
}

Errors #

Verify one-time password, register user (if needed), get the new API key for the user #

Before using this method you should call the signup method to obtain the one-time password.

GET /api/signin/<email>/<otp>/

This method can automatically create the new user if such user does not already exist. In such case the new user will receive the email with instructions on how to login and to reset the account password.

.result field value in a response #

{
user: {             // User data
    login: "str"    // User's login
    email: "str"    // User's email
    regdate: int    // Registration date, for existing users only, UNIX timestamp
}
syncfile: {         // User's synchronization file (see also syncfile_get method)
    filename: "str" // Unique synchronization file name (e.g. "vdconnect-12345678.php")
    download: "str" // Synchronization file direct download URL (e.g. "http://...")
}
publickey: {        // The public key is stored on the server, used by the server to verify the authorization
    id: "str"       // Key ID
    key: "str"      // Key
    hmac: "str"     // Key for DS
}
privatekey: {       // Private key, used by the client for authorization, not stored on the server
    id: "str"       // Key ID
    key: "str"      // Key
    hmac: "str"     // Key for DS
}
keydata: {          // Metadata of generated keys
    owner: "str"    // Key owner identifier
    created: int    // Date of generation, UNIX timestamp
    modified: int   // Last key update date, UNIX timestamp
    expires: int    // The key expires at, if not 0, UNIX timestamp
    uid: "str"      // User login in the system (email)
    ip: "str"       // List of IP addresses from which the key can be used
    pid: "str"      // Parent public key ID
}
}

The newly created key for the user is located in .privatekey.key field. From now the user should use this key to interact with this API (like Cookie: apikey=...).

Errors #

Logout and delete the API key previously created by “signin” method #

This method will delete the currently used API key (the value of apikey cookie, see Authorization section). After deletion, this key can never be used again for authorization. You are able to delete the key only if it was previously created by signin method.

GET /api/signout/

No special params defined.

.result field value in a response #

On success, the .result will contain the same JSON-encoded object as in api_keyinfo section (the info on API key being deleted). On error, the .result will be null, and the error code/message will be reported in .error/.message fields.

Errors #

Get the dashboard login URL #

GET /api/dashboard/

No special params defined.

.result field value in a response #

The full dashboard URL as string. It includes all the data required to authorize the user in the dashboard. It will expire in 24 hours.

Errors #

No common errors for this method.

Create agency or update the agency (hoster) info #

This method will update your agency (hoster) info. If needed, the agency will be created transperently.

The agency info is a JSON-encoded object. It should be transferred via request body:

POST /api/agency_update/
Content-Type: application/json; charset=UTF-8

{
"title":            "Agency (hoster) name (str, required)",
"email":            "Contact email (str, required)",
"website":          "Website name in any form (str)",
"logourl":          "Hoster logo image URL starting from http[s]:// (str)",
"phone":            "Contact phone (str)",
"country":          "Country name or ISO 3166-1 code (str)",
"zipcode":          "Postal (ZIP) code (str)",
"address":          "Address in any form (str)",
"bank_currency":    "Bank: 3-digit currency code (USD, GBP) (str)",
"bank_swift":       "Bank: swift code (str)",
"bank_account":     "Bank: account number (str)",
"bank_routing":     "Bank: routing (str)",
"bank_country":     "Bank: country name or code (str)",
"bank_invoicemail": "Bank: email for invoices (str)",
}

The only required fields are: .title, .email.

.result field value in a response #

On success, the .result will contain the same JSON-encoded object as it was received via request body. Errors will be reported in .error/.message/.errorinfo fields.

Errors #

Delete the agency (hoster) info #

This method will delete your agency (hoster) info previously created by agency_update method.

GET /api/agency_delete/ [?ignore[=1]]

.result field value in a response #

On success, the .result will contain the same JSON-encoded object as described in agency_update section (the existing agency info) or null if the agency is not exists.

Errors #

View your agency (hoster) info #

This method will show the agency (hoster) info currently associated with your account, if any.

GET /api/agency_view/

No special params defined.

.result field value in a response #

On success, the .result will contain the same JSON-encoded object as described in agency_update section.

Errors #

Add sites into account (with additional options) #

The site list is a JSON-encoded array. It should be transferred via request body. Each element in this array can appear in any of the following forms: The “short” form is just a domain name string without any additional options. The “long” form is an object which can specify additional actions to perform for each site. Both “short” and “long” forms can be mixed.

POST /api/sites_add/
Content-Type: application/json; charset=UTF-8

[
    // Long form:
    {
        "name": "domain name (str, required)",
        "share": "share this site with (site owner email, str)",
        // More options could be added later...
    },

    // Short form:
    "domain name (str)",

    // More domains:
    {"name": "example1.com", "share": "admin@example1.com"},
    {"name": "example2.com"},
    "example3.com",
]

.result field value in a response #

The .result contains the the JSON-encoded object. Each field in the result holds the possible error message for the corresponding site index. If the N-th site has been added successfully, then there will be no item under the N-th index in the .result array. For the example above, the .result field will contain up to 5 error messages. The error message for “example1.com” will appear under index 2 and so on:
{"2": "Error message for example1.com", ...}.

Errors #

Site errors will be returned one per site in the .result field.

List sites in account (with extended info and filtering options) #

GET /api/sites_list/? [&unit=email] [&withscanreport] [&withscanhistory] [&withfwhistory]

.result field value in a response #

The .result will contain the array of sites described below. Depending on request options it can contain the extended information and historical data for each site.

[
    {                                 // Site object
        "id": int,                    // internal site ID in Virusdie database
        "host": "str",                // punycode encoded host name (ASCII)
        "domain": "str",              // host name in utf-8
        "adddate": int,               // the date (unix time) when this site has been added into database
        "scanperiod": int,            // the scanning interval in seconds
        "nextscan": int,              // the date (unix time) of the next scan in future
        "firewallstatus": int,        // firewall enabled (1) / disabled (0) flag
        "autotreatment": int,         // automatic cleanup enabled (1) / disabled (0) flag
        "permissions": int,           // permissions bitmask, see "site_setoption" method for more

        // Optional fields:

        "scanreport": {               // Most recent scan report data or NULL
            "id": int,                // Report identifier in Virusdie database
            "date": int,              // The date (UNIX time) of the report
            "cure": int,              // Cleanup (1) or simple scan (0)
            "threats": int,           // Total number of THREATS remaining after cleanup or scan:
            "incurable": int,         // The number of INCURABLE THREATS remaining after cleanup or scan
            "doubt": int,             // The number of SUSPICIONS remaining after cleanup or scan
            "treated": int,           // The number of THREATS WERE CLEANED during cleanup
            "detectedfiles": int,     // Total number of DETECTED FILES:
            "incurablefiles": int,    // The number of INCURABLE FILES
            "malicious": int,         // The number of MALICIOUS FILES
            "suspicious": int,        // The number of SUSPICIOUS FILES
            "checkeddirs": int,       // Total number of DIRECTORIES checked
            "checkedfiles": int,      // Total number of FILES checked
            "treatedfiles": int,      // The number of FILES WERE CLEANED
            "deletedfiles": int,      // The number of FILES WERE DELETED
            "totalbytes": int,        // Total amount of data to scan (bytes)
            "checkedbytes": int,      // The actual amount of scanned data (bytes)
            "errors": int,            // The number of scan errors occured
        },

        "scanhistory": {              // Historical scanning results for 30 days or NULL
            // The object contains key-value pairs. Each field name is the date
            // in "YYYYMMDD" form. The value describes the scanning results on
            // the specified date for the last 30 days:
            "20201201": "clean",      // No malware files were found on this site on 01.12.2020
            "20201215": "not-synced", // Scan errors: the site was not synchronized on 15.12.2020
            "20201231": "infected",   // Malware files were found on 31.12.2020
        },

        "fwhistory": {                // Firewall statistics for 30 days or NULL
            // The object contains key-value pairs. Each field name is the date
            // in "YYYYMMDD" form. The value describes the firewall statistics on
            // the specified date as array containing the following values:
            // 0: Date in form "YYYYMMDD" (20201201 in example)
            // 1: The number of regular (allowed) requests (100 in example)
            // 2: The number of blocked requests (18 in example)
            // 3: The number of DoS/DDoS requests (6 in example)
            // 4: The number of requests containing XSS/SQL injections (5 in example)
            // 5: The number of suspicious uploads (4 in example)
            // 6: The number of other suspicious activities (3 in example)
            // 7: Total number of unique IP addresses were blocked (2 in example)
            // Examples:
            "20201201": [20201201, 100,18, 6,5,4,3, 2],
            ...,
            "20201231": null,
        },
    },
    // ...
]

Errors #

Delete the site from account #

The site being deleted will be automatically unshared if needed. You can also delete all the sites currently shared with the specified unit by using unit_delete method.

GET /api/site_delete/<domain>/ [?ignore[=1]]

.result field value in a response #

If the specified domain is not found then null will be returned. Otherwise, the original domain name will be returned.

Errors #

Unshare the site if it was previously shared with some person (unit) #

If the site is shared with some unit (see sites_add method), then you can unshare this site. After this the site have no owner.

GET /api/site_unshare/<unit>/<domain>/

.result field value in a response #

The original domain name will be returned on success.

Errors #

Change site settings, additional services and options #

Set the specified option on the specified site.

GET /api/site_setoption/<domain>/<option>/<value>/

The options and the values:

(!) Features marked with (!) could be unavailable for the API key currently used.
In this case using of this features will result in 145904 “Permission denied” error.

.result field value in a response #

On success, the original request data will be returned as array of strings:

["<domain>", "<option>", "<value>"]

Errors #

Scan the site for malware #

The site_scan method preforms the site scan via the synchronizations file, which must already be uploaded into site root directory.

GET /api/site_scan/<domain>/

.result field value in a response #

On success, the original domain name will be returned.

Errors #

Change the unit’s email #

Change the email address of the specified unit to new_email. This change will affect all the sites currently shared with the specified unit.

GET /api/unit_update/<unit>/<new_email>/

.result field value in a response #

The new email address of the unit (new_email) will be returned on success.

Errors #

Delete the unit and unshare all sites currently shared with this unit #

All sites shared with the deleted unit will be unshared automatically. These sites will remain in your account unless &withsites argument is set.

GET /api/unit_delete/<unit>/? [&withsites[=1]] [&ignore[=1]]

.result field value in a response #

The email address of the unit will be returned on success.

Errors #

Download the synchronization file #

If you want to connect the site to Virusdie, then you need to place your unique synchronization file in the root directory of this site.

GET /api/syncfile_get/

No special params defined.

.result field value in a response #

This method does not return JSON.

On success, the raw content of the synchronization file (PHP code) will be sent in response with HTTP 200 status code. File name is sent in Content-Disposition and in X-Filename HTTP headers. The file must be uploaded to the site under this name.

Errors will be reported via HTTP status codes.

Errors #

Because this method returns raw data, errors will be reported via HTTP response status codes (4XX+) alongside with one of the following error messages:


Get the list of available methods #

The api_methodlist method allows you to get a list of method names available for the current user.

GET /api/api_methodlist/

.result field value in a response #

Array, the list of method names available under the current API key:

[
    "item1",
    ...
]

See api_methoddata.

Errors #

Get metadata about any available method #

The api_methoddata method allows you to view metadata about the specified method, if this method is available for the current user.

GET /api/api_methoddata/<methodname>/

.result field value in a response #

The object with the description of the requested method:

{
description: "str"  // Method description
alwaysRaw: int      // Always send the raw response for this method, never send the default JSON
httpMethods: "str"  // Restricted HTTP methods set
path: [             // Regular expressions to test request path entries
    "str",          // RegExp for first entry (can be empty)
    ...
]
argv: {             // Regular expressions to test named GET arguments
    name: "str",    // RegExp for entry '&name' (can be empty)
    ...
}
post: {...}         // Regular expressions to test POST arguments (same as .argv)
errprefix: int      // Prefix of method's error codes, 3 - digit number
errors: [           // Error messages
    "str",          // Message for error {.errprefix}900
    "str",          // Message for error {.errprefix}901 and so on
    ...
]
...                 // Method-specific configuration options, if any
}

All fields except .errprefix are optional.

Errors #

Get current API key metadata #

The api_keyinfo method allows you to view metadata about your current API key.

GET /api/api_keyinfo/

.result field value in a response #

An object with public key metadata.

Errors #

There are no special errors for this method

Get the info about key owner (registered user) #

The api_userinfo method allows you to view system user’s info if such user is associated with your API key.

GET /api/api_userinfo/

.result field value in a response #

An object with user data or null if there is no registered user associated with this key.

Errors #

There are no special errors for this method

Testing and debugging #

The api_test method can be used for testing purposes, request debugging, checking error handling mechanisms when developing client APIs.

GET|POST /api/api_test/<item1>/<item2>/<item3>/? &str=str &int=int [&nullint=int] [&err=int] [&raw=int]

You can pass any POST data in the request.

.result field value in a response #

Object containing the original request data:

{
    REQUEST_URI: "str"
    PATH: ["str", ...]
    QUERY: {...}
    HEADERS: {...}
    POST: {
        TYPE: "str"
        LENGTH: int
        DATA: "str"
    }
    FILES: [...]
}

If &raw != 0, then only the value of the .result field will be displayed as a text (no JSON).

Errors #


Methods List