mojo

Developer Guide

So you want to build a gadget, widget, web page or application that uses mojo?

First register your gadget, where you will be assigned a gadgetkey.

A user, such as yourself, may then activate the gadget so it can send text messages and make voice voice calls using their mojits (mojo credits) as well as get information about the user and the calls they've made. When a user activates a gadget, they receive a secret, which their gadget can use to authenticate when talking to Mojo.

We've example HTTP requests as well as test HTML pages, and examples using Curl, Ruby, Perl, PHP, and Python to help you on your way.

Register a Gadget

A gadget author should first visit the new gadget page and provide information including a name and a description to appear on the gadget's home page. The new gadget will be assigned a unique gadgetkey

gadgetkey
public identifier for the gadget, usually included with the gadget's source code

The developer of a gadget may provide more information about their gadget including an icon, screenshot and link back to their website and optionally be listed on the public gadget gallery page.

Alternatively, you can create a new gadget by doing an HTTP POST with the following form encoded parameters to http://mojo.bt.com/gadgets:

name
the name of the gadget to be created
username
the user who is the author of the gadget
description
description of the gadget (optional)
gadgetkey
the gadget being used to create the new gadget
digest
SHA1 hash (hexdigest) of the string created by concatenating the following values, separated by ":" (colons):
  • the user's username
  • the registered gadgetkey of the enabling gadget used to create the new gadget
  • the name of the gadget being created
  • and the user's secret for the enabling gadget

A successful HTTP response indicates the gadget has been created. The response returns the call details in the format specified in the request (html or xml), including the newly generated gadgetkey.

Activate a Gadget

A user must activate a gadget before being able to use it to make phone calls or send messages using their mojits. The activation process passes the following values to the gadget:

username
public identifier for the user of the gadget whose mojits will be used to pay for calls and messages.
secret
private password for each user of each gadget generated by mojo when a user activates the gadget, and which should not be divulged

The user has to cut and paste this information from the gadget's page. Alternatively, you can create a new gadget by doing an HTTP POST with the following form encoded parameters to http://mojo.bt.com/users/<username>/gadgets:

gadgetkey
the registered gadgetkey of the gadget to be activated
enablinggadgetkey
the gadget being used to send the activation request
activate
send "Yes" to confirm you want to activate this gadget for this user
digest
SHA1 hash (hexdigest) of the string created by concatenating the following values, separated by ":" (colons):
  • the user's username
  • the registered enablinggadgetkey of the gadget used to make the activation
  • the registered gadgetkey of the gadget being activated
  • and the user's secret for that gadget

A successful HTTP response indicates the gadget has been activated for this user. The response returns the call details in the format specified in the request (html or xml), including the newly generated GadgetSecret that the user can now use to make calls to the activated gadget.

Retrieving messages and calls with authentication

A gadget is able to GET URIs belonging to a user by appending a query string with the following two values:

gadgetkey
identifies the authenticated gadget
digest
SHA1 hash (hexdigest) of the string created by concatenating the following values, separated by ":" (colons):
  • the operation name 'call' or 'message'
  • the user's username
  • the registered gadgetkey
  • and the user's secret for that gadget

For example, the following URI returns the list of recent calls made by the user marty:

http://mojo.bt.com/messages/marty?gadgetkey=123&digest=abc

Send a Text Message

To send an SMS or other text message, HTTP POST the following form encoded parameters to http://mojo.bt.com/messages:

name
uniquely identifies the message for an individual username. An attempt to send a message with a name already used by the user will be rejected. The name should be a meaningful string provided by the user or a value generated by the gadget, such as a UUID, e.g. London-Weather-20070831, 7e2a1688-5819-11dc-8314-0800200c9a66.
recipient
telephone number to send the message to including the international prefix, e.g. +44770090000, or +15550100
text
message text, no more than 160 characters encoded as UTF-8
gadgetkey
the gadget being used to send the message
username
the user whose mojits will be used to pay for the message
digest
SHA1 hash (hexdigest) of the string created by concatenating the following values, separated by ":" (colons):
  • the user's username
  • the registered gadgetkey
  • the unique message name
  • and the user's secret for the gadget used

A successful HTTP response indicates the message request has been accepted for later processing. The response returns the message details in the format specified in the request (html or xml).

In order to accomodate situations where HTTP POSTS are a problem, you can create a message by an HTTP GET. Send the same parameters to http://mojo.bt.com/messages/sendMessage and the same result will be achieved.

Sending a message via an HTTP GET

We realise that due to cross domain issues, making an HTTP POST to another domain is not always possible. As a workaround, we also allow you to use an HTTP GET to send a message. To do so, send your request to http://mojo.bt.com/messages/sendMessage with the same parameters as you would when doing a post, e.g. http://mojo.bt.com/messages/sendMessage?recipient=44xxxxxx&name=newmessage...

Message Information

A gadget may construct an authenticated URI of the form:

http://mojo.bt.com/messages/<username>/<name>.xml

