API Conventions

Calling Conventions

 Not all of our APIs follow these conventions today.  We are working to resolve this.  In cases where we do not follow these conventions, the API will make a note of that in the documentation.

All APIs from Lulu follow a standard set of calling conventions:

Lulu exposes all of its APIs through HTTPS exclusively.  Be sure not to accidentally submit API information, especially authentication information, without using SSL encryption.

Authentication parameters, such as api_key and auth_token, should always be passed as part of the URL query string, including for POST calls. The POST body should include the request entity for the call.

Except where noted, all APIs support both XML and JSON for input and output.  Requests should specify an Accept header of either "application/xml" or "application/json" to indicate the preferred response format.  A request lacking an Accept header will still succeed, but the default response format may vary by API and should not be relied upon.  We will standardize on a default format in an upcoming release.

Requests that include a request body must specify an appropriate Content-type header.  Except where noted -- for example, file uploads -- this should be "application/xml" or "application/json".

HTTP Methods

Lulu's APIs are accessed by standard HTTP methods according to the following conventions:

  • GET is used for actions which do not change the state of the server.
  • POST is used for actions which create or update a resource or send large amounts of data to the server.
  • DELETE is used for actions which destroy data on the server.
  • None of Lulu's APIs currently use PUT requests.

HTTP Response Codes

Lulu's APIs use standard HTTP response codes to indicate success or failure.  In the event of a failure, the API will also return a notification object indicating the nature of the failure whenever possible.

  • HTTP 200: Success
  • HTTP 400: if the request body is invalid for a given call or is malformed and cannot be parsed.
  • HTTP 403: if the API requires an authenticated user and an auth_token isn't provided, or if the auth_token provided doesn't represent a user with permissions to perform the requested action. HTTP 403 may also be returned if a particular request is well-formed but not permitted -- for example, attempting to update a read-only attribute.
  • HTTP 404: if a non-existent resource is requested.
  • HTTP 405: if the HTTP method requested is not allowed for that resource -- for example, attempting to GET a resource that expects only POST requests, and vice versa.  The response will include an Allow header indicating the permitted methods.
  • HTTP 406: if the request includes an Accept header whose value includes a MIME type other than "application/xml" or "application/json".
  • HTTP 500: on all other errors. The body of the response will contain a notification object with specific details.

Naming Conventions

Lulu's APIs follow a standard naming convention:

https://apps.lulu.com/api/api_set/version/resource

Individual API endpoints are identified by the combination of three identifiers:

  1. api_set -- The set of APIs that you are accessing.  We have grouped our APIs into logical groups to make them easier to understand.  All APIs in a given set will use the same api_key.  Some api_sets share a common api_key.  The key requirement is a part of the api_set documentation.
  2. version -- The version of the API.  See below for backwards compatibility rules.
  3. resource -- The name of the API resource that you are accessing.  Details for each API can be found in our documentation.

Error Notifications Standard

APIs under the "create", "sell", and "shop" API sets have a standard method of returning error and warning notifications. This will include a list of all encountered problems, specifying

  • code -- A unique error code that can be used to map to an appropriate user-facing string.
  • severity -- The severity of the notification. Either ERROR or WARNING.
  • text -- A human readable explanation of what went wrong. This should be used for debugging, not for user-facing messaging.
  • details -- Where applicable, a list of key-value pairs of data pertinent to the error that occured.

Example (XML)

<notifications>
    <notification>
        <code>1000010001</code>
        <severity>ERROR</severity>
        <text>This is an error</text>
        <details>
            <detail key="firstdetail" value="100"/>
            <detail key="seconddetail" value="200"/>
        </details
    </notification>
</notifications>

Example (JSON)

"notifications": [
    { 
      "code": 1000010001,
      "severity": "ERROR",
      "text": "This is an error",
      "details": {
        "firstdetail": 100,
        "seconddetail": 200
      }
    }, 
    ...
]

Notification Context

If an operation fails completely, the result will be an HTTP error response, the body of which is a notifications structure.

If a creation or update partially succeeds, or succeeds with warnings, the expected resource will be returned. That resource will contain a notifications node. For example, a conversion that fails because of a corrupted file may look like this:

<conversion>
    <conversionId>234</conversionId>
    <status>ERROR</status>
    ...
    <notifications>
        <notification>
            <code>1100000005</code>
            <severity>ERROR</severity>
            <text>Conversion finalization error: PDF header signature not found.</text>
        </notification>
    </notifications>
    ...
</conversion>

Backwards Compatibility

Lulu commits to providing backwards compatible support for released APIs during the lifetime of the API and for a minimum of one year after an API is deprecated.

Occasionally, Lulu will add features to our released APIs by adding new fields in our data objects.  When adding new fields, they will either be optional or include intelligent defaults.  In this way, existing application requests will continue to work.  However, you may not be able to take advantage of new features until you add these new fields to your requests.

When new features can not be added in a backwards compatible way, we will supersede the new API with a new API, denoted by incrementing the version component of the endpoint.  When releasing a new API, we will mark the original endpoint as deprecated in the documentation, and announce it in the blog.  As stated above, we commit to support the old API for a minimum of one year after it is marked as deprecated.