Developers area
Did you know that 88 Miles has a completely open REST webservice API? Well it does. So if you are interesting in extending 88 Miles or creating some sort of time tracking mash-up, you are in the right place.
What's a webservice?
A webservice is kind of like a web page, but it is designed to be used by other computers rather than people. This means you can access the features of 88 Miles from your own CMS, website or desktop application. This makes 88 Miles even MORE flexible
What types of web services do you offer?
88 Miles currently supports REST.
I‘m not a developer? What can I do?
MadPilot Productions is available to help you integrate your current systems into 88 Miles. Please contact them if you would like to discuss your requirements.
Webservice authentication
Looking for the page to register your 3rd Party application for OAuth? Then step this way!
The 88 Miles REST interface supports both OAuth and basic authentication. OAuth, whilst being a little bit harder to configure, it doesn't require you to ask for a users password, and is the preferred method of connecting to 88 Miles. There are already a number of libraries for supporting OAuth in many different languages, check out if your favourite one is already supported. If you are a developer and you wish to register your application as a 88 Miles OAuth consumer, you can do so here.
Currently, the 88 Miles OAuth implementation only supports the get http method and the query scheme.
If you are unable to use OAuth, you can still fall back to basic authentication, where you need to send your username and password with each query. If you are worried about revealing you password on each query, feel free to use the secure version of the webservices at https://www.88miles.net/
Please note, for simplicity, the examples below use basic authentication, as curl doesn't support OAuth (easily).
Documentation
Using REST makes accessing the webservices easy. As long as your language of choice can handle making remote HTTP calls and can generate and parse XML, you will fine.
The 88 Miles REST interface is accessed by appending .xml as demostrated below
REST uses verbs to perform actions on a specific URL. Below is a table of how this works for the companies resource.
| Resource | Verb | Action | Description |
|---|---|---|---|
| /companies.xml | GET | list | List all companies |
| /companies/1.xml | GET | show | Get the company with id of 1 |
| /companies | POST | create | Create a new company |
| /companies/1.xml | PUT | update | Update the company with the id of 1 |
| /companies/1.xml | DELETE | destroy | Delete the company with the id of 1 |
88 Miles uses nested resources which makes accessing projects and shifts easy! The following example shows you how to perform actions on projects belonging to a certain Company.
| Resource | Verb | Action | Description |
|---|---|---|---|
| /companies/1/projects.xml | GET | list | List all projects belonging to company with an id of 1 |
| /projects/10.xml | GET | show | Get the project with id of 10 |
| /companies/1.xml | POST | create | Create a new project belonging to the company with id of 1 |
| /projects/10.xml | PUT | update | Update the project with the id of 10 |
| /projects/10.xml | DELETE | destroy | Delete the project with the id of 10 |
The complete API
Staff | Companies | Projects | Shifts | Timezones | ErrorsStaff
Get a list of all your staff (including you)
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/staff.xml
XML to send: None
Returns:
<users>
<user>
<id>1001</id>
<username>wayne.wilks</username>
<first_name>Wayne</first_name>
<last_name>Wilks</last_name>
<email_address>wayne@symag.com</email_address>
<active>true</active>
</user>
<user>
<id>1004</id>
<username>marilynn.gaskins</username>
<first_name>Marilynn</first_name>
<last_name>Gaskins</last_name>
<email_address>marilynn@symag.com</email_address>
<active>true</active>
</user>
</users>
Get a staff member with a supplied id
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/staff/1004.xml
XML to send: None
Returns:
<user>
<id>1004</id>
<username>marilynn.gaskins</username>
<first_name>Marilynn</first_name>
<last_name>Gaskins</last_name>
<email_address>marilynn@symag.com</email_address>
<active>true</active>
</user>
Create a new staff member
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/staff.xml -X post -d [See below]
XML to send:
<user>
<username>esmeralda.hahn</username>
<first_name>Esmeralda</first_name>
<last_name>Hahn</last_name>
<email_address>esmeralda@symag.com</email_address>
<time_zone>Australia/Perth</time_zone>
<password>Mittens</password>
</user>
Returns: 201 - Created
Update a staff member
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/staff/1004.xml -X put -d [See below]
XML to send:
<user>
<id>1006</id>
<username>esmeralda.wible</username>
<first_name>Esmeralda</first_name>
<last_name>Wible</last_name>
<email_address>esmeralda@symag.com</email_address>
</user>
Returns: 200 - Success
Delete a staff member
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/staff/1004.xml -X delete
XML to send: None
Returns: 200 - Success
Companies
Get a list of all your companies
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/companies.xml
XML to send: None
Returns:
<companies>
<company>
<id>560</id>
<name>Atection Consulting</name>
<visibility>public</visibility>
</company>
<company>
<id>569</id>
<name>Trenthan Systems</name>
<visibility>custom</visibility>
<user_ids type="array">
<user type="integer">243</user>
<user type="integer">258</user>
</user_ids>
</company>
<company>
<id>578</name>
<name>Proup Devices</name>
<visibility>private</visibility>
<website>http://www.proup-devices.com.au/</website>
<main_phone>+61.8.9332.1349</main_phone>
<main_address>45/2 James St</main_address>
<main_city>Northbridge</main_city>
<main_state>Western Australia</main_state>
<main_postcode>6001</main_postcode>
<main_country>Australia</main_country>
<contact_salutation>Mr</contact_salutation>
<contact_first_name>Mike</contact_first_name>
<contact_last_name>Wentworth</contact_last_name>
<contact_email_address>m.wentworth@proup-devices.com</contact_email_address>
<notes></notes>
</company>
</companies>
Get a company with a supplied id
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/company/578.xml
XML to send: None
Returns:
<company>
<id>578</id>
<name>Proup Devices</name>
<website>http://www.proup-devices.com.au/</website>
<main_phone>+61.8.9332.1349</main_phone>
<main_address>45/2 James St</main_address>
<main_city>Northbridge</main_city>
<main_state>Western Australia</main_state>
<main_postcode>6001</main_postcode>
<main_country>Australia</main_country>
<contact_salutation>Mr</contact_salutation>
<contact_first_name>Mike</contact_first_name>
<contact_last_name>Wentworth</contact_last_name>
<contact_email_address>m.wentworth@proup-devices.com</contact_email_address>
<notes></notes>
<visibility>private</visibility>
</company>
Create a new company
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/companies.xml -X post -d [See below]
XML to send:
<company>
<name>Gabtune</name>
<visibility>public</visibility>
</company>
Create a new company for selected users
You will get an Company::UserNotAllowed error if one of the users isn't in your staff list.
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/companies.xml -X post -d [See below]
XML to send:
<company>
<name>Gabtune</name>
<visibility>custom</visibility>
<user_ids type="array">
<user type="integer">243</user>
<user type="integer">258</user>
</user_ids>
</company>
Returns: 201 - Created
Update a company
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/company/590.xml -X put -d [See below]
XML to send:
<company>
<name>Gabtune</name>
<visibility>private</visibility>
<website>http://www.gabtune.com/</website>
<main_phone>+61.8.9467.1254</main_phone>
<fax_phone>+61.8.9467.1255</fax_phone>
<main_address>416 Beaufort St</main_address>
<main_city>Inglewood</main_city>
<main_state>Western Australia</main_state>
<main_postcode>6051</main_postcode>
<main_country>Australia</main_country>
<contact_salutation>Ms</contact_salutation>
<contact_first_name>Mary</contact_first_name>
<contact_last_name>Trentson</contact_last_name>
<contact_email_address>mary@gabtune.com</contact_email_address>
<contact_home_phone>+61.8.9307.6243</contact_home_phone>
<contact_mobile_phone>+61.409.153.534</contact_mobile_phone>
<notes>Is a podcast post-production house</notes>
</company>
Returns: 200 - Success
Delete a company
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/company/590.xml -X delete
XML to send: None
Returns: 200 - Success
Projects
Get a list of all your projects
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/projects.xml
XML to send: None
Returns:
<projects>
<project>
<id>2856</id>
<name>Website</name>
<visibility>public</visibility>
<active>true</active>
<time_limit_string>4 hours</time_limit_string>
<default_tags>design development</default_tags>
<notes></notes>
<company_id>578</company_id>
<taglist></taglist>
</project>
<project>
<id>2856</id>
<name>Maintenance plan</name>
<visibility>custom</visibility>
<user_ids type="array">
<user type="integer">345</user>
<user type="integer">546</user>
</user_ids>
<active>true</active>
<time_limit_string>20 hours</time_limit_string>
<default_tags></default_tags>
<notes></notes>
<company_id>538</company_id>
<taglist></taglist>
</project>
<project>
<id>2887</id>
<name>SEO</name>
<visibility>private</visibility>
<active>true</active>
<time_limit_string>>30 minutes</time_limit_string>
<default_tags></default_tags>
<notes>Part two of four part contract</notes>
<company_id>560</company_id>
<taglist>work, contract</taglist>
</project>
</projects>
Get a list of all projects belonging to a specific company
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/company/578/projects.xml
XML to send: None
Returns:
<projects>
<project>
<id>2856</id>
<name>Website</name>
<visibility>public</visibility>
<active>true</active>
<time_limit_string>4 hours</time_limit_string>
<default_tags></default_tags>
<notes></notes>
<taglist>new_tag, old_tag</taglist>
</project>
</projects>
Get a project with a supplied id
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/project/2887.xml
XML to send: None
Returns:
<project>
<id>2887</id>
<name>SEO</name>
<visibility>private</visibility>
<active>true</active>
<time_limit_string>30 minutes</time_limit_string>
<default_tags></default_tags>
<notes></notes>
<company_id>560</company_id>
<taglist></taglist>
</project>
Create a new project
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/company/560/projects.xml -X post -d [See below]
XML to send:
<project>
<name>Email newsletter</name>
<visibility>public</visibility>
<time_limit_string>30 minutes</time_limit_string>
<default_tags></default_tags>
<notes>Check with Michael about body copy</notes>
<taglist></taglist>
</project>
Create a new project for a selected users
You will get an Project::UserNotAllowed error if one of the users isn't in your staff list.
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/company/560/projects.xml -X post -d [See below]
XML to send:
<project>
<name>Email newsletter</name>
<visibility>custom</visibility>
<user_ids type="array">
<user type="integer">243</user>
<user type="integer">258</user>
</user_ids>
<time_limit_string>30 minutes</time_limit_string>
<default_tags></default_tags>
<notes>Check with Michael about body copy</notes>
<taglist></taglist>
</project>
Returns: 201 - Created
Update a project
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/project/3054.xml -X put -d [See below]
XML to send:
<project>
<name>Email newsletter</name>
<visibility>private</visibility>
<time_limit_string>30 minutes</time_limit_string>
<default_tags>email design</default_tags>
<notes></notes>
<taglist></taglist>
</project>
Returns: 200 - Success
Delete a project
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/project/3054.xml -X delete
XML to send: None
Returns: 200 - Success
Punch in to a project
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' 'https://www.88miles.net/project/3054/punch_in.xml' -X post
XML to send: None
Returns: 200 - Success
Punch out of a project
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' 'https://www.88miles.net/project/3054/punch_out.xml' -X post
XML to send: None
Returns: 200 - Success
Shifts
Get a list of all your shifts
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/shifts.xml
XML to send: None
Returns:
<shifts>
<shift>
<id>16253</id>
<user_id>543</user>
<staff_member>Esmeralda Wible</staff_member>
<start>Wed, 13 Dec 2006 23:32:25 GMT</start>
<stop> 14 Dec 2006 01:06:40 GMT</stop>
<time_zone>Australia/Perth</time_zone>
<notes>Initial Design Meeting</notes>
<project_id>2854</project_id>
<taglist></taglist>
</shift>
<shift>
<id>16253</id>
<user_id>543</user>
<staff_member>Esmeralda Wible</staff_member>
<start>Thu, 14 Dec 2006 01:12:39 GMT</start>
<stop>Thu, 14 Dec 2006 01:20:12 GMT</stop>
<time_zone>Australia/Perth</time_zone>
<notes>Setting up Domain</notes>
<project_id>2854</project_id>
<taglist></taglist>
</shift>
</shifts>
Get a list of all shifts belonging to a specific project
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/project/2854/shifts.xml
XML to send: None
Returns:
<shifts>
<shift>
<id>16253</id>
<user_id>543</user>
<staff_member>Esmeralda Wible</staff_member>
<start>Wed, 13 Dec 2006 23:32:25 GMT</start>
<stop> 14 Dec 2006 01:06:40 GMT</stop>
<time_zone>Australia/Perth</time_zone>
<notes>Initial Design Meeting</notes>
<taglist></taglist>
</shift>
<shift>
<id>16253</id>
<user_id>543</user>
<staff_member>Esmeralda Wible</staff_member>
<start>Thu, 14 Dec 2006 01:12:39 GMT</start>
<stop>Thu, 14 Dec 2006 01:20:12 GMT</stop>
<time_zone>Australia/Perth</time_zone>
<notes>Setting up Domain</notes>
<taglist></taglist>
</shift>
</shifts>
Get a project with a supplied id
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/shift/16253.xml
XML to send: None
Returns:
<shift>
<id>16253</id>
<user_id>543</user>
<staff_member>Esmeralda Wible</staff_member>
<start>Thu, 14 Dec 2006 01:12:39 GMT</start>
<stop>Thu, 14 Dec 2006 01:20:12 GMT</stop>
<time_zone>Australia/Perth</time_zone>
<notes>Setting up Domain</notes>
<project_id>2854</project_id>
<taglist></taglist>
</shift>
Create a new shift
Note: For consistency, you can send the staff_member parameter in your data, but it will be ignored
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/project/2887/shifts.xml -X post -d [See below]
XML to send:
<shift>
<start>Thu, 07 Mar 2007 13:07:23</start>
<stop>Thu, 07 Mar 2007 13:53:12</stop>
<time_zone>Australia/Perth</time_zone>
<notes>Worked on new website design</notes>
</shift>
Returns: 201 - Created
Update a shift
Note: For consistency, you can send the staff_member parameter in your data, but it will be ignored
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/shift/89092.xml -X put -d [See below]
XML to send:
<shift>
<start>Thu, 08 Mar 2007 13:07:23</start>
<stop>Thu, 08 Mar 2007 13:53:12</stop>
<time_zone>Australia/Perth</time_zone>
<notes>Worked on new website design</notes>
</shift>
Returns: 200 - Success
Delete a shift
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/shift/89092.xml -X delete
XML to send: None
Returns: 200 - Success
Timezones
Get a list of all the timezones
curl -u 'username:password' -H 'Accept: application/xml' -H 'Content-type: application/xml' https://www.88miles.net/time_zones.xml -X get
XML to send: None
Returns: 200 - Success
<time_zones>
<time_zone>
<zone>Vatican</zone>
<longitude>12.45</longitude>
<latitude>41.9</latitude>
<offset>1</offset>
<dst>false</dst>
</time_zone>
<!-- Rest of them cut because there are lots of time_zones -->
</time_zones>
Dealing with Errors
When dealing with XML, any potential errors are handled by a psuedo-exceptions. The structure of the XML is below:
<errors>
<error type="Project::ReadDenied">Sorry, you aren't allow to view that project</error>
</errors>
Here is a list of some of the Exception types:
Staff
| Name | Description |
|---|---|
| User::Error | General errors |
| User::MaxTime | You aren't able to enter any more time — you have already used entered the maximum time allowed on your account |
| User::MaxStaff | You aren't able to enter any more staff members — you have used created the maximum amount of staff allowed on you account |
| User::StaffNotAllowed | The account you have doesn't allow staff members |
| User::ReadDenied | You aren't allowed to read the details of that staff member |
| User::UpdateDenied | You aren't allowed to update the details of that staff member |
| User::DeleteDenied | You aren't allowed to delete that staff member |
Companies
| Name | Description |
|---|---|
| Company::Error | General errors |
| Company::ParamMissing | The haven't supplied enough parameters in your query |
| Company::ReadDenied | You aren't allowed to read the details of that company |
| Company::UpdateDenied | You aren't allowed to update the details of that company |
| Company::DeleteDenied | You aren't allowed to delete that company |
| Company::UserNotAllowed | You have tried to add a user to your company that isn't part of your user list |
Projects
| Name | Description |
|---|---|
| Project::Error | General errors |
| Project::ParamMissing | The haven't supplied enough parameters in your query |
| Project::ReadDenied | You aren't allowed to read the details of that project |
| Project::UpdateDenied | You aren't allowed to update the details of that project |
| Project::DeleteDenied | You aren't allowed to delete that project |
| Project::ProjectInactive | The project you are trying to punch in to is inactive |
| Project::PunchedIn | The project you are trying to punch in to has already been punched in to |
| Project::PunchedOut | The project you are trying to punch out of has not been punched in to |
| Project::UserNotAllowed | You have tried to add a user to your project that isn't part of your user list |
Shifts
| Name | Description |
|---|---|
| Shift::Error | General errors |
| Shift::ParamMissing | The haven't supplied enough parameters in your query |
| Shift::ReadDenied | You aren't allowed to read the details of that project |
| Shift::UpdateDenied | You aren't allowed to update the details of that project |
| Shift::DeleteDenied | You aren't allowed to delete that project |