The following example illustrates the XML returned for a message:

 <message>
   <name>php1188816903</name>
   <recipient>tel:+44770090000</recipient>
   <text>Indian takeaway for supper?</text>
   <time type="datetime">2007-09-03T12:55:12+02:00</time>
   <status>SENT</status>
 </message>

The order of the elements has no significance and will change, also the XML will contain additional attributes and elements.

Changing the .xml suffix returns the resource in the appropriate representation, for example the URI:

http://mojo.bt.com/messages/<username>/<name>.json

returns the message information in the JSON format as follows:

{attributes: {
	status: "SENT",
	name: "message-32132-312321-3123",
	text: "who throws a shoe? really?",
	time: "2007-08-13 17:21:34",
	recipient: "tel:+44770090000" }},
}

As with the XML, the order of the items is not significant, may change and the JSON may contain additional values.

Recent Messages Sent

A list of recent messages sent is available as HTML from the URI http://mojo.bt.com/messages/<username>. A gadget, providing a authenticated URI, can retrieve this list in the Atom format by adding the .atom suffix, as well as .json, .xml and other representations.

Make a Voice Call

To initiate a voice call between two devices, HTTP POST the following form encoded parameters to http://mojo.bt.com/calls:

name
uniquely identifies the call for the given username. An attempt to send a call with a name already used by the user will be rejected. The name may be a meaningful name provided by the user or a value generated by the gadget, such as a UUID, e.g. Radio-Interview-20070831, 7e2a1688-5819-11dc-8314-0800200c9a66
caller
telephone number to be called first, including the international prefix, e.g. +44770090000, or +15550100
callee
telephone number called second, includes the international prefix, e.g. +44770090000, or +15550100
gadgetkey
the gadget being used to make the call
username
the user whose credits will be used to pay for the call
digest
SHA1 hash (hexdigest) of the string created by concatenating the following values, separated by ":" (colons):
  • the user's username
  • the registered gadgetkey
  • the unique call name
  • and the user's GadgetSecret

A successful HTTP response indicates the call request has been accepted for later processing. The response returns the call details in the format specified in the request (html or xml).

In order to accomodate situations where HTTP POSTS are a problem, you can create a call by an HTTP GET. Send the same parameters to http://mojo.bt.com/calls/makeCall and the same result will be achieved.

Recent Calls Made

A list of recent calls made is available to the user from the URI /calls/<username>, as JSON from /calls/<username>.json and as XML from /calls/<username>.xml An Atom feed containing a list of recent call requests is available to a gadget from a URI linked to from the user's home page.

Making a phone call with an HTTP GET

We realise that due to cross domain issues, making an HTTP POST to another domain is not always possible. As a workaround, we also allow you to use an HTTP GET to make a call. To make a call using a GET, send your request to http://mojo.bt.com/calls/makeCall with the same parameters as you would when doing a post, e.g. http://mojo.bt.com/calls/makeCall?caller=44xxxxxx&callee=44xxxxx...

HTTP Status Codes

The following HTTP status codes are returned by mojo:

201 Resource Created
A successful request and that a resource describing has been created, and may be dereferenced from the URI returned in the Location header.
402 Payment Required
The user had insufficient mojits to send the message or make the phone call.

Example HTTP Request

The following is an example HTTP request to send an SMS message to the UK mobile telephone number +44770090000:

HTTP 1.1
Content-Type: application/x-www-form-urlencoded

name=Foo-1188631665&
recipient=+44770090000&
text=Indian+takeaway+for+supper%3F&
username=marty&
gadgetkey=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15&
digest=4728005145627343c6483760e098ae746989f538

In this case the message request has been successful, as indicated by the a HTTP status code value which is not in the range 4xx or 5xx:

HTTP/1.1 201 Resouce Created
Date: Sat, 01 Sep 2007 07:27:50 GMT
Status: 201 Resource Created
Location: http://mojo.bt.com/messages/marty/Foo-1188631665
Content-Type: text/html; charset=utf-8
Content-Length: 137

<html> ....

Example Curl Script

The following Curl command sends a text message from the Unix bash shell:

name="curl-"$(date +"%s")
recipient="+44770090000"
text="I'm on the train!"
username="marty"
key="f1d2d2f924e986ac86fdf7b36c94bcdf32beec15"
secret="e242ed3bffccdf271b7fbaf34ed72d089537b42f"
digest=$(echo -n "${username}:${key}:${name}:${secret}" |
	openssl dgst -sha1)

curl -F "name=$name" \
     -F "recipient=$recipient" \
     -F "text=$text" \
     -F "username=$username" \
     -F "gadgetkey=$key" \
     -F "digest=$digest" \
     http://mojo.bt.com:/messages

A gadget may construct an authentication token using an OperationType ("message" or "call"), GadgetKey and GadgetSecret as follows:

auth="gadgetkey=$key&digest=$(
  echo -n "${type}:${key}:${secret}" | openssl dgst -sha1)"

which may then be used to GET information from mojo. For example the following returns information for an individual message as XML:

curl "http://mojo.bt.com/messages/$username/$name.xml&$auth"
and the following returns a list of recent messages sent in JSON:

curl "http://mojo.bt.com/messages/$username/$name.json&$auth"

