Sample Implementations

Following is sample implementations for constructing and submitting an API request using HMAC authentication in some of the most popular programming languages. In these samples we use our timeservice as an example, the sample implementation is however applicable to all of our services.

C#/.NET

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Security.Cryptography;
using System.Net;
using System.Web;
 
// ...
String entrypoint = "http://api.xmltime.com/";
String accesskey = "NYczonwTxv";
String secretkey = "x4whvXnG7cCOBiNBoi1r";

public String servicecall(String service, NameValueCollection iargs) {
    // Hash computation
    var timestamp = DateTime.UtcNow.ToString("o");
    var message = accesskey + service + timestamp;
    var hmac = new HMACSHA1(System.Text.Encoding.ASCII.GetBytes(secretkey));
    var hash = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(message));

    // Copy arguments and add authentication parameters
    var args = new NameValueCollection(iargs);
    args.Set("accesskey", accesskey);
    args.Set("timestamp", timestamp);
    args.Set("signature", Convert.ToBase64String(hash));

    // Generate URI from the arguments
    List<String> items = new List<String>();
    foreach (String key in args.AllKeys)
        items.Add(String.Concat(HttpUtility.UrlEncode(key), "=", HttpUtility.UrlEncode(args[key])));

    UriBuilder uri = new UriBuilder(entrypoint + service);
    uri.Query = String.Join("&", items.ToArray());

    // Retrieve data and return it
    using (WebClient client = new WebClient()) {
        client.Encoding = System.Text.Encoding.UTF8;
        return client.DownloadString(uri.Uri);
    }
}

// Getting data as String:
String timedata = servicecall("timeservice",
        new NameValueCollection {{"placeid", "norway/oslo"}, {"out", "js"}})

JavaScript/Node.js

Requires third-party dependency axios.

const crypto = require('crypto'); // https://nodejs.org/api/crypto.html
const axios = require("axios"); // 

const entrypoint = 'http://api.xmltime.com/';
const accesskey = 'NYczonwTxv';
const secretkey = 'x4whvXnG7cCOBiNBoi1r';

function servicecall(service, args) {
  const timestamp = new Date().toISOString();
  const message = `${accesskey}${service}${timestamp}`;
  const signature = crypto.createHmac('sha1', secretkey)
                .update(message)
                .digest('base64');
  Object.assign(args, {
    accesskey,
    timestamp,
    signature
  });

  const query = Object.keys(args)
                  .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(args[key])}`)
                  .join("&")

  const url = `${entrypoint}/${service}?${query}`
  return axios.get(url).then( (res) => res.data);
}

servicecall("timeservice", { "placeid": "norway/oslo", "out": "js", "version": 2} )
  .then((res) => {
    console.log(JSON.stringify(res, null, 2));
  })
  .catch((e => {
    console.error(e);
  }))

Perl

use Digest::HMAC_SHA1;
use LWP::Simple;
use URI::Escape;
use POSIX qw(strftime);

sub servicecall($%);

my ($entrypoint, $accesskey, $secretkey) =
    qw(http://api.xmltime.com/ NYczonwTxv x4whvXnG7cCOBiNBoi1r);

my $timedata = servicecall('timeservice', (placeid=>'norway/oslo', out=>'js');


sub servicecall($%) {
    my ($service, %args) = @_;
    my ($timestamp, $hmac, $signature, $query);

    $timestamp = strftime("%FT%T", gmtime());
    $hmac = Digest::HMAC_SHA1->new($secretkey);
    $hmac->add("$accesskey$service$timestamp");
    $signature = $hmac->b64digest;

    $args{accesskey} = $accesskey;
    $args{timestamp} = $timestamp;
    $args{signature} = $signature;

    $query = join(';', map { "$_=".uri_escape($args{$_}) } keys %args);

    return get("$entrypoint/$service?$query");
}

PHP

$entrypoint = 'http://api.xmltime.com/';
$accesskey = 'NYczonwTxv';
$secretkey = 'x4whvXnG7cCOBiNBoi1r';

$timedata = servicecall('timeservice', array('placeid'=>'norway/oslo'));

function servicecall($service, $args) {
    global $entrypoint, $accesskey, $secretkey;

    $timestamp = gmdate('c');
    $message = "$accesskey$service$timestamp";
    $signature = base64_encode(hash_hmac('sha1', $message, $secretkey, true));

    $args['accesskey'] = $accesskey;
    $args['timestamp'] = $timestamp;
    $args['signature'] = $signature;

    $url = "$entrypoint/$service?" . http_build_query($args);

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

Python

import base64, datetime, hashlib, hmac, urllib

entrypoint = "http://api.xmltime.com/"
accesskey = "NYczonwTxv"
secretkey = "x4whvXnG7cCOBiNBoi1r"

def servicecall(service, args):
    global entrypoint, accesskey, secretkey

    timestamp = datetime.datetime.utcnow().isoformat()
    message = accesskey + service + timestamp
    digester = hmac.new(secretkey, message, hashlib.sha1)

    args['accesskey'] = accesskey
    args['timestamp'] = timestamp
    args['signature'] = base64.b64encode(digester.digest())

    url = entrypoint + '/' + service + '?' + urllib.urlencode(args)
    return urllib.urlopen(url).read()

timedata = servicecall("timeservice", dict(placeid=187, out='js'))

Ruby

require 'base64'
require 'cgi'
require 'hmac-sha1'
require 'net/http'

$entrypoint = 'http://api.xmltime.com/'
$accesskey = 'NYczonwTxv'
$secretkey = 'x4whvXnG7cCOBiNBoi1r'

def servicecall(service, args)
    timestamp = Time.now.getutc.strftime('%FT%T')
    message = $accesskey + service + timestamp
    digest = HMAC::SHA1.digest($secretkey, message)

    args['accesskey'] = $accesskey
    args['timestamp'] = timestamp
    args['signature'] = Base64.encode64(digest).chomp

    query = args.collect do |key, value|
        [key.to_s, CGI::escape(value.to_s)].join('=')
    end.join(';')

    url = $entrypoint + '/' + service + '?' + query
    Net::HTTP.get(URI.parse(url))
end

timedata = servicecall('timeservice', { 'placeid'=>187, 'out'=>'js' })
prev top | next >
Terms & Conditions Copyright © Time and Date AS
All data supplied by timeanddate.com