In App Purchases API

Introduction

The In App Purchases API is organized around REST. Our API is designed to have predictable, resource-oriented URLs and to use HTTP response codes to indicate API errors. We use built-in HTTP features, like HTTP authentication and HTTP verbs, which can be understood by off-the-shelve HTTP clients.

The In App Purchases API is exposed at the following base URLs:

Staging: https://myapps.developer.staging.ubuntu.com/inventory/api/v1

Production: https://myapps.developer.ubuntu.com/inventory/api/v1

All paths mentioned in the rest of this document should be considered relative to these base URLs.

Response Format

JSON will be returned in all responses from the API, including errors. In particular, responses will be returned using the HAL media type.

Authentication

You authenticate to the In App Purchases API by providing OAuth signed requests using an OAuth token associated with your Ubuntu One account.

All API requests SHOULD be made over HTTPS. Calls made over plain HTTP will be redirected to the equivalent HTTPS URL. You MUST authenticate for all requests.

Requests SHOULD include a X-Device-Id header to identify the device the user is accessing the API from.

Errors

The In App Purchases API uses conventional HTTP response codes to indicate success or failure of an API request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from the provided information (e.g. a required parameter was missing), and codes in the 5xx range indicate an error with our servers.

Error responses will include the following fields in the body:

error:

string, required

A short string describing the kind of error that occurred. This is intended for developers writing clients for the API.

description:

string, optional

A human-readable message giving more details about the error. This is intended for displaying to end users.

detail:

string, optional

A JSON object to provide in-detail information about the exact nature of the error. This is intended for developers writing clients for the API.

Example

{
  "error": "INVALID_CURRENCY",
  "description": "The provided currency (ARS) is not a supported currency."
}

An example of detailed error information

{
  "error": "INVALID_REQUEST",
  "detail": {
    "sku": ["This field is required."],
    "title": ["This field is required."]
  }
}

Reference

Package

A Package is the primary resource in the API. Clients of the API should construct a URL using the template, /packages/{name}, where name is the application’s package name.

Package Model

name:

string, required

Package name.

Retrieve Package Details as User

Retrieve a package and a list of its items as embedded resources. The items are extended to include the status of the item in relation to the user’s purchase history.

GET /packages/{name}

Example request:

GET /packages/app.example HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "name": "app.example",
  "_links": {
    "self": {"href": "/packages/app.example"},
    "items": {"href": "/packages/app.example/items"},
    "purchases": {"href": "/packages/app.example/purchases"}
  },
  "_embedded": {
    "item": [
      {
        "id": 1,
        "sku": "sku1",
        "title": "Item 1 Title",
        "description": "Item 1 Description",
        "prices": {
          "USD": "2.99",
          "EUR": "2.49",
          "GBP": "1.99"
        },
        "type": "consumable",
        "state": "available"
        "_links": {
          "self": {"href": "/packages/app.example/items/1"}
        }
      },
      {
        "id": 2,
        "sku": "sku2",
        "title": "Item 2 Title",
        "description": "Item 2 Description",
        "prices": {
          "USD": "5.98",
          "EUR": "4.98",
          "GBP": "3.98"
        },
        "type": "unlockable",
        "state": "purchased"
        "_links": {
          "self": {"href": "/packages/app.example/items/2"}
        }
      }
    ]
  }
}
Parameters:
  • name (string) – the package name
Request Headers:
 
  • Authorization – OAuth token to authenticate
  • X-Device-Id – device making the request
Status Codes:

Retrieve Package Details as Developer

Retrieve the package and a list of all its available items as embedded resources.

GET /packages/{name}

Example request:

