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
gadgetkeyof the enabling gadget used to create the new gadget - the
nameof the gadget being created - and the user's
secretfor the enabling gadget
- the user's
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
gadgetkeyof 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
enablinggadgetkeyof the gadget used to make the activation - the registered
gadgetkeyof the gadget being activated - and the user's
secretfor that gadget
- the user's
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
secretfor that gadget
- the operation name
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
secretfor the gadget used
- the user's
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
- the user's
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
Locationheader. 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;
