The Contain Feature

Many Network API methods (Offer::findById, Conversion::findAll, Affiliate::findAllByIds, etc.) include a special parameter called "contain". This feature allows you to retrieve and join related data together, such as categories associated to individual offers, in a single API call.

Using Contain

The contain parameter takes an array of strings as input. Each value in that array corresponds to a related model allowed by that method. For example, to retrieve data for every category related to each offer retrieved from Offer::findAll:

https://NETWORKID.api.hasoffers.com/Apiv3/json?NetworkToken=NETWORK_TOKEN&Target=Report&Method=getStats&contain[]=OfferCategory

View/Modify This Call in Our API Builder

Of course, add filters, fields, and other find functionality as desired to tailor the resulting list of core objects (such as Offer objects for Offer::findAll).

How the Response Changes

The response is formatted differently when you use contain. Normally, each result in the response array holds a list of fields. When you use contain, each result holds two arrays:

  • One named after the core model, which holds the fields and values for the core object (Offer in the example below)
  • One named after the model referenced in contain, which holds an array of related objects (OfferCategory in the example below)
"data": {
    "10": {
        "Offer": {
            "id": "10",
            "name": "$1,500 Mondo Burger Gift Card"
            … other Offer fields …
        },
        "OfferCategory": {
            "4": {
                "id": "4",
                "name": "Contests",
                "status": "active",
                "date_created": "2015-04-21 18:32:40",
                "date_updated": "2017-08-14 15:11:29",
                "offer_count": "5"
            }
        }
    },
    "6": {
        "Offer": {
            "id": "6",
            "name": "Atomic Tilt (iPhone, Free, CA, 25MB)"
            … other Offer fields …
         },
         "OfferCategory": {
             "2": {
                 "id": "2",
                 "name": "Games",
                 "status": "active",
                 "date_created": "2015-04-21 18:32:13",
                 "date_updated": "0000-00-00 00:00:00",
                 "offer_count": "6"
             },
             "10": {
                    "id": "10",
                    "name": "Mobile",
                    "status": "active",
                    "date_created": "2015-06-12 19:06:15",
                    "date_updated": "0000-00-00 00:00:00",
                    "offer_count": "6"
                }
            }
         }
    },
    … other Offer objects …
}

If a core object has no related objects (such as an offer with no categories), the call returns an empty array.

Since contain is an array-based parameter, you can include multiple models. For instance, to retrieve category and offer group data for each offer in the same API call:

https://NETWORKID.api.hasoffers.com/Apiv3/json?NetworkToken=NETWORK_TOKEN&Target=Report&Method=getStats&contain[]=OfferGroup&contain[]=OfferCategory

View/Modify This Call in Our API Builder

When requesting multiple related models, objects for each model are returned in separate arrays. In this case, each result in the response holds three arrays: Offer, OfferCategory, and OfferGroup.

Caution about Using Contain

This feature is very useful for reducing the number of API calls used for basic tasks, but it isn’t without limitations. Calls using contain takes longer to process, and the JSON result may be significantly larger depending on how many related objects are found.

In addition, because related objects are attached to each individual core object, you may have a large degree of repeated data. If you have a category attached to 100 offers and return all 100 offers, each offer will repeat that category. This can lead to significant JSON bloat and more memory usage when parsing the JSON. We recommend you account for this when building routines around uses of contain. Additionally, use the field and filter parameters to keep your core objects as lean as possible.

To keep the contain processing as quick as possible, we don’t allow you to reduce the number of fields returned for those related objects, filter those objects by any conditionals, sort, and so on. This means you must filter values useful to you as part of parsing the JSON, such as excluding related objects with a deleted status.

Have a Question? Please contact [email protected] for technical support.