GET /packages/app.example HTTP/1.1
Authorization: OAuth realm="…", …

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "name": "app.example",
  "_links": {
    "self": {"href": "/packages/app.example"},
    "items": {"href": "/packages/app.example/items"}
  },
  "_embedded": {
    "item": [
      {
        "id": 1,
        "sku": "sku1",
        "title": "Item 1 Title",
        "description": "Item 1 Description",
        "prices": {
          "USD": "2.99",
          "EUR": "2.49",
          "GBP": "1.99"
        },
        "type": "consumable",
        "_links": {
          "self": {"href": "/packages/app.example/items/1"}
        }
      },
      {
        "id": 2,
        "sku": "sku2",
        "title": "Item 2 Title",
        "description": "Item 2 Description",
        "prices": {
          "USD": "5.98",
          "EUR": "4.98",
          "GBP": "3.98"
        },
        "type": "unlockable",
        "_links": {
          "self": {"href": "/packages/app.example/items/2"}
        }
      }
    ]
  }
}
Parameters:
  • name (string) – the package name
Request Headers:
 
Status Codes:

Package Items

A purchasable item available to the application’s users.

Item Model

id:

int, required

Unique ID of the item.

sku:

string, required

A short identifier, unique to the application.

title:

string, required

Item title.

description:

string

Item description.

prices:

map, required

Map of currency code to item price in that currency, e.g.

{
  "USD": "2.99",
  "EUR": "2.49",
  "GBP": "1.99"
}
type:

string, required

Item type, one of:

  • consumable - can be consumed and repurchased
  • unlockable - can only be purchased once
state:

string, required for device

Item’s purchase state, only present when retreived by a device, one of:

  • available - available for purchase
  • approved - purchase approved, needs acknowledging
  • purchased - purchased

Retrieve Package Items as User

The application’s items, returned as embedded resources. Each item is extended to include its status in relation to the user’s purchase history.

GET /packages/{name}/items

Example request:

GET /packages/app.example HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "_links": {
    "self": {"href": "/packages/app.example/items"}
  },
  "_embedded": {
    "item": [
      {
        "id": 1,
        "sku": "sku1",
        "title": "Item 1 Title",
        "description": "Item 1 Description",
        "prices": {
          "USD": "2.99",
          "EUR": "2.49",
          "GBP": "1.99"
        },
        "type": "consumable",
        "state": "available"
        "_links": {
          "self": {"href": "/packages/app.example/items/1"}
        }
      },
      {
        "id": 2,
        "sku": "sku2",
        "title": "Item 2 Title",
        "description": "Item 2 Description",
        "prices": {
          "USD": "5.98",
          "EUR": "4.98",
          "GBP": "3.98"
        },
        "type": "unlockable",
        "state": "purchased"
        "_links": {
          "self": {"href": "/packages/app.example/items/2"}
        }
      }
    ]
  }
}
Parameters:
  • name (string) – the package name
Request Headers:
 
  • Authorization – OAuth token to authenticate
  • X-Device-Id – device making the request
Status Codes:

Retrieve Item Details as User

GET /packages/{name}/items/{id}

Example request:

GET /packages/app.example/items/1 HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "id": 1,
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable",
  "state": "available",
  "_links": {
    "self": {"href": "/packages/app.example/items/1"},
    "package": {"href": "/packages/app.example"},
    "purchase": [
        {"href": "/packages/app.example/purchases/1"}
    ]
  }
}
Parameters:
  • name (string) – the package name
  • id (int) – the item id
Request Headers:
 
Status Codes:

Retrieve Item Details By SKU

GET /packages/{name}/items/by-sku/{sku}

Example request:

GET /packages/app.example/items/by-sku/sku1 HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "id": 1,
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable",
  "state": "available"
  "_links": {
    "self": {"href": "/packages/app.example/items/1"}
  }
}
Parameters:
  • name (string) – the package name
  • sku (string) – the item sku
Request Headers:
 
Status Codes:

Acknowledge Item Purchase

Acknowledging an item allows a device to notify the Inventory API that an item has been used by the application installed on the user’s device.

Acknowledging a consumable item also makes the item available for purchase again in the future.

POST /packages/{name}/items/{id}

Example request:

POST /packages/app.example/items/1 HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123
Content-Type: application/json

{
  "state": "acknowledged",
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "id": 1,
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable",
  "state": "available",
  "_links": {
    "self": {"href": "/packages/app.example/items/1"},
    "package": {"href": "/packages/app.example"},
    "purchase": [
        {"href": "/packages/app.example/purchases/1"}
    ]
  }
}
Parameters:
  • name (string) – the package name
  • id (int) – the item id
