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.
JSON will be returned in all responses from the API, including errors. In particular, responses will be returned using the HAL media type.
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.
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."]
}
}
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.
| name: | string, required Package name. |
|---|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
A purchasable item available to the application’s users.
| 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:
|
| state: | string, required for device Item’s purchase state, only present when retreived by a device, one of:
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: device123Example 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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
:statuscode 409 item not purchased or already acknowledged from other device
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
A Purchase represents a user’s transaction to buy a package item.
| 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:
|
| 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. |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
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: |
|
|---|---|
| Request Headers: | |
|
|
| Status Codes: |
|
Errors
item_sku or no item matching provided value{
"error": "INVALID_ITEM_SKU",
"description": "A valid item_sku must be provided for item purchases."
}
currency{
"error": "INVALID_ITEM_CURRENCY",
"description": "A valid currency must be provided for item purchases."
}
X-Device-Id header in request{
"error": "INVALID_DEVICE_ID",
"description": "No X-Device-Id header was found in the reqest."
}