HQAPI example API tutorial

HQAPI has a free Example web service made for learning and testing: three simple methods that work on no live data. That makes it a good first API to call. In this tutorial you get a token, try the methods with curl, and then call them from PHP and Python, errors included.

1. Get a free token

Register on hqapi.com. You are subscribed to the Example service right away, for free: 10,000 calls per month, one call at a time. Then open the Example service page and click Create API Token for Example.

The token is part of every address you call. In the samples below, replace YOUR_TOKEN with your own token. Keep it to yourself: anyone with the token can use your calls.

2. The three methods

Every method lives at https://api.eu-west.hqapi.com/api/v1/YOUR_TOKEN/example/ followed by its name, and every answer is JSON.

MethodCallWhat it does
nopGETDoes nothing and answers {}. Use it to test your connection and token.
addPOSTAdds two whole numbers a and b and answers {"value": a+b}.
pingPOST or GETEchoes the text you send as value.

3. Try it with curl

curl comes with macOS, Linux and Windows 10 and later. Run these in a terminal; the answer is shown below each command.

$ curl "https://api.eu-west.hqapi.com/api/v1/YOUR_TOKEN/example/nop"
{}

$ curl -X POST --data '{"a":2,"b":3}' \
    "https://api.eu-west.hqapi.com/api/v1/YOUR_TOKEN/example/add"
{"value":5}

$ curl "https://api.eu-west.hqapi.com/api/v1/YOUR_TOKEN/example/ping?value=Hello%2C+world%21"
{"value":"Hello, world!"}

With POST the arguments go in a JSON body; with GET they go in the address, URL-encoded (a comma becomes %2C, a space +).

4. Call it from PHP

This sample uses only what PHP has built in, no extra packages. The hqapi() function does a GET when there is no payload and a POST with JSON when there is, and turns an error answer into an exception.

<?php

// Call the HQAPI Example web service from PHP, without extra packages.
// Your free token: register on https://hqapi.com and create one on
// https://hqapi.com/api/example

$token = 'YOUR_TOKEN';
$base = 'https://api.eu-west.hqapi.com/api/v1/' . rawurlencode($token) . '/example/';

// Call a method: GET without a payload, POST with a JSON payload.
// Returns the JSON answer as an array, or throws on an error answer.
function hqapi($url, $payload = null)
{
    $options = array('http' => array(
        'method' => $payload === null ? 'GET' : 'POST',
        'header' => "Content-Type: application/json\r\n",
        'content' => $payload === null ? '' : json_encode($payload),
        'ignore_errors' => true, // also read the body of 400 and 401 answers
        'timeout' => 10,
    ));
    $body = file_get_contents($url, false, stream_context_create($options));
    if ($body === false) {
        throw new Exception('No answer from HQAPI');
    }
    $data = json_decode($body, true);
    if (!is_array($data)) {
        throw new Exception('HQAPI did not answer with JSON');
    }
    if (isset($data['code'])) {
        throw new Exception('HQAPI error ' . $data['code'] . ': ' . $data['message']);
    }
    return $data;
}

try {
    hqapi($base . 'nop');                                    // {}: the connection works
    $sum = hqapi($base . 'add', array('a' => 2, 'b' => 3));
    echo '2 + 3 = ' . $sum['value'] . "\n";                  // 2 + 3 = 5
    $echo = hqapi($base . 'ping', array('value' => 'Hello, world!'));
    echo $echo['value'] . "\n";                              // Hello, world!
} catch (Exception $e) {
    echo $e->getMessage() . "\n";
}

Output:

2 + 3 = 5
Hello, world!

5. Call it from Python

The same in Python 3, again with only the standard library:

# Call the HQAPI Example web service from Python, standard library only.
# Your free token: register on https://hqapi.com and create one on
# https://hqapi.com/api/example

import json
import urllib.error
import urllib.request

TOKEN = "YOUR_TOKEN"
BASE = f"https://api.eu-west.hqapi.com/api/v1/{TOKEN}/example/"


def hqapi(method, payload=None):
    """Call a method: GET without a payload, POST with a JSON payload."""
    data = None if payload is None else json.dumps(payload).encode()
    request = urllib.request.Request(BASE + method, data=data,
                                     headers={"Content-Type": "application/json"})
    try:
        with urllib.request.urlopen(request, timeout=10) as response:
            return json.load(response)
    except urllib.error.HTTPError as error:
        # 400 and 401 answers come with a JSON body: code and message
        body = json.load(error)
        raise RuntimeError(f"HQAPI error {body['code']}: {body['message']}") from None


hqapi("nop")                                         # {}: the connection works
print("2 + 3 =", hqapi("add", {"a": 2, "b": 3})["value"])   # 2 + 3 = 5
print(hqapi("ping", {"value": "Hello, world!"})["value"])   # Hello, world!

HQAPI also offers ready-made clients: pip install hqapi-client for Python and composer require hqapi/hqapi-client for PHP. Calling the API yourself first, as above, shows what those clients do for you.

6. When something goes wrong

Errors come back as JSON too, with an HTTP error status, a code and a message. Two you will meet:

$ curl "https://api.eu-west.hqapi.com/api/v1/WRONG_TOKEN/example/nop"
{"code":401,"message":"User token is unknown"}

$ curl -X POST --data '{"foo":"bar"}' \
    "https://api.eu-west.hqapi.com/api/v1/YOUR_TOKEN/example/ping"
{"code":400,"message":"Missing argument `value` in payload"}

Both samples check for this: the PHP sample prints HQAPI error 401: User token is unknown, the Python sample raises a RuntimeError with the same text. Always check for errors like this when you call a web service, so your program does not go on with an answer that is not there.

Next steps

HQAPI's paid services, such as its Screenshot API, are called the same way: a token in the address and JSON in and out. For more background, read How to consume a web service, or browse the free web services to find your next API.