Request Headers:
 
Status Codes:

:statuscode 409 item not purchased or already acknowledged from other device

Retrieve Package Items as Developer

The application’s items, returned as embedded resources.

GET /packages/{name}/items

Example request:

GET /packages/app.example/items HTTP/1.1
Authorization: OAuth realm="…", …

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "_links": {
    "self": {"href": "/packages/app.example/items"}
  },
  "_embedded": {
    "item": [
      {
        "id": 1,
        "sku": "sku1",
        "title": "Item 1 Title",
        "description": "Item 1 Description",
        "prices": {
          "USD": "2.99",
          "EUR": "2.49",
          "GBP": "1.99"
        },
        "type": "consumable",
        "_links": {
          "self": {"href": "/packages/app.example/items/1"}
        }
      },
      {
        "id": 2,
        "sku": "sku2",
        "title": "Item 2 Title",
        "description": "Item 2 Description",
        "prices": {
          "USD": "5.98",
          "EUR": "4.98",
          "GBP": "3.98"
        },
        "type": "unlockable",
        "_links": {
          "self": {"href": "/packages/app.example/items/2"}
        }
      }
    ]
  }
}
Parameters:
  • name (string) – the package name
Request Headers:
 
Status Codes:

Retrieve Item Details as Developer

GET /packages/{name}/items/{id}

Example request:

GET /packages/app.example/items/1 HTTP/1.1
Authorization: OAuth realm="…", …

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "id": 1,
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable",
  "_links": {
    "self": {"href": "/packages/app.example/items/1"},
    "package": {"href": "/packages/app.example"}
  }
}
Parameters:
  • name (string) – the package name
  • id (int) – the item id
Request Headers:
 
Status Codes:

Create a New Item

This is only available to the package’s owner.

POST /packages/{name}/items

Example request:

POST /packages/app.example/items HTTP/1.1
Authorization: OAuth realm="…", …
Content-Type: application/json

{
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable"
}

Example response:

HTTP/1.1 201 Created
Content-Type: application/hal+json
Location: /packages/app.example/items/1

{
  "id": 1,
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable",
  "_links": {
    "self": {"href": "/packages/app.example/items/1"},
    "package": {"href": "/packages/app.example"}
  }
}
Parameters:
  • name (string) – the package name
Request Headers:
 
Status Codes:

Update Item Details

This is only available to the package’s owner.

PUT /packages/{name}/items/{id}

Example request:

PUT /packages/app.example/items/1 HTTP/1.1
Authorization: OAuth realm="…", …
Content-Type: application/json

{
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable"
}

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "id": 1,
  "sku": "sku1",
  "title": "Item 1 Title",
  "description": "Item 1 Description",
  "prices": {
    "USD": "2.99",
    "EUR": "2.49",
    "GBP": "1.99"
  },
  "type": "consumable",
  "_links": {
    "self": {"href": "/packages/app.example/items/1"},
    "package": {"href": "/packages/app.example"}
  }
}
Parameters:
  • name (string) – the package name
  • id (int) – the item id
Request Headers:
 
Status Codes:

Remove Item For Sale

This is only available to the package’s owner.

DELETE /packages/{name}/items/{id}

Example request:

DELETE /packages/app.example/items/1 HTTP/1.1
Authorization: OAuth realm="…", …

Example response:

HTTP/1.1 204 No Content
Parameters:
  • name (string) – the package name
  • id (int) – the item id
Request Headers:
 
Status Codes:

Purchases

A Purchase represents a user’s transaction to buy a package item.

Purchase Model

id:

int, required

Unique purchase ID.

requested_timestamp:
 

string[date], required

Timestamp when purchase was requested.

requested_device:
 

string, required

ID of the device that initiated the purchase.

status:

string, required

Purchase status, one of:

  • new - purchase in progress
  • successful - purchase completed successfully
  • failed - purchase failed
completed_timestamp:
 

