API

Table of contents

Purpose

This document describes the JSON-RPC API provided by the Zonemaster RPC API daemon. This API provides means to check the health of domains and to fetch domain health reports. Health checks are called tests in Zonemaster lingo.

Protocol

This API is implemented using JSON-RPC 2.0.

JSON-RPC request objects are accepted in the body of HTTP POST requests to any path. The HTTP request must contain the header Content-Type: application/json.

All JSON-RPC request and response objects have the keys "jsonrpc", "id" and "method". For details on these, refer to the JSON-RPC 2.0 specification.

Deviations from JSON-RPC 2.0

Notes on the JSON-RPC 2.0 implementation

Request handling

When a method expects a string argument but receives an array or an object, the value may be interpreted as something like "ARRAY(0x1a2d1d0)" or "HASH(0x1a2d2c8)".

When a method expects a boolean argument, any kind of value is accepted. A number of values are interpreted as false: false, null, "", "0" and any number equal to zero. Everything else is interpreted as true.

When a method expects an integer arguments, numbers encoded in strings are also accepted and used transparently, and numbers with fractions are rounded to the nearest integer.

For details on when a test are performed after it's been requested, see the architecture documentation.

Error reporting

If the request object is invalid JSON, an error with code -32700 is reported.

If no method is specified or an invalid method is specified, an error with code -32601 is reported.

If no params object is specified when it is required, or the params object for the specified method is invalid, an error with code -32602 is reported. For more information on the validation error data format see Validation error data.

All error states that occur after the RPC method has been identified are reported as internal errors with code -32603.

Privilege levels

This API provides three classes of methods:

Data types

This sections describes a number of data types used in this API. Each data type is based on a JSON data type, but additionally imposes its own restrictions.

API key

Basic data type: string

A string of alphanumerics, hyphens (-) and underscores (_), of at least 1 and at most 512 characters. I.e. a string matching /^[a-zA-Z0-9-_]{1,512}$/.

Represents the password of an authenticated account (see Privilege levels)

Batch id

Basic data type: number

A strictly positive integer.

The unique id of a batch.

Client id

Basic data type: string

A string of alphanumerics, hyphens, underscores, pluses (+), tildes (~), full stops (.), colons (:) and spaces ( ), of at least 1 and at most 50 characters. I.e. a string matching /^[a-zA-Z0-9-+~_.: ]{1,50}$/.

Represents the name of the client. Used for monitoring which client (GUI) uses the API.

Client version

Basic data type: string

A string of alphanumerics, hyphens, pluses, tildes, underscores, full stops, colons and spaces, of at least 1 and at most 50 characters. I.e. a string matching /^[a-zA-Z0-9-+~_.: ]{1,50}$/.

Represents the version of the client. Used for monitoring which client (GUI) uses the API.

Domain name

Basic data type: string

  1. If the string is a single character, that character must be ..

  2. The length of the string must not be greater than 254 characters.

  3. When the string is split at . characters (after IDNA conversion, if needed), each component part must be at most 63 characters long.

Note: Currently there are no restrictions on what characters that are allowed.

DS info

Basic data type: object

DS for Delegation Signer references a DNSKEY record in the delegated zone.

Properties:

IP address

Basic data type: string

This parameter is a string that is either

Language tag

Basic data type: string

A string matching one of the following regular expression:

The set of valid language tags is further constrained by the LANGUAGE.locale property.

E.g. if LANGUAGE.locale is "en_US en_UK sv_SE", all the valid language tags are "en_US", "en_UK", "sv_SE" and "sv".

The use of language tags that include the country code is deprecated (planned removal: v2023.1).

Design

The two first characters of the language tag are intended to be an ISO 639-1 two-character language code and the optional two last characters are intended to be an ISO 3166-1 alpha-2 two-character country code.

Out-of-the box support

A default installation will accept the following language tags:

Language | Preferred language tag | Deprecated language tag ---------|------------------------|------------------ Danish | da | da_DK English | en | en_US Spanish | es | es_ES Finnish | fi | fi_FI French | fr | fr_FR Norwegian| nb | nb_NO Swedish | sv | sv_SE

Name server

Basic data type: object

Properties:

Non-negative integer

Basic data type: number (integer)

A non-negative integer is either zero or strictly positive.

Priority

Basic data type: number (integer)

This parameter is any integer that will be used by The Zonemaster Test Agents to sort the test requests from highest to lowest priority. This parameter will typically be used in a setup where a GUI will send requests to the RPC API and would like to get response as soon as possible while at the same time using the idle time for background batch testing. The drawback of this setup will be that the GUI will have to wait for at least one background processing slot to become free (would be a few seconds in a typical installation with up to 30 parallel zonemaster processes allowed)

