
Welcome to the first report from Project Ash, my
little project in which I plan to write PHP functions that will act as
wrappers for Tucows API calls! As I write the library that will house
these functions, I'll post reports from time to time that will apprise
you of my progress, explain some of my design decisions and cover some
details about the APIs that may not be covered in the official
documentation.
What's the Goal of Project Ash?
The goal is to have a PHP 4/5 open source library of functions that
allow you, as a developer, to worry less about the specifics of making
calls to our APIs and concentrate on creating you application. With
this library, it should be simple for someone with a Tucows API account
(and some PHP programming skill, but not a lot) to write a PHP client
that provisions Tucows services or to integrate Tucows service
functions into existing PHP applications. Possible applications for
such a library include:
- Full-service provisioning sites: These are sites
whose primary purpose is to provision and manage services such as
domain names and email accounts. The library should make it much easier
for you to build your own full-service client in PHP.
- Sites that offer Tucows services as features:
Perhaps you're running a dating site and would like to be able to offer
your users an email mailbox that's separate from their regular email
address. You can use the library to integrate email account
provisioning and management with your service.
- Offbeat apps and mash-ups: There are probably mash-up uses for the Tucows APIs I haven't yet thought up, but the Duke of URL application I wrote back in Dceember is an example of an offbeat app based on a single Tucows API call (the
NAME_SUGGEST call).
By “Tucows APIs”, I refer to the three major APIs for the
provisioning and management of Tucows services, which are listed below:
- XCP: Also referred to as “the OpenSRS API”, this
is our original API, made specifically for the provisioning and
management of domain names. It dates back to when Tucows first got into
the web service wholesale business, when domain names were the only
service we offered. XCP is short for “eXternal Client Protocol”. You can download the latest documentation [PDF format] for XCP here.
- TPP: The API for provisioning and managing services added after domain names, namely:
- Digital Certificates
- Email
- Email Defense
- Managed DNS
- Website Builder
TPP is short for “Tucows Provisioning Protocol”. You can download the basic TPP API docs [PDF format] here, and docs for specific TPP-based services can be found at here.
- Blogware Reseller Provisioning API: Blogware, our
own hosted blogging platform, has its own API (alas, it has no acronym
– nobody calls it “BRPA”). The Blogware Reseller Provisioning API docs
are available both online and in PDF format.

In Project Ash, I'll first provide wrapper functions for XCP, then
TPP, then BRPA — er, I mean the Blogware Reseller Provisioning API.
Why is the Project Named “Ash”?
The graphic accompanying this article should be a hint: it's named after the protagonist in Sam Raimi's Evil Dead series of horror movies.
One tongue-in-cheek way of describing the character Ash is to say that
he's “just one man with a chainsaw, trying to make a difference”. Ash's
goals in swinging that chainsaw and mine in cobbling together this PHP
library could be seen as similar, hence the project's name.
PHP OpenSRS Client: Project Ash's Foundation
I've made mention of the PHP OpenSRS Client project
on SourceForge written by Colin Viebrock several times before. It will
be the foundation on which the XCP and TPP parts of Ash will be built,
as it takes care of two key operations:
- Connecting to and authenticating with Tucows' servers
- Sending and receiving messages to and from Tucows' servers
With these tasks out of the way, the Ash library is left to
concentrate on providing functions that assemble the data structures
that the PHP OpenSRS Client can easily convert into the XML that makes
up XCP and TPP calls. In the next few sections, we'll take a look at
building such a function.
First Steps: Anatomy of an XCP API Call
An XCP call can be viewed as an associative array (or, if you
prefer, “hash” or “dictionary”) of parameters, which the documentation
calls the input parameters. The input parameters
contain details about the call itself, such as the name of the call and
the object on which the call is to be performed. One of these input
parameters is called attributes — this parameter is
an associative array containing what we would consider to be the
arguments of the call; the arguments to the wrapper functions will
mostly be put into this array.

