Log In Contact API Blog FAQ

Xpenser Developer API


Xpenser offers two authentication methods: HTTP Basic Auth and OAuth.

HTTP Basic Authentication

One way to access the Xpenser APIs is via the use of HTTP Basic Authentication. For example, here's a simple way to record a new expense:

curl -i -u "user@test.com:password"

where "user@test.com" is the username and "password" is the password.

HTTP Basic Authentication is one of the oldest and simplest ways to authenticate for web access and is well supported by just about every programming language on the web.


OAuth is a newer method for gaining access to protected resources. It offers several advantages over HTTP Basic Authentication - in particular, it does not require the user's username and password be known when invoking the APIs. We encourage you to make use of OAuth instead of HTTP Basic Auth where possible.

In order to use OAuth to gain access to Xpenser APIs you will need a consumer and secret key. Please contact us at api@xpenser.com to get setup.

The Xpenser OAuth endpoints are:

  • Request Token: http://xpenser.com/oauth/request_token
  • Authorize: http://xpenser.com/oauth/request_tokenauthorize
  • Access Token: http://xpenser.com/oauth/access_token

Ruby Sample Code

The following Ruby code accesses the Xpenser APIs using OAuth:

require 'oauth'
@consumer=OAuth::Consumer.new "consumer_key", "secret", {:site=>"http://xpenser.com"}
auth_url = @request_token.authorize_url({:oauth_callback =>

# Now go to auth_url using a browser and authorize the request
# you should get redirected to http://your_address_here.com/callback/ on success


You may find the OAuth Explorer tool helpful in testing OAuth access.

Entering Expenses Into Xpenser

The simplest way to enter expenses into Xpenser is the "simple" api.


The report parameter is optional; if omitted the default report will be used.

For example:


Will create the expense "lunch 45 with jack" and return the response using the json format.

If you omit the format parameter the response will be returned as html. This is particularly useful if you want to integrate simple expense entry into a web application - just create a form whose action points to http://xpenser.com/api/simple/ and include the free-form expense as the q parameter.

Please note that the user will need to be logged in to Xpenser either via normal browser based login or using http authentication in order to access this API.

When using json as the format, the status response code indicates the status of the request, and is based on HTTP response codes. In partical, 200 indicates success.

The expense format (the format of the parameter q) is the normal expense submission format:

type amount notes #tag1 #tag2

For example:

Lunch 45 with Jack
Tax 34 office to airport #cash #clientx
Time 37 mins contract review
Time start clientx
Time stop

The Expense API

The Expense API is REST/JSON based. Input data should be formatted as normal POST variables.

View an expense:

GET /api/expense/676
{"status": 200, "data": {"date": "2008-08-18 12:35:00", "report": 36,
  "amount": "15.32", "type": "dinner", "notes": "some note here"}}

Create an expense:

POST /api/expense/
(report id is optional)

Update an expense:

POST /api/expense/676
{"status": 200, "data": {"date": "2008-08-18 12:35:00", "report": 36,
  "amount": "14", "type": "dinner", "notes": "targets"}, "id": 676}

Downloading Expenses

GET /api/expenses/

Returns all expenses in current (active) report in the default CSV format.


curl -i -u testuser@test.com:testpass 

URL Parameters:

  • format: csv, json, qif

    GET /api/expenses/?format=json -- get all expenses in current (active) report in JSON format
    GET /api/expenses/?format=json&report=* -- get all expenses in all reports in JSON format

  • report: ID of report.
    If not specified, current report is used.
    If specified as "*" expenses across all reports are used.

    GET api/expenses/?report=* -- get all expenses from all reports
    GET api/expenses/?report=54 -- get all expenses in report 54

  • date, date_op :

    • date: Date of expense, specified as "%d %b %Y" (for example, 01+Aug+2009).
    • date_op: the operation to perform. Use "lt" for less than, "gt" for greater than.

    GET /api/expenses/?report=54&date_op=gt&date=01+Aug+2009 NOTE: the date format will likely be changed to standard ISO format in a future release.

  • type: Type of expense

    GET /api/expenses/?report=54&type=lunch -- get all expenses in report 54 whose type is lunch

  • notes: Expense notes.

    GET /api/expenses/?report=54&notes=cash -- get all expenses in report 54 whose note field is cash

  • amount, amount_op: Amount of expense

    • amount_op: the operation to perform. Use "lt" for less than, "gt" for greater than.

    GET /api/expenses/?report=54&amount_op=gt&amount=3 -- get all expenses in report 54 whose amount is greater than 3

  • created, created_op: Date expense was first created, specified as "%Y-%m-%d %H:%M:%S" (for example, 2009-08-26+00:00:00)

    • created_op: the operation to perform. Use "lt" for less than, "gt" for greater than.

    GET /api/expenses/?report=*&created=2009-08-26+00:00:00&created_op=gt -- get all expenses across all reports created after 2009-08-26+00:00:00

  • modified, modified_op: Date expense was last modified, specified as "%Y-%m-%d %H:%M:%S" - eg. 2009-08-26+00:00:00

    • modified_op: the operation to perform. Use "lt" for less than, "gt" for greater than.

    GET /api/expenses/?report=*&modified=2009-08-26+00:00:00&modified_op=gt -- get all expenses across all reports modified after 2009-08-26+00:00:00

Response Format

A list of expenses encoded via JSON will be returned:

  • pk is the expense id.
  • type is the expense type (eg. "lunch")
  • report is the expense report or folder the expense is filed in.
  • amount is the amount of the expense in the user's base currency. For example, if the expense was "mileage 100", and the mileage was converted to 100*$0.55 = $55, then amount would be 55.
  • rawamount is the raw amount originally entered in the expense. For example, if the expense was "mileage 100", and the mileage was converted to 100*$0.55 = $55, then rawamount would be 100.
  • date is the time and date of the expense.
  • notes contains any notes associated with the expense.
  • created is the date at which the expense was first created.
  • modified is the date at which the expense was last modified.
  • tags are a list of tags for the expense.

Sample response:

{"pk": 622012, "model": "xpense.expense", "fields": {"category":
null, "status": 1, "rawamount": "1.00", "sourceid":
"SP-25914-2009-08-27T14:27:05.717294", "notes": "one", "created":
"2009-08-27 14:27:05", "modified": "2009-08-27 14:27:05", "report":
50705, "amount": "1.00", "user": 25914, "date": "2009-08-27 14:28:00",
"type": "Test Expense", "tags": [44557]}}, 
{"pk": 622013, "model":
"xpense.expense", "fields": {"category": null, "status": 1,
"rawamount": "2.00", "sourceid":
"SP-25914-2009-08-27T14:27:15.059368", "notes": "two", "created":
"2009-08-27 14:27:15", "modified": "2009-08-27 14:27:15", "report":
50705, "amount": "2.00", "user": 25914, "date": "2009-08-27 14:28:00",
"type": "Another expense", "tags": [44558]}}, 
{"pk": 622011, "model":
"xpense.expense", "fields": {"category": null, "status": 1,
"rawamount": "0.00", "sourceid": "", "notes": "To modify anything
(type, amount, etc) just click on it.", "created": "2009-08-27
14:25:52", "modified": "2009-08-27 14:25:52", "report": 50705,
"amount": "0.00", "user": 25914, "date": "2009-08-27 14:25:52",
"type": "Sample Expense", "tags": []}}

Delta API - Downloading Expenses Modified Since

Sometimes it is useful to download only expenses modified or created since a particular date - for example, when synchronizing expenses across applications.

The modified field can be used to achieve this:

GET /api/expenses/?report=*&modified=2009-08-26+00:00:00&modified_op=gt

Returns the list of expenses modified after 2009-08-26 00:00:00 .

Tools and Testing

If you're using FireFox the RestTest tool can be quite useful for testing and debugging services.

curl, is a command line tool for accessing HTTP based services and an excellent way to test the Xpenser APIs.