Example HTML Form

The following example HTML form:

	<form name="gadget" id='GadgetForm' action="" method="POST">
		<span class="field">GadgetSecret:</field> 
		<input type="text" name="GadgetKey" id="GadgetSecret" value="ccc012344951ab5dca1234bbb9285a16b6ef0022" />
	</form>

	<form name="send" id='CallForm' action="http://mojo.bt.com/calls.xml" method="POST">
		<input type="text" name="name" />
		<input type="text" name="caller" value="+4479xxxxxxxxx"/>
		<input type="text" name="callee" value="+4479xxxxxxxxx"/>
		<input type="text" name="username" value="ronburgundy" />
		<input type="text" name="gadgetkey" value="bd6d29c8fe040809bcb1ccb4cda49879e9f4b3f9" />
		<input type="text" name="digest" value="" />
		<input type="button" name="calculate" value="calculate" onClick="calcDigest(this.form);"/>
		<input type="submit" name="send" value="send"/>
	</form>

uses the following Javascript snippet to calculate the digest:

<script type="text/javascript" src="sha1.js"></script>
<script language="JavaScript">
function calcDigest(form) {
	var digestString =
		form.username.value + ":"+
		form.gadgetkey.value + ":"+
		form.name.value + ":"+
		document.getElementById('GadgetSecret').value;
	form.digest.value = sha1(digestString);
}
</script>

Example Ruby Script

The following ruby script sends a text message:

require 'digest/sha1'
require 'net/http'
require 'uri'

name="ruby-" + Time.now().strftime("%s")
username="psd"
key="c9722348e8eadd9d0d980d8c8438cf66f43ec911"
secret="1189078987"
digest=Digest::SHA1.hexdigest(
	"#{username}:#{key}:#{name}:#{secret}")

form = { 'name'=> name,
    	'recipient'=> "+44770090000",
    	'text'=> "hello I'm on the train!",
    	'username'=> username,
    	'gadgetkey'=> key,
    	'digest'=> digest }

uri = URI.parse("http://mojo.bt.com/messages")

# ruby 1.9 and later:
print Net::HTTP.post_form(uri,form)

Example PHP Script

The following PHP script sends a text message:

<?php
$name = "php-" . time();
$recipient = "+44770090000";
$msgText = "I'm on the train!";
$username = "marty";
$key = "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15";
$secret = "e242ed3bffccdf271b7fbaf34ed72d089537b42f";
$digest = sha1(""$username:$key:$name:$secret"");

$params =
   "name=".urlencode($name) ."&".
   "recipient=".urlencode($recipient) ."&".
   "text=".urlencode($msgText) ."&".
   "gadgetkey=".urlencode($key) ."&".
   "username=".urlencode($username) ."&" .
   "digest=".urlencode($digest);

$post = curl_init("http://mojo.bt.com/messages");
curl_setopt($post, CURLOPT_HEADER, 1);
curl_setopt($post, CURLOPT_POST, 1);
curl_setopt($post, CURLOPT_POSTFIELDS, $params);
curl_setopt($post, CURLOPT_RETURNTRANSFER, 1);
echo curl_exec($post);
curl_close($post);
?>

Example Python Script

The following python script sends a text message:

import httplib, urllib, sha
from time import time

name="python-" + str(time())
recipient="+44770090000"
text="hello"
username="marty"
key="f1d2d2f924e986ac86fdf7b36c94bcdf32beec15"
secret="e242ed3bffccdf271b7fbaf34ed72d089537b42f"
digest=sha.new(username+":"+key+":"+name+":"+secret).hexdigest()

params = urllib.urlencode({
	'name': name,
	'recipient': recipient,
	'text': text,
	'username': username,
	'gadgetkey': key,
	'digest': digest
	})

headers = {"Content-type": "application/x-www-form-urlencoded"}
conn = httplib.HTTPConnection("mojo.bt.com")
conn.request("POST", "/messages", params, headers)
response = conn.getresponse()
print response.status, response.reason
print response.read()
conn.close()

Example Perl Script

The following perl script sends a text message:

use strict;
use Digest::SHA1;
use LWP::UserAgent;
use CGI;
 
my $name = "perl-" . time();
my $recipient = "+44770090000";
my $msgText = "I'm on the train!";
my $username = "ronburgundy";
my $key = "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15";
my $secret = "e242ed3bffccdf271b7fbaf34ed72d089537b42f";
 
my $digestInput = "$username:$key:$name:$secret";
my $digest = Digest::SHA1->new->add($digestInput)->hexdigest();
 
my $postdata = "name=" . CGI::escape($name) . 
              "&recipient=" . CGI::escape($recipient) . 
               "&text=" . CGI::escape($msgText) . 
               "&gadgetkey=" . CGI::escape($key) . 
               "&username=" . CGI::escape($username) . 
               "&digest=" . CGI::escape($digest);
 
my $uri = "http://mojo.bt.com/messages";
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(POST => $uri);
$req->content($postdata);
$req->header('Content-Type' => 'application/x-www-form-urlencoded');
 
my $res = $ua->request($req);
print $res->as_string;