Building the “Lookup Domain” Call
Let's see how this structure applies to one of the simplest XCP calls: Lookup Domain. If you'd like to see how it appears in the documentation, it's on page 194 of the 2.9.6 version of the OpenSRS API Specification
[PDF link] (a.k.a. the XCP documentation). Given a domain name, this
call returns a value that states whether or not it is available.
The table below shows how the call is structured:
| Input parameter name |
Value |
| action |
The action to be performed.
In the case of Lookup Domain, set this value to lookup
or LOOKUP — it's not case-sensitive.
|
| object |
The object on which the action is to be performed.
In the case of Lookup Domain, set this value to domain
or DOMAIN — it's not case-sensitive.
|
| registrant_ip |
Optional. The IP address of the registrant, in “dotted quad” format (for example,
127.0.0.1). |
| attributes |
| Attribute name |
Value |
| domain |
Set this to the name of the domain for which you wish to perform
the lookup.
|
|
On page 195 of the documentation, there's a Perl example of an associative array that defines a Lookup Domain call for the domain name example.com. Here it is:
{
protocol => 'XCP',
action => 'lookup',
object => 'domain',
registrant_ip => '111.121.121.121',
attributes => {
domain => 'example.com'
}
Let's translate this into PHP. It's easy — the Perl code above is simply an associative array literal. In PHP, array literals are a little bit more verbose since they include the keyword array (that's right, array isn't considered a function!). Here's the Perl array declaration translated into its PHP equivalent:
array(
'action' => 'lookup',
'object' => 'domain',
'registrant_ip' => '111.121.121.121',
'attributes' => array(
'domain' => 'example.com'
)
);
(Yes, I've skipped the 'protocol' => 'XCP' key-value pair — the PHP OpenSRS library lets us specify the protocol elsewhere.)
Now that we've built the API call, let's send it!
Sending the “Lookup Domain” Call
This is where the PHP OpenSRS Client comes in. Once you've built the associative array for the API call you want to use, you simply use the client to create an instance of an “OpenSRS” class and use that instance's send_cmd method to send the message to the Tucows servers. The class will handle all the details of authenticating, converting the associative array into XML that the Tucows servers can understand and sending the XML to the Tucows servers. The return value of send_cmd message will contain the servers' response.

Installing the PHP OpenSRS Client
If you haven't installed the PHP OpenSRS Client code yet, you might
want to consult the Introducing OpenSRS-PHP article.
|
Enough preamble! Here's the complete code for a simple PHP script that makes a Lookup Domain API call based on associative array we created earlier:
<?php
require_once 'openSRS.php';
$server = new openSRS('LIVE', 'XCP');
$cmd = array(
'action' => 'lookup',
'object' => 'domain',
'registrant_ip' => '111.121.121.121',
'attributes' => array(
'domain' => 'example.com'
)
);
$result = $server->send_cmd($cmd);
echo("<h1>Lookup Results</h1>");
print_r($result);
?>
Assuming that all is well — your internet connection is working and you've defined your username and private keys in openSRS.php — when you run this script, you should get a page with a big headline that reads “Lookup Result” followed by:
Array ( [is_success] => 1 [response_code] => 211 [response_text] => Domain taken [attributes] => Array ( [status] => taken [upg_to_subdomain] => [reason] => ) )
It's time to look at the structure of the response.
Anatomy of an XCP Response
Like an XCP call, an XCP reponse can also be viewed as an associative array of parameters. The response parameters contain details about the call itself, such as whether the call was successfully performed and the result code for the call. The XCP response also has a parameter called attributes; like the XCP call parameter with the same name, this parameter is
an associative array containing additional result data for the call; it's used when the result code for the call doesn't provide enough information (for example, API calls that return lists of data would place those lists into the attributes parameter).

The table below shows how the response is structured:
| Response parameter name |
Value |
| is_success |
1 if the API command was executed successfully, 0
otherwise |
| response_code |
A numeric code representing the result of the API call.
In the case of Lookup Domain, the possible
values are:
210 - Domain available.
211 - Domain taken.
221 - Domain taken (a waiting registration exists in OpenSRS). Note that this is for asynchronous registries only.
250 - Action submitted successfully for processing to asynchronous registry.
|
| response_text |
Text representing the result of the API call.
It's best to use this value for debugging purposes only. Your program logic
should be based on the value of response_code (see above).
|
| attributes |
| Attribute name |
Value |
| status |
[available if the domain name is
available, taken otherwise.] |
| upg_to_subdomain |
[Not covered in the docs; I'm going to bug someone
about this.] |
| reason |
[Not covered in the docs; I'm going to bug someone
about this.] |
|
Using the XCP Response
In the case of Lookup Domain, looking at the is_success and response_code response parameters should be enough to determine:
- Whether the call was successfully completed
- Whether the given domain name is available
Other calls may return more complex results and may require looking at the values within the attributes parameter.
Building the Ash Library
The Ash library will encapsulate the PHP code to assemble API commands and send them to the Tucows servers into functions, with one function per API call. Instead of having to write all the PHP code, shown above, you should only have to write a single line of code like the only below to run the Lookup Domain command on the live server:
$result = lookupDomain('live', 'example.com');
And that's my goal. Over the next little while, I'm going to write functions to wrap each API call, starting with the XCP calls. Every now and again, I'll post an article here, covering my progress and reporting on little-known features of some of the API calls. Watch this space!
As always, if you have any questions or suggestions or would like to voice an opinion, let me know in the comments!