Skip to content

API Overview

Data Types

The huggg API, like most APIs, can be thought of as a interface for Creating, Reading, Updating and Deleting data. Our data is split into three classes:

Scalar Types

Scalar values are as most languages and systems would define them: singular values which are not broken down into any smaller parts when stored or transmitted. Examples include:

  • Numbers: integers, floating points, etc
  • Boolean values
  • String values: names, email addresses etc

Models

Models, sometimes called compounds in other systems, are a collections of one of more scalar or model values. In programming, these can be thought of as a class, or struct. Examples include:

  • Coordinates - which are made up of two scalar values: longitude and latitude
  • Clusters - which are made up of three scalar values: type, image_url, and count, and 2 other sub models: pin (which is a Coordinate model) and area (which is an Area model).

Entities

Entities are a special form of model which has an id. This makes it uniquely identifiable, and standalone. Examples include:

Working with Data

Entities are the only type of data which can be directly requested or worked with (for example, you can Redeem a specific huggg).

Whenever the API returns an entity, all of its scalar and model values will always be returned, assuming you have permission to view them. This makes entities reasonably atomic and cacheable - whenever an entity is returned it will be exactly the same.

All responses from the API come in a JSON envelope - this includes meta data about the state of the request, and a data field for the response of the endpoint itself.

Single Entity Endpoints

Where an endpoint only returns a single entity, the data field is a JSON representation of the entity itself. For successful requests, there are not normally any extra fields at the top level envelope.

Entity Collection Endpoints

Some endpoints return collections of entities - in these cases data is an array of entities. In these cases, endpoints normally support pagination, and by default return a maximum of 20 results per page.

Pagination Envelope Fields

For these endpoints, the top level envelope includes the following fields, in addition to data:

from - The index within the overall collection that the first entity in this page response is.

to - The index within the overall collection that the last entity in this page response is.

current_page - The current page

path - The current canonical URL

last_page - The last page in this collection

total - The total number of entities in the overall collection

per_page - The number of entities that will be returned per page

prev_page_url - The canonical URL of the previous page in the collection

next_page_url - The canonical URL of the next page in the collection

Pagination Query Parameters

The following URL query parameters are also normally accepted:

page - Set the page to request (defaults to 1 if not provided)

per_page - The number of results to set per page (most endpoints default to 20 if not provided)

Entity References

It is very common for entities to be related to each other. For example, a Product belongs to a Brand, and a Brand has one or more Products.

One-to-*1 relationships are represented as scalar field on the entity, with the referenced entity's ID. As this is a scalar value, this is always returned. For example, a Product has a brand_id field:

1
2
3
4
5
6
{
    "id": "example_product",
    "brand_id": "example_brand",
    "label": "An Example Coffee Product",
    ...
}

Many-to-*2 relationships are represented as an array of the referenced entities' IDs. As this is a model value, this is always returned. For example, a Brand has an array of products, each of which is an ID:

1
2
3
4
5
6
7
8
{
    "id": "example_brand",
    "products": [
        "example_product",
        "another_example_product"
    ],
    "name": "An Example Merchant Brand"
}

Embedding Entities

Often, a client knows it is going to need more than one related entity in order to complete a task. As an example, let us use an application which needs to display the following message:

{Sender's First Name} sent you a {product name} huggg on {huggg date}

In order to do this, you need three entities: the huggg, the product linked to the huggg, and the sender (user entity) linked to the huggg.

In this case, the "primary" entity we're interested in is the huggg, as the other two entities link off from it. When requesting this huggg we can ask the endpoint to also return the huggg's purchase, which is a reference to a product, and sender, which is a reference to a user, in the same response envelope.

To do this, we pass these as embed[] URL parameters:

/api/v2/hugggs/{hugggId}?embed[]=purchase&embed[]=sender

In the response, the data field of the envelope will include the huggg, including its references to purhcase_id and sender_id as described in the Entity References section above. In addition to this, the response envelope will include an embedded collection with arrays for users and products:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
    "data": {
        "id": "id_of_a_huggg",
        "sender_id": "id_of_a_user",
        "purchase_id": "id_of_a_product",
        ...
    },
    "embedded": {
        "users": [
            {"id": "id_of_a_user", ...}
        ],
        "products": [
            {"id": "id_of_a_product", ...}
        ]
    }
}

Whenever entities are embedded, multiple references to the same entity will only ever result in the entity being serialised once. For example, if you were to request this huggg's sender and receiver, and this huggg had been sent by someone to themselves, that user would only be included once in the users embedded collection. You are also able to embed relations of relations, for example you could include a huggg's purchase.brand.

Full example

Request:

/api/v2/hugggs/id_of_a_huggg
    ?embed[]=purchase
    &embed[]=purchase.brand
    &embed[]=sender
    &embed[]=receiver
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
    "data": {
        "id": "id_of_a_huggg",
        "sender_id": "id_of_a_user",
        "receiver_id": "id_of_a_user",
        "purchase_id": "id_of_a_product",
        ...
    },
    "embedded": {
        "users": [
            {
                "id": "id_of_a_user",
                "first_name": "Steve",
                ...
            }
        ],
        "products": [
            {
                "id": "id_of_a_product",
                "brand_id": "id_of_a_brand",
                "label": "An Example Coffee",
                ...
            }
        ],
        "brands": [
            {
                "id": "id_of_a_brand",
                "name": "An Example Merchant Brand",
                ...
            }
        ]
    }
}

  1. One-to-One and One-to-Many relationships 

  2. Many-to-One and Many-to-Many relationships