Creating Measurements with the RIPE Atlas Restful API
This is still very much alpha code, so if you find an issue, please contact us with a bug report and be as detailed as possible. The more information we have, the more we can improve.
Measurement creation is managed based on the premise of having to submit as little information as possible while still obtaining something useful. With that said, even the simplest measurement requires a rather large amount of information to initiate things. We need the type, the af, the description, the target, and a specification telling us which probes you want to use for the measurement. If you omit the start_time, we assume you want it started right away; if you don't set the is_oneoff flag, we assume it must be a regular measurement, and so on.
Structure
Our REST API uses JSON to post data. If you haven't already, it's best to familarise yourself with how this is done before continuing. To get you started, we'll be providing all of the examples using a common *nix utility called curl.
Simple Example
Let's begin with an example. Assume we want to create a simple ping measurement from 50 probes anywhere in the world to ripe.net. Here's how to do this in curl:
$ curl -H "Content-Type: application/json" -H "Accept: application/json" -X POST -d '{ "definitions": [ { "target": "ripe.net", "description": "My First Measurement", "type": "ping", "af": 4 } ], "probes": [ { "requested": 50, "type": "area", "value": "WW" } ] }' https://atlas.ripe.net/api/v1/measurement/?key=YOUR_API_KEY
Response
{
"measurements": [
123456
]
}
Let's break it down to make it more readable.
-H "Content-Type: application/json"
This tells the server to expect POST data in JSON format.
-H "Accept: application/json"
This tells the server we're expecting JSON back.
-X POST
By default, curl sends GET requests. This just tells curl that we want to send a POST request instead.
-d '{...}'
Our POST request contains a lot of data, and as we specified with the Content-Type header, we'll be sending this data in JSON format. This -d flag tells curl to send the following string as the POST argument.
The actual POST Data
Let's take another look at what we're sending, but format it for humans:
{
"definitions": [
{
"target": "ripe.net",
"description": "My First Measurement",
"type": "ping",
"af": 4
}
],
"probes": [
{
"requested": 50,
"type": "area",
"value": "WW"
}
]
}
?key=YOUR_API_KEY
You can't just create a measurement and assign it to anyone; that wouldn't be fair. Instead, we make use of our API keys to identify the request as being authorised to create a measurement. You can create and manage your keys by visiting the API Keys page.
Basically, each request has three sections: definitions, probes and a third section we'll cover later in this document: times.
definitions
This is a list of measurement specifications, and it's probably the most complex section. This is where you specify parameters such as whether it's a one-off (is_oneoff) measurement, or that you want 10 packets instead of the default. However, each measurement requires a few simple things by default:
target: The target of the measurement. Note that this is not required fordnsmeasurements.description: An arbitrary string you will use to refer to this measurement.type: One ofping,traceroute,dns,sslcertorntpaf: The address family. It must be either4or6.
probes
This section is a little simpler - it's essentially a list of probe requests by region. For our basic case, there's only one request: 50 probes located anywhere in the world.
requested: The number of probes you want from the given region.type: The type of request. It can be one ofarea,country,prefix,asn,probesormsm.value: The lookup used against the giventype. This is explained in more detail below, but for our reasons, let's just work with the fact thatWWmeans world-wide.
Based on the above, our API will create a ping measurement hitting the first IPv4 address found at ripe.net, using 50 probes from various points all over the globe.
Definitions
A measurement definition contains a few core properties, and a myriad of type-specific options. For example, while all definitions have an af property, only traceroute measurements have a paris property. Given this, this section is broken up accordingly.
Core properties
These properties are available to all measurement types:
| Name | Description | Default | Required? | Price Modifier |
|---|---|---|---|---|
| description | The name you give this measurement. This field is entirely arbitrary. | YES | ||
| af | The address family. Must be either 4 or 6. | YES | ||
| type | The type of measurement you're attempting to create. Must be one of: ping, traceroute, dns, sslcert or ntp. | YES | ||
| resolve_on_probe | Set to 'true' if you want the probe to resolve your target instead of the RIPE Atlas servers. | false | ||
| is_oneoff | Set this to 'true' to make this measurement a one-off. | false | ||
| is_public | Set this measurement to be public, so that other people can see the results. | true | ||
| interval | In normal (not one-off) measurements, this value represents the number of seconds between measurements by a single probe. Note that while interval is defined for each measurement type, the default varies, so check the appropriate section below for the default for your specified type. | changes with type |
Ping-Specific Properties
Ping requests may use any of those mentioned in the Core Properties section, as well as the following:
| Name | Description | Default | Required? | Price Modifier |
|---|---|---|---|---|
| target | The target of your measurement. It can be an IP address or a (resolveable) hostname. | YES | ||
| interval | In normal (not one-off) measurements, this value represents the number of seconds between measurements by a single probe. | 240 | ||
| packets | The number of packets sent in the ping request. Value must be between 1 and 16 | 3 | × packets ÷ 3 | |
| size | The size of the packets. Value must be between 1 and 2048 | × size ÷ 1500 | ||
| packet_interval | Time between packets (ms). Value must be between 2 and 30000 | 1000 |
Traceroute-Specific Properties
Traceroute requests may use any of those mentioned in the Core Properties section, as well as the following:
| Name | Description | Default | Required? | Price Modifier |
|---|---|---|---|---|
| target | The target of your measurement. It can be an IP address or a (resolveable) hostname. | YES | ||
| interval | In normal (not one-off) measurements, this value represents the number of seconds between measurements by a single probe. | 900 | ||
| protocol | Must be one of ICMP, UDP or TCP. | ICMP | YES | |
| dontfrag | Don't fragment the packet. | false | ||
| paris | Use Paris. Value must be between 0 and 64. If 0, a standard traceroute will be performed. | 0 | NO | |
| firsthop | Value must be between 1 and 255 | |||
| maxhops | Value must be between 1 and 255 | |||
| timeout | Value (in milliseconds) must be between 1 and 60000 | 4000 | ||
| size | The size of the packets. Value must be between 1 and 2048 | × size ÷ 40 | ||
| port | Destination port, valid for TCP only. | 80 | ||
| destination_option_size | IPv6 destination option header | |||
| hop_by_hop_option_size | IPv6 hop by hop option header |
DNS-Specific Properties
DNS requests may use any of those mentioned in the Core Properties section, as well as the following:
| Name | Description | Default | Required? | Price Modifier |
|---|---|---|---|---|
| target | A hostname. | |||
| interval | In normal (not one-off) measurements, this value represents the number of seconds between measurements by a single probe. | 300 | ||
| do | Set the DNSSEC OK flag (RFC3225) | false | ||
| cd | Set the DNSSEC Checking Disabled flag (RFC4035) | false | ||
| use_probe_resolver | false | |||
| use_NSID | false | |||
| query_class | Must be either "IN" or "CHAOS". | YES | ||
| query_type |
Valid types vary by class: IN: A AAAA ANY CNAME DNSKEY DS MX NS NSEC PTR RRSIG SOA TLSA TXT SRV NAPTR CHAOS: TXT |
YES | ||
| query_argument | YES | |||
| recursion_desired | NOTE: For privacy reasons, when use_probe_resolver is true, this property is silently set to true. |
false | NO | |
| protocol | Must be either "TCP" or "UDP" | UDP | NO | × 2 |
| udp_payload_size | May be any integer between 512 and 4096 inclusive. | 512 | NO | |
| retry | Number of times to retry | 0 | NO |
SSL Certificate-Specific Properties
SSL certificate requests may use any of those mentioned in the Core Properties section, as well as the following:
| Name | Description | Default | Required? | Price Modifier |
|---|---|---|---|---|
| target | The target of your measurement. It can be an IP address or a (resolveable) hostname. | YES | ||
| interval | In normal (not one-off) measurements, this value represents the number of seconds between measurements by a single probe. | 1800 | ||
| port | 443 |
HTTP-Specific Properties
HTTP measurements may use any of those mentioned in the Core Properties section, as well as the following:
| Name | Description | Default | Required? | Price Modifier |
|---|---|---|---|---|
| target | The target of your measurement. It can be an IP address or a (resolveable) hostname. | YES | ||
| interval | In normal (not one-off) measurements, this value represents the number of seconds between measurements by a single probe. | 1800 | ||
| header_bytes | The maximum number of bytes to retrieve from the header. | 80 | ||
| version | The HTTP version to use | 1.1 | ||
| method | The HTTP method to use | GET | ||
| port | 443 | |||
| path | / | |||
| query_string | ||||
| user_agent | The user-agent used when performing the requrest | RIPE Atlas: https://atlas.ripe.net/ | ||
| max_bytes_read | ||||
| extended_timing | A boolean value. Time to Read, Time to Connect, Time to First Byte | |||
| more_extended_timing | A boolean value. |
NTP-Specific Properties
NTP requests may use any of those mentioned in the Core Properties section, as well as the following:
| Name | Description | Default | Required? | Price Modifier |
|---|---|---|---|---|
| target | The target of your measurement. It can be an IP address or a (resolveable) hostname. | YES | ||
| interval | In normal (not one-off) measurements, this value represents the number of seconds between measurements by a single probe. | 900 | ||
| packets | Number of requests to send | 3 | ||
| timeout | Time to wait for a response in milliseconds | 4000 |
Probes
probes, like definitions, is a list with nested sets of key/value pairs.
Basically, there are six types of requests: area, country, prefix, asn, probes and msm. In each case you'll be stating how many probes of that type you'd like to use, (requested) and what subsection of that type you're looking at (value). In addition, you can optionally further restrict each request using probe tags. We'll go over the request types one by one.
Area
For our purposes, the world is broken up into five arbitrary geographical areas:
WW(Worldwide)WestNorth-CentralSouth-CentralNorth-EastSouth-East
Country
If you want to request probes by country, specify the ISO two-letter country code here. For Canada for example, you would use CA, for the Netherlands NL, and for South Korea KR.
Prefix
This is an IP prefix. For example:
"probes": [
{
"requested": 5,
"type": "prefix",
"value": "193.3.6.0/8"
}
]
ASN
For ASNs, just the number is sufficient. For example:
"probes": [
{
"requested": 5,
"type": "asn",
"value": 3333
}
]
Probes
Probes can be explicitly requested by requesting type: "probe", and specifying a comma-separated list of integers as the value:
"probes": [
{
"requested": 3,
"type": "probes",
"value": "1,2,3"
}
]
Measurement (msm)
Finally, if you want to use the same probes used in a past measurement, you can employ this option. Simpley specify a measurement ID in the value field:
"probes": [
{
"requested": 1,
"type": "msm",
"value": 1000002
}
]
Additional: Probe tags
Any of the above request types can be further restricted based on probe tags.
This is achieved by specifying an optional "tags" item which may contain
one or both of "include" — a list of tags to require — and "exclude" — a list of tags to prohibit.
e.g. to request 10 probes from anywhere in the world which are in a datacentre, and do have working
IPv4 but do not have working IPv6:
"probes": [
{
"requested": 10,
"type": "area",
"value": "WW"
"tags": {
"include": ["datacentre", "system-ipv4-works"],
"exclude": ["system-ipv6-works"]
}
}
]
The Response
Not exactly RESTful - but probably more useful - the response to any successful POST request will render a key/value pairing, (presently with only one key: measurements). It will also render a list of values for that key: measurement IDs created from your POST, in the order they were specified in the definitions list.
Times
As we mentioned earlier, the API supports a third argument: times. As you might have guessed, this is a set of values dictating the start and end times for all measurements you're specifying in the request. In other words, if you send a single request to create two ping measurements targetting ripe.net, you can use times to specify when you'd like both measurements to start and finish. If you want to have two or more measurements start or stop at different times, you must define them in separate API calls.
An Example Request
We'll use our previous simple example, and attach times data to it:
{
"definitions": [
{
"target": "ripe.net",
"description": "My First Measurement",
"type": "ping",
"af": 4
}
],
"probes": [
{
"requested": 50,
"type": "area",
"value": "WW"
}
],
"start_time": 1388534400,
"stop_time": 1401580800
}
Note that times are always defined as Unix timestamps. In the example above, start_time is defined as 1 January 2014, and stop_time is set to 1 June 2014.
Note that you cannot set a start_time or stop_time in the past. Nor can you set a stop_time earlier than your start_time. Lastly, due to system limitations, you cannot have your start_time and stop_time less than five minutes apart. If you really need this kind of behaviour, you may be better served by a one-off measurement.
A Complex Measurement Request
The following code sample is provided as an example of how complicated this API can get, and is not meant to be executed.
{
"definitions": [
{
"target": "www.ripe.net",
"description": "My Complex Measurement",
"type": "traceroute",
"af": 6,
"resolve_on_probe": true,
"is_public": true,
"packets": 16,
"protocol": "ICMP",
"paris": 99,
"firsthop": 30,
"interval": 1800,
"is_oneoff": true
},
{
"target": "www.ripe.net",
"description": "My Complex Measurement",
"type": "ping",
"af": 4,
"resolve_on_probe": false,
"is_public": false,
"is_oneoff": false
}
],
"probes": [
{
"requested": 10,
"type": "area",
"value": "WW"
},
{
"requested": 5,
"type": "country",
"value": "GR"
},
{
"requested": 5,
"type": "country",
"value": "CA"
},
{
"requested": 3,
"type": "probes",
"value": [55,19,252]
},
{
"requested": 1,
"type": "udm",
"value": 1000002
}
],
"start_time": 1461807395,
"stop_time": 1462807395
}
The Response
{
"measurements": [
123456789,
123456790
]
}
Error Messages
As with all RESTful servers, you should write your code to act based on the HTTP error codes (404,401, etc.), but in the event that you receive an error, we have added some further explanations here to help you figure out what went wrong.
| Code | Message | Explanation |
|---|---|---|
| 100 | This server only accepts application/JSON content types. | The REST server is only capable of reading JSON data from your requests. |
| 101 | Your JSON POST request appears to be mal-formed. | Make sure your JSON data is properly formatted. Use an online parser if necessary. |
| 102 | Invalid input. Please check the documentation. | This error presents itself when some of the basic elements of a POST are missing. Make sure that you've supplied a value for definitions and probes, as well as values for description, type, and af in each definition and requested, type and value in each probe request. |
| 103 | You are not permitted to run more than %s concurrent measurements. | Users are limited to a finite number of measurements they can execute. Attempts to exceed this limit will result in this message. |
| 104 | (Variable) | This is a blanket error code assigned to any error message that prevents your measurement from running (over and above the others stated here). The message changes based on what's gone wrong, but examples include exceeding the limit of measurements targetting a particular domain, or specifying an excessive number of packets in a ping request. |
| 200 | That measurement cannot be stopped. | This error is raised when you try to stop a measurement that has already been stopped. |