Profile name

Basic data type: string

This parameter is a case-insensitive string validated with the case-insensitive regex /^[a-z0-9]$|^[a-z0-9][a-z0-9_-]{0,30}[a-z0-9]$/i which must be predefined in the configuration file as specified in the Configuration document profile sections.

The name of a profile.

Below are the current error messages for an incorrect profile name. The messages should, however, considered to be unstable and are planned to be updated to gain consistent error messages from the RPCAPI.

When a method receives an illegal profile name value for a parameter with this type, it returns the following error message:

{
    "jsonrpc":"2.0",
    "id":1,
    "error":{
        "message":"Invalid method parameter(s).",
        "data": [
            {
              "path": "/profile",
              "message": "String does not match (?^ui:^[a-z0-9]$|^[a-z0-9][a-z0-9_-]{0,30}[a-z0-9]$)."
            },
        ],
        "code":"-32602"
    }
}

When a method receives a legal but undefined profile name value for a parameter with this type, it returns the following error message:

{
    "jsonrpc":"2.0",
    "id":1,
    "error":{
        "message":"Invalid method parameter(s).",
        "data": [
            {
              "path": "/profile",
              "message": "Unknown profile"
            },
        ],
        "code":"-32602"
    }
}

The error code is "009" (as above) if method [start_domain_test][API start_domain_test] was requested. Instead it will be "015" if method add_batch_job is requested.

Progress percentage

Basic data type: number (integer)

An integer ranging from 0 (not started) to 100 (finished).

Queue

Basic data type: number (integer)

This parameter allows an optional separation of testing in the same database. The default value for the queue is 0. It is closely related to the ZONEMASTER.lock_on_queue parameter of the backend_config.ini file. The typical use case for this parameter would be a setup with several separate Test Agents running on separate physical or virtual machines each one dedicated to a specific task, for example queue 0 for frontend tests and queue 1 dedicated to batch testing. Running several Test Agents on the same machine is currently not supported.

Severity level

Basic data type: string

One of the strings (in order from least to most severe):

Severity levels in Zonemaster are defined in the Severity Level Definitions document. The following severity levels are not available through the RPCAPI (in order from least to most severe):

Test id

Basic data type: string

A string of exactly 16 lower-case hex-digits matching /^[0-9a-f]{16}$/.

Each test has a unique test id.

Test result

Basic data type: object

The object has four keys, "module", "message", "level" and "testcase".

Sometimes additional keys are present.

Timestamp (deprecated)

Basic data type: string

Deprecated representation (planned removal: v2023.1).

Default database timestamp format: "Y-M-D H:M:S.ms". Example: "2017-12-18 07:56:17.156939"

Timestamp

Basic data type: string

A string representing a date and time using the following ISO 8601 format: "YYYY-MM-DDThh:mm:ssZ". Example: "2017-12-18T07:56:17Z"

Username

Basic data type: string

A string of alphanumerics, dashes, full stops and at-signs, of at least 1 and at most 50 characters. I.e. a string matching /^[a-zA-Z0-9-.@]{1,50}$/.

Represents the name of an authenticated account (see Privilege levels)

Validation error data

Basic data type: array

The items of the array are objects with two keys, "path" and "message":

API method: version_info

Returns the version of the Zonemaster-LDNS, Zonemaster-Engine and Zonemaster-Backend software combination.

Example request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "version_info"
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "zonemaster_ldns": "1.0.1",
    "zonemaster_backend": "1.0.7",
    "zonemaster_engine": "v1.0.14"
  }
}

"result"

An object with the following properties:

"error"

TODO: List all possible error codes and describe what they mean enough for clients to know how react to them.

API method: profile_names

Returns the names of the public subset of the available profiles.

Example request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "profile_names"
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    "default",
    "another-profile"
  ]
}

"result"

An array of Profile names in lower case. "default" is always included.

API method: get_language_tags

Returns the set of valid language tags.

Note: If there are two locale tags in LANGUAGE.locale that would give the same short language tag then the short tag is excluded from the set of valid language tags.

Note: Language tags that include country code are deprecated (planned removal: v2023.1).

Example request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "get_language_tags"
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    "da",
    "da_DK",
    "en",
    "en_US",
    "es",
    "es_ES",
    "fi",
    "fi_FI",
    "fr",
    "fr_FR",
    "nb",
    "nb_NO",
    "sv",
    "sv_SE"
  ]
}

"result"

An array of language tags. It is never empty.

"error"