string[date]

Timestamp when purchase completed, whether successful or failed.

acknowledged_timestamp:
 

string[date]

Timestamp when purchase was acknowledged.

acknowledged_device:
 

string, required

ID of the device that acknowledged the purchase.

Retrieve Purchases as User

A list of all purchases the device’s user has made for items of an application.

GET /packages/{name}/purchases

Example request:

GET /packages/app.example/purchases HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "_links": {
    "self": {"href": "/packages/app.example/purchases"},
    "package": {"href": "/packages/app.example"}
  },
  "_embedded": {
    "purchase": [
      {
        "id": 1,
        "requested_timestamp": "2015-03-12T14:33:23.000Z",
        "requested_device": "device123",
        "user_id": "user1",
        "status": "successful",
        "completed_timestamp": "2015-03-12T14:38:11.000Z",
        "_links": {
          "self": {"href": "/packages/app.example/purchases/1"},
          "package": {"href": "/packages/app.example"}
        },
        "_embedded": {
          "item": {
            "id": 1,
            "sku": "sku1",
            "title": "Item 1 Title",
            "description": "Item 1 Description",
            "type": "consumable",
            "state": "purchased"
            "_links": {
              "self": {"href": "/packages/app.example/items/1"}
            }
          }
        }
      }
    ]
  }
}
Parameters:
  • name (string) – the package name
Request Headers:
 
Status Codes:

Retrieve Purchase Details as User

GET /packages/{name}/purchases/{id}

Example request:

GET /packages/app.example/purchases/1 HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123

Example response:

HTTP/1.1 200 OK
Content-Type: application/hal+json

{
  "id": 1,
  "requested_timestamp": "2015-03-12T14:33:23.000Z",
  "requested_device": "device123",
  "user_id": "user1",
  "status": "successful",
  "completed_timestamp": "2015-03-12T14:38:11.000Z",
  "_links": {
    "self": {"href": "/packages/app.example/purchases/1"},
    "package": {"href": "/packages/app.example"}
  },
  "_embedded": {
    "item": {
      "id": 1,
      "sku": "sku1",
      "title": "Item 1 Title",
      "description": "Item 1 Description",
      "type": "consumable",
      "state": "purchased"
      "_links": {
        "self": {"href": "/packages/app.example/items/1"}
      }
    }
  }
}
Parameters:
  • name (string) – the package name
  • id (int) – the purchase id
Request Headers:
 
  • Authorization – OAuth token to authenticate
  • X-Device-Id – Device making the request
Status Codes:

Create a New Purchase

POST /packages/{name}/purchases

Example request:

POST /packages/app.example/purchases HTTP/1.1
Authorization: OAuth realm="…", …
X-Device-Id: device123
Content-Type: application.json

{
    "item_sku": 1,
    "currency": "USD"
}

Example response:

HTTP/1.1 201 Created
Location: /packages/app.example/purchases/1
Content-Type: application/hal+json

{
  "id": 1,
  "requested_timestamp": "2015-03-12T14:33:23.000Z",
  "requested_device": "device123",
  "status": "new",
  "_links": {
    "self": {"href": "/packages/app.example/purchases/1"},
    "package": {"href": "/packages/app.example"}
  },
  "_embedded": {
    "item": {
      "id": 1,
      "sku": "sku1",
      "title": "Item 1 Title",
      "description": "Item 1 Description",
      "type": "consumable",
      "_links": {
        "self": {"href": "/packages/app.example/items/1"}
      }
    }
  }
}
Parameters:
  • name (string) – the package name
Request Headers:
 
Status Codes:

Errors

  • Missing item_sku or no item matching provided value
{
  "error": "INVALID_ITEM_SKU",
  "description": "A valid item_sku must be provided for item purchases."
}
  • Missing or invalid currency
{
  "error": "INVALID_ITEM_CURRENCY",
  "description": "A valid currency must be provided for item purchases."
}
  • Missing X-Device-Id header in request
{
  "error": "INVALID_DEVICE_ID",
  "description": "No X-Device-Id header was found in the reqest."
}