The FreeAgent API (Beta)
The FreeAgent API provides secure programmatic access to the FreeAgent service, allowing you to build cool and useful tools and services on top.
This initial release of our API, covering the FreeAgent data listed on the right, will soon be enhanced with support for Bank Accounts and their associated Transactions and Entries, and for Payroll, Expenses and Taxes. Keep an eye on The Central for updates.
How to use the API
The FreeAgent API uses a RESTful style using XML over HTTP. Four HTTP methods are used: GET, POST, PUT and DELETE.
Authorisation
All API requests should be made via HTTPS using your own unique FreeAgent URL (e.g. https://nosteptwo.freeagentcentral.com), just like when you access the site through a browser. Authentication is managed using HTTP Basic Authentication. The user name and password you use to authenticate should be the email address and password you use to log into the website.
Every request to the FreeAgent API must be in XML format which means the "Content-Type" header must be set to "application/xml". To tell FreeAgent to send an XML response, the "Accept" header must also be set to "application/xml". Here's an example using Curl:
curl -u userid:password -H 'Accept: application/xml' -H 'Content-Type: application/xml' \ https://company.freeagentcentral.com/clients
Reponses
If an API request fails, the error information is returned with the HTTP status code. If you supply incorrect login details, you'll get a 401 Unauthorized response, such as:
HTTP/1.x 401 Unauthorized Date: Fri, 14 Mar 2008 11:03:30 GMT
If you request a specific resource which cannot be found, you'll receive a 404 Not Found response:
HTTP/1.x 404 Not Found Date: Fri, 14 Mar 2008 11:06:32 GMT
If you POST or PUT a resource with invalid XML, you'll receive a 400 Bad Request response, and the body of the reponse will contain the errors (if applicable):
HTTP/1.x 400 Bad Request Date: Fri, 14 Mar 2008 11:06:32 GMT <?xml version="1.0" encoding="UTF-8"?> <errors> <error>Name has already been taken</error> </errors>
If a request causes a new record to be created (new Client, Invoice, Project etc), the response will use a 201 Created status and the URI to the newly created resource will be present in the Location header:
HTTP/1.x 201 Created Location: /projects/1/tasks/125 Date: Fri, 14 Mar 2008 11:06:32 GMT
Any other successful operation will use a 200 OK status code:
HTTP/1.x 200 OK Date: Fri, 14 Mar 2008 11:10:22 GMT
Resources
The URIs in the FreeAgent API are the same as those you see in the browser. Here are some examples:
- https://your_company.freeagentcentral.com/invoice_timeline
- https://your_company.freeagentcentral.com/clients
- https://your_company.freeagentcentral.com/clients/client_id
- https://your_company.freeagentcentral.com/invoices
- https://your_company.freeagentcentral.com/invoices/invoice_id
- https://your_company.freeagentcentral.com/timeslips
- https://your_company.freeagentcentral.com/timeslips/timeslip_id
Company
There are two resources available at the Company level. The /company/invoice_timeline resource provides information about due and overdue invoices:
<?xml version="1.0" encoding="UTF-8"?>
<invoice-timeline-items type="array">
<invoice_timeline_item>
<reference>Abstract Web Design 001</reference>
<summary>Payment: Abstract Web Design 001: £1,000.00 received</summary>
<description>Jackson Pollock: Abstract Web Design</description>
<dated_on>Tue Mar 18 00:00:00 UTC 2008</dated_on>
<amount>1000.0</amount>
</invoice_timeline_item>
</invoice-timeline-items>
The /company/tax_timeline resource provides information about upcoming tax events:
<?xml version="1.0" encoding="UTF-8"?>
<timeline-items type="array">
<timeline_item>
<description>Corporation Tax, year ending 05 Apr 07*</description>
<nature>Submission Due</nature>
<dated_on>Sat Apr 05 00:00:00 UTC 2008</dated_on>
<amount_due></amount_due>
<is_personal>false</is_personal>
</timeline_item>
<timeline_item>
<description>Corporation Tax, year ending 05 Apr 08*</description>
<nature>Payment Due</nature>
<dated_on>Tue Jan 06 00:00:00 UTC 2009</dated_on>
<amount_due>190.14</amount_due>
<is_personal>false</is_personal>
</timeline_item>
<timeline_item>
<description>Corporation Tax, year ending 05 Apr 08*</description>
<nature>Submission Due</nature>
<dated_on>Sun Apr 05 00:00:00 UTC 2009</dated_on>
<amount_due></amount_due>
<is_personal>false</is_personal>
</timeline_item>
</timeline-items>
Clients
The GET /clients resource contains a list of all clients. The XML representation is formatted like this:
<?xml version="1.0" encoding="UTF-8"?> <client> <id type="integer">28</id> <organisation-name></organisation-name> <first-name>Andy</first-name> <last-name>Warhol</last-name> <address1></address1> <address2></address2> <address3></address3> <town></town> <region></region> <country>United Kingdom</country> <postcode></postcode> <phone-number></phone-number> <email></email> <client-name-on-invoices type="boolean">true</client-name-on-invoices> <sales-tax-registration-number></sales-tax-registration-number> </client>
Single clients can be requested directly using GET /clients/client_id where client_id is the ID of the client.
To create a client you should POST to /clients. You only need to specify the required elements which for clients are <first-name> and <last-name>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <client> <first-name>Mark</first-name> <last-name>Rothko</last-name> </client>
Updating a client doesn't require every element. To update a client's phone number, you should PUT to /clients/client_id with:
<?xml version="1.0" encoding="UTF-8"?> <client> <phone-number>020 1234 4321</phone-number> </client>
To delete a client you should DELETE to /clients/client_id. A client can only be deleted if it has no projects. If the DELETE is unsuccessful, the response will be 409 Conflict.
Projects
The GET /projects resource contains a list of all projects. The XML representation is formatted like this:
<?xml version="1.0" encoding="UTF-8"?> <project> <id type="integer">20</id> <client-id type="integer">26</client-id> <name>Website redesign</name> <billing-basis type="decimal">1</billing-basis> <budget type="integer">0</budget> <budget-units>Hours</budget-units> <invoicing-reference></invoicing-reference> <is-ir35 type="boolean">false</is-ir35> <normal-billing-rate type="decimal">0.0</normal-billing-rate> <payment-terms-in-days type="integer">30</payment-terms-in-days> <starts-on type="datetime" nil="true">2006-09-01T00:00:00Z</starts-on> <ends-on type="datetime" nil="true">2006-12-31T00:00:00Z</ends-on> <status>Active</status> </project>
Single projects can be requested directly using GET /projects/project_id where project_id is the ID of the project.
To create a project you should POST to /projects. You only need to specify the required elements which for projects are <client-id>, <name>, <status>, <payment-terms-in-days>, <billing-basis>, <budget-units> and <status>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <project> <client-id type="integer">26</client-id> <name>Website redesign</name> <billing-basis type="decimal">1</billing-basis> <budget type="integer">0</budget> <budget-units>Hours</budget-units> <payment-terms-in-days type="integer">30</payment-terms-in-days> <status>Active</status> </project>
Three of these fields are restricted in what values can be supplied. <billing-basis> must be one of:
- 1 (per hour)
- 7 (per day of 7 hours)
- 7.5 (per day of 7.5 hours)
- 8 (per day of 8 hours)
<budget-units> must be one of:
- Hours
- Days
- Monetary
<status> must be one of:
- Active
- Completed
Updating a project doesn't require every element. To update a projects's status, you should PUT to /projects/project_id with:
<?xml version="1.0" encoding="UTF-8"?> <project> <status>Completed</status> </project>
To delete a project you should DELETE to /projects/project_id. A project can only be deleted if it has no dependent invoices, tasks, timeslips, bank account entries and expenses. If the DELETE is unsuccessful, the response will be 409 Conflict.
Tasks
The GET /projects/project_id/tasks resource contains a list of all tasks for the specified proejct. The XML representation is formatted like this:
<?xml version="1.0" encoding="UTF-8"?> <task> <id type="integer">38</id> <project-id type="integer">19</project-id> <name>Development</name> </task>
Single tasks can be requested directly using GET /projects/project_id/tasks/task_id.
To create a task you should POST to /projects/project_id. You only need to specify <name>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <task> <name>New task name</name> </task>
Similarly, to update a task's name you should PUT to /projects/project_id/tasks with:
<?xml version="1.0" encoding="UTF-8"?> <task> <name>Updated task name</name> </task>
To delete a task you should DELETE to /projects/project_id/tasks/task_id. A task can only be deleted if no timeslips are dependent upon it. If the DELETE is unsuccessful, the response will be 409 Conflict.
Invoices
The GET /invoices resource contains a list of all invoices as well as their corresponding invoice items. The XML representation is formatted like this:
<?xml version="1.0" encoding="UTF-8"?>
<invoices type="array">
<invoice>
<id type="integer">85</id>
<company-id type="integer">10</company-id>
<project-id type="integer">16</project-id>
<dated-on type="datetime">2008-02-17T00:00:00Z</dated-on>
<reference>Abstract Web Design 001</reference>
<net-value type="decimal">1000.0</net-value>
<sales-tax-value type="decimal">0.0</sales-tax-value>
<status>Sent</status>
<comments></comments>
<discount-percent type="decimal" nil="true"></discount-percent>
<omit-header type="boolean">false</omit-header>
<payment-terms></payment-terms>
<recurring></recurring>
<written-off-date type="datetime" nil="true"></written-off-date>
<invoice-items type="array">
<invoice-item>
<id type="integer">607</id>
<invoice-id type="integer">85</invoice-id>
<project-id type="integer" nil="true"></project-id>
<item-type>Services</item-type>
<description>Setting up hosting</description>
<price type="decimal">160.0</price>
<quantity type="decimal">1.0</quantity>
<sales-tax-rate type="decimal">17.5</sales-tax-rate>
<sales-tax-value type="float">175.0</sales-tax-value>
</invoice-item>
<invoice-item>
<id type="integer">611</id>
<invoice-id type="integer">85</invoice-id>
<project-id type="integer" nil="true"></project-id>
<item-type>Hours</item-type>
<description>Coding the templates</description>
<price type="decimal">40</price>
<quantity type="decimal">30</quantity>
<sales-tax-rate type="decimal">17.5</sales-tax-rate>
<sales-tax-value type="float">0.0</sales-tax-value>
</invoice-item>
</invoice-items>
</invoice>
</invoices>
Single invoices can be requested directly using GET /invoices/invoice_id where invoice_id is the ID of the invoice.
To create an invoice you should POST to /invoices. You only need to specify the required elements which for invoices are <company-id>, <project-id>, <dated-on>, <reference> and <status>, e.g.:
<invoice> <company-id>42</company-id> <project-id>21</project-id> <dated-on>2008-02-17T00:00:00Z</dated-on> <reference>INVOICE 2001</reference> <status>Draft</status> <comments>A comment</comments> </invoice>
Updating an invoice doesn't require every element. To update a invoice date, you should PUT to /invoices/invoice_id with:
<?xml version="1.0" encoding="UTF-8"?> <invoice> <dated-on>2008-02-29T00:00:00Z</dated-on> </invoice>
To delete an invoice you should DELETE to /invoices/invoice_id. An invoice can only be deleted if it is in Draft state. If the DELETE is unsuccessful, the response will be 409 Conflict.
Changing Status
Specific resources exist for changing an invoice status. To change between Draft, Sent and Cancelled state, you must PUT to:
- /invoices/invoice_id/mark_as_draft
- /invoices/invoice_id/mark_as_sent
- /invoices/invoice_id/mark_as_cancelled
If the state transition cannot be made (e.g. if an invoice has no invoice items it cannot be marked as Sent), a 403 Forbidden response will be returned by these resources.
Note: marking an invoice as paid is handled automatically in FreeAgent through Bank Account Entries and Bank Transactions. These are not supported in the current API.
Invoice Items
The GET /invoices/invoice_id/invoice_items resource contains a list of all invoice items for the invoice specified by invoice_id. The XML representation is formatted like this:
<?xml version="1.0" encoding="UTF-8"?> <invoice-item> <id type="integer">618</id> <invoice-id type="integer">95</invoice-id> <project-id type="integer" nil="true"></project-id> <item-type>Hours</item-type> <price type="decimal">1.0</price> <quantity type="decimal">1.0</quantity> <description>test</description> <sales-tax-rate type="decimal">17.5</sales-tax-rate> </invoice-item>
Single invoice items can be requested directly using GET /invoices/invoice_id/invoice_items/invoice_item_id.
To create an invoice item you should POST to /invoices/invoice_id/invoice_items. You only need to specify the required elements which for invoice items are <item-type>, <description>, <quantity>, <price>, <sales-tax-rate> and <last-name>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <invoice-item> <item-type>Hours</item-type> <price>50</price> <quantity>12</quantity> <sales-tax-rate>17.5</sales-tax-rate> <description>Creating wireframe templates</description> </invoice-item>
The value of <item-type> must be one of:
- Hours
- Days
- Months
- Years
- Products
- Services
- Expenses
- Discount
- Credit
- Comment
Updating an invoice item doesn't require every element. To update an invoice item's quantity, you should PUT to /invoices/invoice_id/invoice_items/invoice_item_id with:
<?xml version="1.0" encoding="UTF-8"?> <invoice-item> <quantity>13</quantity> </invoice-item>
To delete an invoice item you should DELETE to /invoices/invoice_id/invoice_items/invoice_item_id.
Timeslips
The GET /timeslips resource contains a list of all the timeslips for the company. The GET /projects/project_id/timeslips resource contains a list of all the timeslips for that project. The XML representation for both of these is formatted like this:
<?xml version="1.0" encoding="UTF-8"?> <timeslip> <id type="integer">169</id> <dated-on type="datetime">2008-03-03T00:00:00Z</dated-on> <task-id type="integer">38</task-id> <user-id type="integer">11</user-id> <hours type="decimal">1.0</hours> <comment></comment> </timeslip>
Single timeslips can be requested directly using GET /timeslips/timeslip_id where timeslip_id is the ID of the timeslip.
To create a timeslip you should POST to /timeslips. You only need to specify the required elements which for clients are <project-id>, <user-id>, <hours>, <dated-on> and one of <task-id> or <new-task>. To create a timeslip for an existing task, use <task-id>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <timeslip> <dated-on>2008-03-03T00:00:00Z</dated-on> <task-id>38</task-id> <user-id>11</user-id> <hours>1</hours> </timeslip>To create a timeslip with a new task, use <new-task>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <timeslip> <dated-on>2008-03-03T00:00:00Z</dated-on> <new-task>The new task name</new-task> <user-id>11</user-id> <hours>1</hours> </timeslip>
Updating a timeslip doesn't require every element. To update a timeslip's hours, you should PUT to /timeslips/timeslip_id with:
<?xml version="1.0" encoding="UTF-8"?> <timeslip> <hours>10</hours> </timeslip>
To delete a timeslip you should DELETE to /timeslips/timeslip_id. An timeslip can only be deleted if has not been rebilled on an invoice. If the DELETE is unsuccessful, the response will be 409 Conflict.
Users
The GET /company/users resource contains a list of all users. The XML representation is formatted like this:
<?xml version="1.0" encoding="UTF-8"?> <user> <company-id type="integer">10</company-id> <email>olly@lylo.co.uk</email> <first-name>Olly</first-name> <id type="integer">11</id> <last-logged-in-at type="datetime">2008-03-03T21:16:09Z</last-logged-in-at> <last-name>Headey</last-name> <opening-director-loan-account-balance type="decimal">0.0</opening-director-loan-account-balance> <opening-expense-balance type="decimal">0.0</opening-expense-balance> <opening-salary-balance type="decimal">0.0</opening-salary-balance> <opening-share-or-capital-balance type="decimal">0.0</opening-share-or-capital-balance> <role>Director</role> </user>
Single users can be requested directly using GET /company/users/user_id where user_id is the ID of the user.
To create a user you should POST to /company/users. You only need to specify the required elements which for users are <first-name>, <last-name>, <email>, <role>, <password> and <password-confirmation>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <user> <first-name>John</first-name> <last-name>Smith</last-name> <email>john.smith@freeagentcentral.com</email> <role>Director</role> <password>password</password> <password-confirmation>password</password-confirmation> </user>
The value of <role> must be one of:
- Owner
- Director
- Partner
- Company Secretary
- Employee
- Shareholder
- Accountant
Updating a user doesn't require every element. To update a user's first name, you should PUT to /company/users/user_id with:
<?xml version="1.0" encoding="UTF-8"?> <user> <first-name>Dave</first-name> </user>
To delete a user you should DELETE to /company/users/user_id. A user can only be deleted if there are no expenses, payslips, timeslips, tax returns and bank account entries dependent upon it. A company must have at least one user, therefore the final user can never be deleted. If the DELETE is unsuccessful, the response will be 409 Conflict.
Expenses
The GET /users/user_id/expenses resource contains a list of all the expenses for the user specified by user_id. The XML representation is formatted like this:
<?xml version="1.0" encoding="UTF-8"?> <expense> <id type="integer">78</id> <user-id type="integer">11</user-id> <dated-on type="datetime">2008-03-29T00:00:00Z</dated-on> <description>Hard drive</description> <engine-size-index type="integer">1</engine-size-index> <engine-type-index type="integer">0</engine-type-index> <expense-type>Computer Hardware</expense-type> <gross-value type="decimal">-200.0</gross-value> <have-vat-receipt type="boolean">false</have-vat-receipt> <initial-rate-mileage type="integer">0</initial-rate-mileage> <mileage type="integer" nil="true"></mileage> <rebill-mileage-rate type="decimal">0.4</rebill-mileage-rate> <rebill-to-project-id type="integer" nil="true"></rebill-to-project-id> <rebilled-on-invoice-item-id type="integer" nil="true"></rebilled-on-invoice-item-id> <receipt-reference></receipt-reference> <reclaim-mileage-rate type="decimal">0.4</reclaim-mileage-rate> <recurring nil="true"></recurring> <recurring-end-date type="datetime" nil="true"></recurring-end-date> <sales-tax-rate type="decimal">17.5</sales-tax-rate> <vehicle-type nil="true"></vehicle-type> </expense>
Single expenses can be requested directly using GET /users/user_id/expenses/expense_id where expense_id is the ID of the expense.
Updating an expense doesn't require every element. To update an expenses description, you should PUT to /users/user_id/expenses/expense_id with:
<?xml version="1.0" encoding="UTF-8"?> <expense> <description>MacBook Pro</description> </expense>
To delete an expense you should DELETE to /users/user_id/expenses/expense_id. If the DELETE is unsuccessful, the response will be 409 Conflict.
To create an expense you should POST to /users.user_id/expenses. You only need to specify the required elements which for standard (non-mileage) expenses are <description>, <dated-on>, <expense-type> and <gross-value>, e.g.:
<?xml version="1.0" encoding="UTF-8"?> <expense> <dated-on>2008-03-29T00:00:00Z</dated-on> <description>MacBook Pro</description> <expense-type>Computer Hardware</expense-type> <gross-value>-300</gross-value> </expense>
Mileage
Mileage expenses (i.e. an expense with an <expense-type> of Mileage) are treated slightly differently to standard expenses. The behaviour is also different depending on the company type.
No <gross-value> field is required. Instead, a new numerical value <mileage> is required.
If <rebill-to-project-id> is specified, and references a valid project, <rebill_mileage_rate> is required and must be numeric.
Mileage for UK Companies
<vehicle-type> is required and must be one of:
- Car
- Motorcycle
- Bicycle
<have-vat-receipt> is required and must be either true or false.
<engine-type-index> is required and must be one of the following integer values:
- 0 ("Petrol")
- 1 ("Diesel")
- 2 ("LPG")
<engine-size-index> is required and must be one of the following integer values:
- 0 ("Up to 1400cc")
- 1 ("1400-2000cc")
- 2 ("Over 2000cc")
Here is an example of a mileage expense for UK companies:
<?xml version="1.0" encoding="UTF-8"?> <expense> <dated-on>2008-03-29T00:00:00Z</dated-on> <description>Visit to FreeAgent Central</description> <expense-type>Mileage</expense-type> <mileage>100</mileage> <vehicle-type>Car</vehicle-type> <engine_type_index>0</engine_type_index> <engine-size-index>0</engine-size-index> <have-vat-receipt>true</have-vat-receipt> </expense>
Mileage for Universal Companies
The numeric value <reclaim-mileage-rate> is required.
Sections
Questions?
If you have any questions or feedback about the API, please post a message to our dedicated Google Group.