TODO: List all possible error codes and describe what they mean enough for clients to know how react to them. Or prevent RPCAPI from starting with errors in the configuration file and make it not to reread the configuration file while running.

API method: get_host_by_name

Looks up the A and AAAA records for a hostname (domain name) on the public Internet.

Example request:

Valid syntax:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "get_host_by_name",
  "params": {"hostname": "zonemaster.net"}
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": [
    {
      "zonemaster.net": "192.134.4.83"
    },
    {
      "zonemaster.net": "2001:67c:2218:3::1:83"
    }
  ]
}

"params"

An object with the property:

"result"

A list of one or two objects representing IP addresses (if 2 one is for IPv4 the other for IPv6). The objects each have a single key and value. The key is the domain name given as input. The value is an IP address for the name, or the value 0.0.0.0 if the lookup returned no A or AAAA records.

TODO: If the name resolves to two or more IPv4 address, how is that represented?

"error"

{
  "error": {
    "message": "Invalid method parameter(s).",
    "code": "-32602",
    "data": [
      {
        "path": "/hostname",
        "message": "Missing property"
      }
    ]
  },
  "jsonrpc": "2.0",
  "id": 1624630143271
}

API method: get_data_from_parent_zone

Returns all the NS/IP and DS/DNSKEY/ALGORITHM pairs of the domain from the parent zone.

Example request: Valid syntax:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "get_data_from_parent_zone",
  "params": {"domain": "zonemaster.net"}
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "ns_list": [
      {
        "ns": "ns.nic.se",
        "ip": "2001:67c:124c:100a::45"
      },
      {
        "ns": "ns.nic.se",
        "ip": "91.226.36.45"
      },
      ...
    ],
    "ds_list": [
      {
        "algorithm": 5,
        "digtype": 2,
        "keytag": 54636,
        "digest": "cb496a0dcc2dff88c6445b9aafae2c6b46037d6d144e43def9e68ab429c01ac6"
      },
      {
        "keytag": 54636,
        "digest": "fd15b55e0d8ee2b5a8d510ab2b0a95e68a78bd4a",
        "algorithm": 5,
        "digtype": 1
      }
    ]
  }
}

Note: The above example response was abbreviated for brevity to only include the first two elments in each list. Omitted elements are denoted by a ... symbol.

"params"

An object with the properties:

"result"

An object with the following properties:

"error"

{
  "error": {
    "data": [
      {
        "message": "The domain name character(s) are not supported",
        "path": "/domain"
      }
    ],
    "code": "-32602",
    "message": "Invalid method parameter(s)."
  },
  "id": 1624630143271,
  "jsonrpc": "2.0"
}

API method: start_domain_test

Enqueues a new test and returns the test id of the test.

Example request:

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "start_domain_test",
  "params": {
    "client_id": "Zonemaster Dancer Frontend",
    "domain": "zonemaster.net",
    "profile": "default",
    "client_version": "1.0.1",
    "nameservers": [
      {
        "ip": "2001:67c:124c:2007::45",
        "ns": "ns3.nic.se"
      },
      {
        "ip": "192.93.0.4",
        "ns": "ns2.nic.fr"
      }
    ],
    "ds_info": [],
    "ipv6": true,
    "ipv4": true
  }
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": "c45a3f8256c4a155"
}

"params"

An object with the following properties:

"result"

A test id.

If a test has been requested with the same parameters (as listed below) not more than "reuse time" ago, then a new request will not trigger a new test. Instead the test id of the previous test will be returned. The default value of "reuse time" is 600 seconds, and can be set by the ZONEMASTER.age_reuse_previous_test key in the configuration file.

The parameters that are compared when to determine if two requests are to be considered to be the same are domain, ipv6, ipv4, nameservers, ds_info and profile.

"error"

Example of error response:

{
  "error": {
    "code": "-32602",
    "data": [
      {
        "message": "Expected integer - got string.",
        "path": "/ds_info/0/algorithm"
      },
      {
        "message": "Missing property.",
        "path": "/ds_info/0/digest"
      },
      {
        "path": "/profile",
        "message": "Unknown profile"
      },
      {
        "path": "/domain",
        "message": "The domain name character(s) are not supported"
      },
      {
        "path": "/nameservers/0/ip",
        "message": "Invalid IP address"
      }
    ],
    "message": "Invalid method parameter(s)."
  },
  "id": 1,
  "jsonrpc": "2.0"
}

API method: test_progress

Reports on the progress of a test.

Example request:

Valid syntax:

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "test_progress",
  "params": {"test_id": "c45a3f8256c4a155"}
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": 100
}

"params"

An object with the property:

"test_id": A test id, required. The test to report on.

"result"

