A complete API guide for Virusdie partners and developers.
2024-08-30
Send HTTPS requests to virusdie.com.
A common request format is:
(GET|POST) https://virusdie.com/api/<method>/[param1/paramN][?query]
method
* - Method (action). Described in section Methods List.param1, paramN, ...
- Numbered parametersquery
- Named parameters, query stringTwo 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 transferapimac=hmac_value
argument.
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.
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:
500
- Service is temporarily unavailable501
- Internal system error502
- Authorization Error503
- Invalid request format504
- Method not implemented or not supported505
- A higher level of access is requiredErrors specific for each method are described in the appropriate subsections of the Methods List.
Authorization in third-party applications via email
Agency (hoster) info management
Sites management
Units management
Synchronization file
Common methods
GET /api/signup/<email>/
email
* - User’s e-mail (existing or new)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.
{
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
}
}
111900
- Failed to send the one-time password by email111901
- Registration is not allowedBefore using this method you should call the signup method to obtain the one-time password.
GET /api/signin/<email>/<otp>/
email
* - User’s e-mailotp
* - One-time password provided by userThis 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.
{
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=...
).
112900
- The email or password is unknown112901
- Failed to create the new user112902
- Failed to send the registration email112903
- Failed to generate the new API key112904
- Incompatible account typeThis 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.
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.
113900
- Database error113900
- You can only delete the keys created by “signin” methodGET /api/dashboard/
No special params defined.
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.
No common errors for this method.
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
.
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.
121900
- Database errorThis method will delete your agency (hoster) info previously created by agency_update method.
GET /api/agency_delete/ [?ignore[=1]]
ignore
- Ignore errors (do not report the error if there is no agency associated with your account)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.
122900
- Database error122901
- No agency is associated with your account (see “agency_update” method)This method will show the agency (hoster) info currently associated with your account, if any.
GET /api/agency_view/
No special params defined.
On success, the .result
will contain the same JSON-encoded object as described in agency_update section.
123900
- No agency is associated with your account (see “agency_update” method)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",
]
The .name
option (domain name) can appear in any form, using punycode or not.
Duplicate sites will not be added twice, so passing duplicated items is not an error. But in this case the additional options (if any) will overwrite the previous ones.
The .share
option allows you to share the site with the specified person (end customer).
For example, this person will receive the scan reports for this site and more.
For each unique email the distinct entity (so called “unit”) will be created in
database and all the sites with the same .share
option will be shared with this unit.
You can change the email address of the unit at any time (see unit_update method),
and the changes will affect all the sites currently shared with this unit.
In order to be able to share the site, you need to fill up the agency (hoster)
info by using the agency_update method.
See General concepts section for more.
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", ...}
.
141900
- Upgrade required (need to upgrade you subscription plan to add more sites)Site errors will be returned one per site in the .result
field.
GET /api/sites_list/? [&unit=email] [&withscanreport] [&withfwhistory]
unit
- Show only sites shared with this unitwithscanreport
- Add the most recent scan report data (.scanreport
) into result listwithfwhistory
- Add firewall statistics for 30 days (.fwhistory
) into result listThe .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
},
"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,
},
},
// ...
]
142900
- Unit not foundThe 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]]
domain
* - Domain name in UTF-8 (do not use punycode encoding)ignore
- Ignore errors (do not report the error if there is no such site in list)If the specified domain is not found then null
will be returned.
Otherwise, the original domain name will be returned.
143900
- Database error143901
- Site not foundIf 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>/
unit
* - The email address of the person the site was shared withdomain
* - Domain name in UTF-8 (do not use punycode encoding)The original domain name will be returned on success.
144900
- Database error144901
- Unit not found144902
- Site not found144903
- This site is not shared with this unitSet the specified option on the specified site.
GET /api/site_setoption/<domain>/<option>/<value>/
domain
* - Domain name in UTF-8 (do not use punycode encoding)option
* - The option name to change (see below)value
* - The value to set for the option (see below)The options and the values:
permissions
- Change the permissions (features) available for the user on this site, a bitmask of:
autocleanup
- Turn autocleanup on (1
) / off (0
) (!)autopatching
- Turn automatic patching on (1
) / off (0
) (!)firewall
- Enable (enable
), disable (disable
), uninstall (remove
) the Virusdie firewallscanperiod
- Change the interval between automatic scans: month
, week
, day
or 0
to disable auto scan(!) 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.
On success, the original request data will be returned as array of strings:
["<domain>", "<option>", "<value>"]
145900
- Database error145901
- Site not found145902
- Invalid option/value145903
- Operation failed145904
- Permission deniedThe 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>/
domain
* - Domain name in UTF-8 (do not use punycode encoding)On success, the original domain name will be returned.
146900
- Site not found146901
- Not available for this site146902
- Scanner initialization failedChange 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>/
unit
* - The current email address, the existing unitnew_email
* - New email address to set for this unitThe new email address of the unit (new_email
) will be returned on success.
131900
- Database error131901
- Unit not foundAll 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]]
unit
* - The email address of the existing unit to deletewithsites
- Also delete all sites currently shared with this unit (see also site_delete method)ignore
- Ignore errors (do not report the error if there is no such unit)The email address of the unit will be returned on success.
132900
- Database error132901
- Unit not foundIf 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.
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.
Because this method returns raw data, errors will be reported via HTTP response status codes (4XX+) alongside with one of the following error messages:
The api_methodlist method allows you to get a list of method names available for the current user.
GET /api/api_methodlist/
Array, the list of method names available under the current API key:
[
"item1",
...
]
See api_methoddata.
101900
- Error getting method list on serverThe 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>/
methodname
* - The name of the method to be displayedThe 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.
102900
- An unknown/unaccessible method is specified (field methodname
)The api_keyinfo method allows you to view metadata about your current API key.
GET /api/api_keyinfo/
An object with public key metadata.
There are no special errors for this method
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/
An object with user data or null
if there is no registered user associated with this key.
There are no special errors for this method
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]
item1
* - String a-zitem2
* - Number 0+item3
* - Any valuestr
* - Any valueint
* - Number 0+nullint
- If present, there must be a number 0+err
- If present and non-zero, then stop the request with an errorraw
- If present and non-zero, then display only .result field value as a text (no JSON)You can pass any POST data in the request.
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).
100900
- Test error message 0100901
- Test error message 1