1. Skip to navigation
  2. Skip to content
  3. Skip to sidebar

API reference

The Blinksale Application Programming Interface is simply another way to access your Blinksale data—one that makes it easy for third-party and custom tools to programatically access and interact with the service. The API follows the REST style, and this guide should provide everything you need to implement software that works with Blinksale.

The Terms of Service covers the acceptable use of the API (along with the rest of the site). Beyond the legalities, please design your programs to use Blinksale considerately—cache as much as possible, limit the frequency of your requests, and include a User-Agent header in your requests. If you find a problem with the API, please give us a chance to correct it before going public. If you have any questions or issues, feel free to contact support@blinksale.com. And let us know how you’re using it—we’d love to hear about it, and help you spread the word about your project.

Client Libraries

Although the Blinksale API is simple to use, a client library can make it even easier by wrapping the API in your preferred language. Currently, there is only a client library for the Ruby language. If you develop one for another language, let us know and we’ll link to it here.

Resources & URIs

If you’ve used Blinksale, the URIs in the Blinksale API will look familiar. That’s because both views of the application use the same URIs. In REST parlance, URIs are considered identifiers for resources, and each resource can have several representations—such as the standard HTML view, an XML version, an Atom version, etc. Generally, each type of data has one collection resource (e.g., http://example.blinksale.com/clients) and each collection has several member resources (e.g., http://example.blinksale.com/clients/client_id). Here are some of the URIs used in the API:

  1. http://example.blinksale.com/
  2. http://example.blinksale.com/clients
  3. http://example.blinksale.com/clients/client_id
  4. http://example.blinksale.com/clients/client_id/people
  5. http://example.blinksale.com/clients/client_id/people/person_id
  6. http://example.blinksale.com/invoices
  7. http://example.blinksale.com/invoices/invoice_id
  8. http://example.blinksale.com/invoices/invoice_id/deliveries
  9. http://example.blinksale.com/invoices/invoice_id/deliveries/delivery_id
  10. http://example.blinksale.com/invoices/invoice_id/payments
  11. http://example.blinksale.com/invoices/invoice_id/payments/payment_id

Authentication & Encryption

All API requests should have your Blinksale ID in the host (like example.blinksale.com), just like when you access the site through a browser. Login is done with HTTP Basic Authentication. For example, using the cURL command line program:

curl -u userid:password http://example.blinksale.com/

Most HTTP libraries will handle Basic Authentication details automatically. To do it manually, include an Authorization header with a value like Basic credentials, in every request. The credentials string should be the Base64-encoded version of the string userid:password. For example:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Because all Blinksale accounts can have unlimited users, you might want to create a user specifically for the API, or for a program that uses the API.

Free accounts can only access the site with HTTP (unencrypted); paid accounts can use either HTTP or HTTPS (encrypted). To turn on or off HTTPS with your paid account, click “Settings”, then “Invoice Details”, and change the SSL checkbox near the bottom of the page. Note that authentication information is sent with every API request— so if you’re using HTTP, your password will be vulnerable to eavesdropping. When using HTTPS, everything (including your password) will be encrypted.

Representation Formats

The API uses XML for requests and responses, and the expected media type is application/vnd.blinksale+xml. That media type should always be specified in two request headers: Content-Type (the format of the data you’re sending) and Accept (the format of the response you want). For example, again using cURL:

curl -H ‘Accept: application/vnd.blinksale+xml’ -H ‘Content-Type: application/vnd.blinksale+xml’ \
    -u userid:password http://example.blinksale.com/

All XML documents sent to and returned from the service should be XML 1.0, encoded as UTF-8, and include the XML namespace http://www.blinksale.com/api Within the XML, booleans are represented by the strings true and false. Dates and times are represented in ISO-8601, e.g. 2006-05-30T03:38:24Z.

In general, data within elements is open to modification, but data within attributes is read-only. For example:

<?xml version="1.0" encoding="UTF-8"?>
<invoice total="19.00" (...)>
  <terms due_date="2006-07-12">15</terms>
  <tax amount="0.00">8.75</tax_rate>

  (...)
</invoice>

In this example, the invoice total, due date, and tax amount are not editable via the API; they’re derived from other values in the system, so they can be left out of POST and PUT requests. On the other hand, the invoice terms and tax rate are editable.

In some cases, you may want to request another format, such as the HTML version of an invoice, or the Atom version of a list of invoices—just change the Accept header as needed.

Resource Methods

The Blinksale API uses four standard HTTP methods: GET, POST, PUT, and DELETE.

To retrieve a representation, use the GET method. For example (using cURL’s -X option to specify the request method):

curl -H ‘Accept: application/vnd.blinksale+xml’ -H ‘Content-Type: application/vnd.blinksale+xml’ \
    -u userid:password -X GET http://example.blinksale.com/clients

To create a new member resource, use the POST method on a collection. The body of the request should be an XML document in the same format as one of the member resources. For example, (using cURL’s -d option to provide a request body):

curl -H ‘Accept: application/vnd.blinksale+xml’ -H ‘Content-Type: application/vnd.blinksale+xml’ \
    -u userid:password -d ‘<?xml version=”1.0″ encoding=”UTF-8″?>
<client xmlns=”http://www.blinksale.com/api”>
  <name>Acme Inc.</name>
</client>’ -X POST http://example.blinksale.com/clients

The PUT method changes existing member resources. The body of the request should be an XML document in the same format as the member resource. For example:

curl -H ‘Accept: application/vnd.blinksale+xml’ -H ‘Content-Type: application/vnd.blinksale+xml’ \
    -u userid:password -d ‘<?xml version=”1.0″ encoding=”UTF-8″?>
<client xmlns=”http://www.blinksale.com/api”>
  <name>Acme Incorporated</name>
</client>’ -X PUT http://example.blinksale.com/clients/client_id

The DELETE method permanently removes a member resource. For example:

curl -H ‘Accept: application/vnd.blinksale+xml’ -H ‘Content-Type: application/vnd.blinksale+xml’ \
    -u userid:password -X DELETE http://example.blinksale.com/clients/client_id

Note that in some cases, deleting a resource will cascade to related resources. For example, deleting a client will also delete the client’s invoices and people.

Because not all HTTP libraries support the PUT and DELETE methods, they can be tunneled through POST by including a _method query parameter in the request, with a value of either PUT or DELETE.

Responses & Errors

All response codes are included in the HTTP Status response header. Possible status codes include:

  • 200: Success (upon a successful GET, PUT, or DELETE request)
  • 201: Created (upon a successful POST request)
  • 400: Resource Invalid (improperly formatted request)
  • 401: Unauthorized (incorrect or missing authentication credentials)
  • 404: Resource Not Found
  • 405: Method Not Allowed
  • 406: Not Acceptable
  • 500: Application Error

Successful POST requests (e.g., to create a new invoice) will return a status code of 201, include a Location header with the URI of the newly-created resource, and include the XML representation of the resource in the body of the response.

Successful PUT requests (e.g., to update an existing invoice) will return a status code of 200, and include the XML representation of the resource in the body of the response.

Successful DELETE requests (e.g., to delete an existing invoice) will return a status code of 200, and no body.

Clients

The /clients resource contains a list of clients with partial detail. The XML representation is formatted like this:

<?xml version="1.0" encoding="UTF-8"?>
<clients xmlns="http://www.blinksale.com/api" uri="http://example.blinksale.com/clients">
  <client uri="http://example.blinksale.com/clients/2">
    <name>Haute Haute Heat</name>
  </client>
</clients>

The client list contains abbreviated information for each client, and a link to the full detail. Those URIs look like /clients/client_id, and the XML representation looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<client xmlns="http://www.blinksale.com/api" uri="http://example.blinksale.com/clients/2" 
        updated_at="2006-09-18T16:06:19Z" created_at="2006-05-30T03:38:24Z">
  <name>Haute Haute Heat</name>
  <address1>1234 Main Street</address1>

  <address2>Suite 123</address2>
  <city>Anytown</city>
  <state>TX</state>
  <zip>70123</zip>

  <country>US</country>
  <url>http://www.example.com/</url>
  <phone>123-555-1212</phone>
  <fax>123-555-1212</fax>

  <people uri="http://example.blinksale.com/clients/2/people">
    <person uri="http://example.blinksale.com/clients/2/people/2">
      <first_name>Bob</first_name>
      <last_name>Jones</last_name>
    </person>

  </people>
  <invoices uri="">
    <invoice uri="http://example.blinksale.com/invoices/1" />
  </invoices>
</client>

Creating a new resource doesn’t require every element shown above. For example, to create a client, you could POST to /clients with a minimal request body like this:

<?xml version="1.0" encoding="UTF-8"?>
<client xmlns="http://www.blinksale.com/api">
  <name>Haute Haute Heat</name>
</client>

Updating a resource doesn’t require every element either. For example, to change a client’s phone number, you could PUT to /clients/client_id with a minimal request body like this:

<?xml version="1.0" encoding="UTF-8"?>
<client xmlns="http://www.blinksale.com/api">
  <phone>123-555-1212</phone>
</client>

People

The /clients/client_id/people resource contains a list of people associated with a client in partial detail. The XML representation is formatted like this:

<?xml version="1.0" encoding="UTF-8"?>
<people xmlns="http://www.blinksale.com/api" uri="http://example.blinksale.com/clients/2/people">
  <person uri="http://example.blinksale.com/clients/2/people/2">
    <first_name>Bob</first_name>

    <last_name>Jones</last_name>
    <email>bob@example.com</email>
  </person>
</people>

The person list contains abbreviated information for each person, and a link to the full detail. Those URIs look like /clients/client_id/people/person_id, and the XML representation looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<person xmlns="http://www.blinksale.com/api" uri="http://example.blinksale.com/clients/2/people/2" 
        updated_at="2006-07-26T05:13:52Z" created_at="2006-07-26T04:58:31Z">
  <first_name>Bob</first_name>
  <last_name>Jones</last_name>
  <email>bob@example.com</email>

  <phone_office>123-555-1212</phone_office>
  <phone_mobile>123-555-1212</phone_mobile>
</person>

Creating a new resource doesn’t require every element shown above. For example, to create a person, you could POST to /clients/client_id/people with a minimal request body like this:

<?xml version="1.0" encoding="UTF-8"?>
<person xmlns="http://www.blinksale.com/api">
  <first_name>Bob</first_name>
  <last_name>Jones</last_name>
  <email>bob@example.com</email>

</person>

Updating a resource doesn’t require every element either. For example, to change a person’s email address, you could PUT to /clients/client_id/people/person_id with a minimal request body like this:

<?xml version="1.0" encoding="UTF-8"?>
<person xmlns="http://www.blinksale.com/api">

  <email>jones@example.com</email>
</person>

Invoices

The /invoices resource contains a list of invoices with partial detail. The results can be limited by including parameters in the query string, which can be combined in any order:

  • /invoices?start=2006-01-01 excludes invoices before the given date. Defaults to January 1 of the current year.
  • /invoices?end=2006-12-31 excludes invoices after the given date. Defaults to December 31 of the current year.
  • /invoices?status=draft will only return invoices with the given status (draft, open, past_due, closed, or all). Defaults to all.
  • /invoices?tags=foo will only return invoices with the given tag.

The XML representation is formatted like this:

<?xml version="1.0" encoding="UTF-8"?>
<invoices xmlns="http://www.blinksale.com/api">
  <invoice status="open" uri="http://example.blinksale.com/invoices/1" total="37.56" total_due="37.56">
    <client name="Acme">http://example.blinksale.com/clients/2</client>

    <number>100001</number>
    <date>2006-09-19</date>
    <terms due_date="2006-10-04">15</terms>
    <currency>USD</currency>

    <tags>brian, consulting</tags>
  </invoice>
  (...)
</invoices>

To get invoice lists in other formats, just change your Accept header. For Atom, use application/atom+xml. For iCalendar, use text/calendar.

The invoice list contains abbreviated information for each invoice, and a link to the full detail. Those URIs look like /invoices/1, and the representation looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<invoice xmlns="http://www.blinksale.com/api" uri="http://example.blinksale.com/invoices/1" 
         status="pastdue" subtotal="19.00" total="19.00" paid="2.00" total_due="17.00"
         surplus="0.00" updated_at="2006-09-20T17:27:48Z" created_at="2006-06-27T22:43:13Z">
  <client name="Acme">http://example.blinksale.com/clients/2</client>
  <number>100001</number>

  <po_number>123456</po_number>
  <date>2006-06-27</date>
  <terms due_date="2006-07-12">15</terms>
  <currency>USD</currency>

  <tax amount="0.00">8.75%</tax>
  <freight>0.00</freight>
  <late_fee amount="0.00">0%</late_fee>
  <tags>bob, scott</tags>

  <lines total="882.00">
    <line>
      <name>French Hens</name>
      <quantity>3.0</quantity>
      <units>Product</units>

      <unit_price>19.00</unit_price>
      <taxed>false</taxed>
    </line>
    <line>
      <name>Piper-Piping</name>

      <quantity>11.0</quantity>
      <units>Service</units>
      <unit_price>75.00</unit_price>
      <taxed>false</taxed>

    </line>
  </lines>
  <deliveries uri="http://example.blinksale.com/invoices/1/deliveries">
    <delivery uri="http://example.blinksale.com/invoices/1/deliveries/3" created_at="2006-09-22T23:51:42Z">
      <body>Here's the invoice for the latest work - thanks!</body>

      <recipient name="John Doe" email="john@acme.com">http://example.blinksale.com/clients/2/people/2</recipient>
      <recipient name="Bob Smith" email="bob@example.com">http://example.blinksale.com/users/1</recipient>
    </delivery>
  </deliveries>
  <payments uri="http://example.blinksale.com/invoices/1/payments" total="10.00">

    <payment uri="http://example.blinksale.com/invoices/1/payments/5" created_at="2006-09-25T18:01:33Z">
      <amount>10.00</amount>
      <date>2006-09-25</date>
      <payment_method>Check</method>

      <number>10001</number>
    </payment>
  </payments>
  <notes>Please reference this invoice number in your check memo.</notes>
  <include_payment_link>true</include_payment_link>

</invoice>

The currency element is a property of an invoice, and automatically inherited by its payments, lines, etc.

The status attribute of the invoice element can be one of four values: closed, pastdue, draft, or open.

The tags element contains a list of tag strings, separated by spaces; space characters are not allowed within tags.

The units element can be one of four values: Service, Hours, Days, or Product. The value is purely for presentation—it doesn’t affect how line values are calculated.

The late_fee element can be one of four percentage values (0%, 1%, 1.5%, or 2%) which will accumulate per 30 days past due, or an absolute fee (e.g., 100.00) that will be applied one time only. The amount attribute of the late_fee element will show the absolute amount of the current late fee. In other words, if a $100 invoice has a late fee of 1%, the amount attribute on the late_fee element will be 0.00 for the first 30 days, 1.00 when 30 days past due, 2.00 when 60 days past due, etc.

The notes element should be plain text.

Creating a new resource doesn’t require every element shown above. For example, to create an invoice, you could POST to /invoices with a minimal request body like this:

<?xml version="1.0" encoding="UTF-8"?>
<invoice>
  <client>http://example.blinksale.com/clients/38732</client>

  <number>100001</number>
  <date>2006-09-27</date>
  <terms>30</terms>
  <currency>USD</currency>

  <lines>
    <line>
      <name>Consulting</name>
      <quantity>1.0</quantity>
      <units>Hours</units>

      <unit_price>100.00</unit_price>
      <taxed>false</taxed>
    </line>
  </lines>
</invoice>

Updating a resource doesn’t require every element either. For example, to change an invoice’s tags, you could PUT to /invoices/invoice_id with a minimal request body like this:

<?xml version="1.0" encoding="UTF-8"?>
<invoice xmlns="http://www.blinksale.com/api">
  <tags>foo, bar</tags>

</invoice>

Deliveries

The /invoices/invoice_id/deliveries resource contains a list of deliveries for an invoice—in other words, a record of every time the invoice has been sent. The XML representation is formatted like this:

<?xml version="1.0" encoding="UTF-8"?>

<deliveries uri="http://example.blinksale.com/invoices/1/deliveries" xmlns="http://www.blinksale.com/api">
  <delivery uri="http://example.blinksale.com/invoices/1/deliveries/3" created_at="2006-09-22T23:51:42Z">
    <body>Here's the invoice for the latest work - thanks!</body>
    <recipient name="John Doe" email="john@acme.com">http://example.blinksale.com/clients/2/people/2</recipient>
    <recipient name="Bob Smith" email="bob@example.com">http://example.blinksale.com/users/1</recipient>

  </delivery>
</deliveries>

The member resource URIs look like /invoices/invoice_id/deliveries/delivery_id, and their XML representation looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<delivery uri="http://example.blinksale.com/invoices/1/deliveries/3" xmlns="http://www.blinksale.com/api" created_at="2006-09-22T23:51:42Z">

  <body>Here's the invoice for the latest work - thanks!</body>
  <recipient name="John Doe" email="john@acme.com">http://example.blinksale.com/clients/2/people/2</recipient>
  <recipient name="Bob Smith" email="bob@example.com">http://example.blinksale.com/users/1</recipient>
</delivery>

The delivery element can contain any number of recipient elements, each of which should contain a URI for a person.

Creating a new resource doesn’t require every element shown above. For example, to send an invoice, you could POST to /invoices/invoice_id/deliveries with a minimal request body like this:

<?xml version="1.0" encoding="UTF-8"?>
<delivery xmlns="http://www.blinksale.com/api">
  <recipient>http://example.blinksale.com/clients/client_id/people/person_id</recipient>
</delivery>

Payments

The /invoices/invoice_id/payments resource contains a list of payments for an invoice. The XML representation is formatted like this:

<?xml version="1.0" encoding="UTF-8"?>
<payments xmlns="http://www.blinksale.com/api" uri="http://example.blinksale.com/invoices/1/payments" total="10.00">

  <payment uri="http://example.blinksale.com/invoices/1/payments/5" created_at="2006-09-25T18:01:33Z">
    <amount>10.00</amount>
    <date>2006-09-25</date>
    <payment_method>Check</method>

    <number>10001</number>
  </payment>
</payments>

The member resource URIs look like /invoices/invoice_id/payments/payment_id, and the XML representation looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<payment xmlns="http://www.blinksale.com/api" uri="http://example.blinksale.com/invoices/1/payments/5" created_at="2006-09-25T18:01:33Z">
  <amount>10.00</amount>
  <date>2006-09-25</date>
  <payment_method>Check</method>

  <number>10001</number>
</payment>

Creating a new resource doesn’t require every element shown above. For example, to record a payment, you could POST to /invoices/invoice_id/payments with a minimal request body like this:


<?xml version="1.0" encoding="UTF-8"?>
<payment xmlns="http://www.blinksale.com/api">
  <amount>1000.00</amount>
  <date>2006-09-27</date>
</payment>

Questions?

If you have any questions or issues, feel free to contact support@blinksale.com.

Document History

  • 2007-03-19: Adding the (optional) notes and include_payment_link elements to the invoices representation. Backwards compatible.
  • 2006-10-02: Release 1.0
  • 2006-09-20: Prerelease