A progress percentage.

"error"

TODO: List all possible error codes and describe what they mean enough for clients to know how react to them.

API method: get_test_results

Return all test result objects of a test, with messages in the requested language as selected by the language tag.

Example request:

{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "get_test_results",
  "params": {
    "id": "c45a3f8256c4a155",
    "language": "en"
  }
}

The id parameter must match the result in the response to a start_domain_test call, and that test must have been completed.

Example response:

{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "creation_time": "2016-11-15 11:53:13.965982",
    "created_at": "2016-11-15T11:53:13Z",
    "hash_id": "c45a3f8256c4a155",
    "params": {
      "ds_info": [],
      "client_version": "1.0.1",
      "domain": "zonemaster.net",
      "profile": "default",
      "ipv6": true,
      "nameservers": [
        {
          "ns": "ns3.nic.se",
          "ip": "2001:67c:124c:2007::45"
        },
        {
          "ip": "192.93.0.4",
          "ns": "ns2.nic.fr"
        }
      ],
      "ipv4": true,
      "client_id": "Zonemaster Dancer Frontend"
    },
    "testcase_descriptions": {
      "ZONE08": "MX is not an alias",
      "SYNTAX05": "Misuse of '@' character in the SOA RNAME field",
      ...
    },
    "results": [
      {
        "module": "SYSTEM",
        "message": "Using version v1.0.14 of the Zonemaster engine.\n",
        "level": "INFO"
      },
      {
        "message": "Configuration was read from DEFAULT CONFIGURATION\n",
        "level": "INFO",
        "module": "SYSTEM"
      },
      ...
    ]
  }
}

Note: The above example response was abbreviated for brevity to only include the first two elments in each list. Omitted elements are denoted by a ... symbol.

"params"

An object with the following properties:

"result"

If the test was created by start_domain_test then "params" is a normalized version "params" object sent to start_domain_test when the test was created.

If the test was created with add_batch_job then "params" is a normalized version of an object created from the following parts:

TODO: Change name in the API of "hash_id" to "test_id"

"error"

TODO: List all possible error codes and describe what they mean enough for clients to know how react to them.

API method: get_test_history

Returns a list of completed tests for a domain.

Example request:

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "get_test_history",
  "params": {
    "offset": 0,
    "limit": 200,
    "filter": "all",
    "frontend_params": {
      "domain": "zonemaster.net"
    }
  }
}

Example response:

{
  "id": 7,
  "jsonrpc": "2.0",
  "result": [
    {
      "id": "c45a3f8256c4a155",
      "creation_time": "2016-11-15 11:53:13.965982",
      "created_at": "2016-11-15T11:53:13Z",
      "undelegated": true,
      "overall_result": "error",
    },
    {
      "id": "32dd4bc0582b6bf9",
      "undelegated": false,
      "creation_time": "2016-11-14 08:46:41.532047",
      "created_at": "2016-11-14T08:46:41Z",
      "overall_result": "error",
    },
    ...
  ]
}

Note: The above example response was abbreviated for brevity to only include the first two elments in each list. Omitted elements are denoted by a ... symbol.

Undelegated and delegated

A test is considered to be "delegated" below if the test was started, by start_domain_test or add_batch_job without specifying neither "nameserver" nor "ds_info". Else it is considered to be "undelegated".

"params"

An object with the following properties:

The value of "frontend_params" is an object with the following properties:

"result"

An object with the following properties:

"error"

TODO: List all possible error codes and describe what they mean enough for clients to know how react to them.

API method: add_api_user

In order to use the add_batch_job method a username and its api key must be added by this method.

This method is not available if RPCAPI.enable_add_api_user is disabled (disabled by default). This method is not available unless the connection to RPCAPI is over localhost (administrative method).

Example request:

{
  "jsonrpc": "2.0",
  "method": "add_api_user",
  "id": 4711,
  "params": {
    "username": "citron",
    "api_key": "fromage"
  }
}

Example response:

{
  "id": 4711,
  "jsonrpc": "2.0",
  "result": 1
}

"params"

An object with the following properties:

"result"

An integer. The value is equal to 1 if the registration is a success, or 0 if it failed.

"error"

TODO: List all possible error codes and describe what they mean enough for clients to know how react to them.

Trying to add a already existing user:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "data": {
      "username": "citron"
    },
    "message": "User already exists",
    "code": -32603
  }
}

Omitting params:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": "-32602",
    "message": "Invalid method parameter(s).",
    "data": [
      {
        "message": "Expected string - got null.",
        "path": "/api_key"
      }
    ]
  }
}
{
  "error": {
    "data": [
      {
        "path": "/username",
        "message": "Expected string - got null."
      }
    ],
    "message": "Invalid method parameter(s).",
    "code": "-32602"
  },
  "jsonrpc": "2.0",
  "id": 1
}

Trying to add a user over non-localhost:

{
  "id": 1,
  "jsonrpc": "2.0",
  "error": {
    "code": -32603,
    "data": {
      "remote_ip": "10.0.0.1"
    },
    "message": "Call to \"add_api_user\" method not permitted from a remote IP"
  }
}

Trying to add a user when the method is disabled:

{
  "error": {
    "code": -32601,
    "message": "Procedure 'add_api_user' not found"
  }
}

API method: add_batch_job

Add a new batch test composed by a set of domain name and a params object. All the domains will be tested using identical parameters.

This method is not available if RPCAPI.enable_add_batch_job is disabled (enabled by default).

A username and its api key can be added with the add_api_user method. A username can only have one un-finished batch at a time.

Tests enqueud using this method are assigned a priority of 5.

Example request:

{
  "jsonrpc": "2.0",
  "id": 147559211348450,
  "method": "add_batch_job",
  "params" : {
    "api_key": "fromage",
    "username": "citron",
    "test_params": {},
    "domains": [
      "zonemaster.net",
      "domain1.se",
      "domain2.fr"
    ]
  }
}

Example response:

{
    "jsonrpc": "2.0",
    "id": 147559211348450,
    "result": 8
}

"params"

An object with the following properties:

The value of "test_params" is an object with the following properties:

"result"

A batch id.

"error"

Trying to add a batch when a batch is still running for the username in the request:

{
  "jsonrpc": "2.0",
  "error": {
    "data": {
      "creation_time": "2021-09-27 07:33:40",
      "created_at": "2021-09-27T07:33:40Z",
      "batch_id": 1
    },
    "code": -32603,
    "message": "Batch job still running"
  },
  "id": 1
}

Trying to add a batch when wrong username or api key is used:

{
  "error": {
    "message": "User not authorized to use batch mode",
    "code": -32603,
    "data": {
      "username": "citron"
    }
  },
  "id": 1,
  "jsonrpc": "2.0"
}

Trying to add a batch with an empty list of domains:

{
  "id": 1,
  "jsonrpc": "2.0",
  "error": {
    "data": [
      {
        "message": "Not enough items: 0/1.",
        "path": "/domains"
      }
    ],
    "message": "Invalid method parameter(s).",
    "code": "-32602"
  }
}

Trying to add a batch when the method has been disabled.

{
  "error": {
    "message": "Procedure 'add_batch_job' not found",
    "code": -32601
  }
}

API method: get_batch_job_result

Return all test id objects of a batch test, with the number of finshed test.

Example request:

Valid syntax:

{
    "jsonrpc": "2.0",
    "id": 147559211994909,
    "method": "get_batch_job_result",
    "params": {"batch_id": "8"}
}

Example response:

{
   "jsonrpc": "2.0",
   "id": 147559211994909,
   "result": {
      "nb_finished": 5,
      "finished_test_ids": [
         "43b408794155324b",
         "be9cbb44fff0b2a8",
         "62f487731116fd87",
         "692f8ffc32d647ca",
         "6441a83fcee8d28d"
      ],
      "nb_running": 195
   }
}

"params"

An object with the property:

"result"

An object with the following properties:

"error"

If the batch_id is undefined the following error is returned:

{
  "id": 1,
  "error": {
    "data": {
      "batch_id": "10"
    },
    "message": "Unknown batch",
    "code": -32603
  },
  "jsonrpc": "2.0"
}

API method: get_test_params

Return a normalized params objects of a test.

Example request:

Valid syntax:

{
    "jsonrpc": "2.0",
    "id": 143014426992009,
    "method": "get_test_params",
    "params": {"test_id": "6814584dc820354a"}
}

Example response:

{
    "jsonrpc": "2.0",
    "id": 143014426992009,
    "result": {
         "domain": "zonemaster.net",
         "profile": "default",
         "client_id": "Zonemaster Dancer Frontend",
         "nameservers": [
            {
                "ns": "ns3.nic.se",
                "ip": "2001:67c:124c:2007::45"
            },
            {
                "ip": "192.93.0.4",
                "ns": "ns2.nic.fr"
            }
         ],
         "ipv4": true,
         "ipv6": true,
         "client_version": "1.0.1",
         "ds_info": []
    }
}

"params"

An object with the property:

"result"

The "params" object sent to start_domain_test or add_batch_job when the test was started.

"error"

TODO: List all possible error codes and describe what they mean enough for clients to know how react to them.