Query (GET) Endpoints

The Loyalty API endpoints broadly fall into the following categories:

CategoryNotes
Entity Resource endpointsUsed for listing Entity resources that match the Dimension criteria
Entity based queriesQueries based on a known Entity.
Member based queriesQueries based on a known Member
Cross-entity transactional QueriesTransactional queries searching across all Entities and Members
View a single resultSelecting just one record

Entity Resource Endpoints

All Entities and their raw configurations can be accessed through the Config API. However, in most cases websites and Apps only have access to the Loyalty API, and would also only want to access Entities that are relevant and also want to see CMS content translated into the right language etc.

The Loyalty API therefore provides read-only query Entity Resource endpoints for most Entity types, which removes the need for connecting to the Config API.

Typical reasons for wanting to query the Entity resources include:

  • To be able to list a set of relevant Offers, Competitions, Votes etc on a website
  • To grab the Entity's associated CMS content for display on a website
  • To get the configuration to be able to dynamically render a form on a website, for example the fields in a Form, or the questions in a Survey.
  • For data extract and integration programs, which need to find all relevant Entity identifiers to be used within the below Query and Save endpoints.

The URL syntax is simple, simply state the base folder for each type, as per these examples:

GET /loyalty/v1/{space}/competitions
GET /loyalty/v1/{space}/surveys
GET /loyalty/v1/{space}/forms
GET /loyalty/v1/{space}/ordersets
GET /loyalty/v1/{space}/offers
etc

Entity Resource Query Params

The Entity Resource query endpoints all support the following request parameters:

Request parametersDescription
dim, dim_*The dimensions for the request, for example country, promotion. This is matched against the Entities' DimensionFilter so that only the relevant Entities are returned. The Dimensions are also used to resolve and localize any CMS content associated with the Entities. The Dimensions can either be specified as one concatenated string in a single dim parameter, or broken up into separate parameters prefixed by dim_
qry, qry_*Gives the ability to add further filtering on one or more Entity attributes, for example category or name. See Query page.
page, pageSizeFor pagination. See Pagination page.
sortAllows sorting of the result based on one or more of the attributes
bypassDimensionFilterThis parameter, if set to true, bypasses the filtering by DimensionFilter. This requires special permissions and is mainly useful for portal and reporting applications and integrations
includeUnpublishedBy default, only ACTIVE (Published) Entities are considered. By setting this parameter to true, unpublished Entities are also returned. This requires special permissions.

Examples:

// List five most recent UK offers
GET .../offers?dim=country:UK&sort=-updated&pageSize=5

// Select a specific one for display
GET ...competitions?qry=name:thisOne&bypassDimensionFilter=true

Entity Resource Query Responses

All Entity Resource Queries return the same type of responses, following the following format:

{
  "content": [
    {
      // The basic Entity attributes
      "id": "The Entity's internal Id",
      "externalId": "The Entity's optional External Id",
      "name": "The Entity's unique name",
      "type": "OFFER",
      "subType": "GENERAL", // Only relevant for some types
      "category": "The optional Entity category",
      
      "dimensionMismatch": true, // Only relevant when bypassDimensionFilter=true
      "unpublished": true, // Only relevant when includeUnpublished=true
      "cmsContent": { // Any Entity CMS content is localised based on Dimensions
        "title": "Super Offer"
      },
      "created": "UTC time when the Entity was created",
      "updated": "UTC time when the Entity was last udated",
      
      "runInfo": { // Only relevant for some Entity types. May contain additional statistics
        // See API documentation
      }
    }
  ],
  // The normal pagination attributes
  "elements": 10,
  "page": 0,
  "pageSize": 100,
  "totalElement": 10,
  "totalPages": 1
}

If the result is empty the content section contains an empty array:

{
  "content": [
  ],
  // The normal pagination attributes
  "elements": 0,
  "page": 0,
  "pageSize": 100,
  "totalElement": 0,
  "totalPages": 1
}

Entity based Queries

All standard query endpoints are based on a known Entity Lookup Id (a specific Survey, a specific Wallet, a specific List etc).

The URL syntax just adds the Entity Lookup Id and one word after the above Entity Queries, as per these examples:

GET /loyalty/v1/{space}/competitions/{lookupId}/entries
GET /loyalty/v1/{space}/surveys/{lookupId}/members
GET /loyalty/v1/{space}/forms/{lookupId}/members
GET /loyalty/v1/{space}/ordersets/{lookupId}/orders
GET /loyalty/v1/{space}/offers/{lookupId}/instances
GET /loyalty/v1/{space}/games/{lookupId}/plays
etc

📘

The Entity Lookup Id can be one of:

  • The Entity's internal Id. All in lowercase
  • The Entity's External Id, if exists. Prefixed with the $ sign
  • The Entity's unique name, mixed case

Query Params

Some endpoints may support additional parameters, but the following request parameters are supported by all query endpoints:

Request parametersDescription
dim, dim_*The dimensions for the request, for example country, promotion. This is matched against the specified Entity Lookup Id's DimensionFilter, and an error is thrown if the dim field doesn't match. The Dimensions can either be specified as one concatenated string in a single dim parameter, or broken up into separate parameters prefixed by dim_
page, pageSizeFor pagination. See Pagination page.
sortAllows sorting of the result based on one or more of the result attributes. See Pagination page.
countTotalsIf set to true, counts and returns information about the total number of rows and pages that match the query. Note that whilst this may be useful to display in user interfaces, this can be a very heavy operation on large datasets. This parameter is therefore false by default. Use with caution.
bypassDimensionFilterThis parameter, if set to true, bypasses the filtering by DimensionFilter. This requires special permissions and is mainly useful for portal and reporting applications and integrations
includeUnpublishedBy default, only ACTIVE (Published) Entities are considered. By setting this parameter to true, unpublished Entities are also returned. This requires special permissions.

🚧

Note about Dimensions

The dim and the bypassDimensionFilter parameters only relate to the Entity Lookup Id specified in the URL. They are not used to validate the actual transactional data returned.

It is therefore perfectly possible that the returned data has completely different dimensions to the ones passed in the dim parameter.

Use the dimf parameter (below) if you want to filter the transactional result based on it's Dimensions.

In addition, many Query endpoints support the following query request parameters:

Request parametersDescription
qry, qry_*Gives the ability to add further filtering on one or more result attributes. The attributes that can be used are specific to each endpoint.
memberOne or more comma-separated Member Lookup Ids. Limits the result to rows relevant for one or a set of Members. The Member Lookup Id can be any of Member Id, External Id, email etc, but if more than one value then all Lookup Ids have to be of the same type.
dimf, dimf_*dimf is a DimensionFilter parameter which can be used when querying transactional data that contain Dimensions information. The dimf attribute supports wildcards. See DimensionFilter page. As with the dim parameter the dimf parameter can either contain a concatenated set of dimensions, or they can be specified as separate query parameters prefixed with dimf_

Examples:

// List all UK based partner site orders
GET .../orders/Partner/orders?dim=country:US;channel=web&dimf=country:UK

// List all current and saved games
GET ...games/StarWars/plays?qry_state=SAVED,PLAYING&dim=country:US

Query Responses

All Entity-based queries return the same pagination-based result format:

{
  "content": [
    // This is a list of all returned rows.
    // The content depends on the Entity type
  ],
  // The normal pagination attributes
  "elements": 10,
  "page": 0,
  "pageSize": 100,
  "totalElement": 10, // Only if countTotals=true
  "totalPages": 1 // Only if countTotals=true
}

If the result is empty the content section contains an empty array:

{
  "content": [
  ],
  "elements": 0,
  "page": 0,
  "pageSize": 100
}

However if the lookupId specified in the url doesn't exist, has the wrong state or can't be accessed due to Dimensions, an InvalidEntity error is returned.

Member based Queries

The standard query functionality (above) is powerful and flexible for querying large data sets, but is based on passing in a specific Entity Lookup Id. But what if we for example want to find all Competition entries for a specific Member? Or if we want to find all offers by unlocked or available to a Member? Or all games a Member has played?

This is where Member based queries come in. They take a Member Lookup Id instead of an Entity Lookup Id, and then searches the all transactional data based on that Member, across all Entities.

The URL syntax looks as follows:

GET /loyalty/v1/{space}/members/{memberLookupId}/competitions
GET /loyalty/v1/{space}/members/{memberLookupId}/surveys
GET /loyalty/v1/{space}/members/{memberLookupId}/orders
GET /loyalty/v1/{space}/members/{memberLookupId}/offers
GET /loyalty/v1/{space}/members/{memberLookupId}/games
etc

The purpose of Member based Queries is generally very different to the purpose of Entity based queries. For example:

  • Member based queries only relate to a single Member and therefore don't tend to return many rows. Pagination is therefore not as important
  • Member based queries are often used for customer care purposes/screens, where we need to display all information across all Dimensions, and including historical data and interactions. Member based queries therefore don't take or filter by a dim parameter, and they return rows even for entities that may since have been inactivated or archived.

For the above reasons, the Member based queries don't take any standard query parameters for filtering the result.

The format of the result of Member based queries is the same as for Entity based queries. However if the Member specified in the url doesn't exist or has been deleted, an InvalidMember error is returned.

Cross-Entity Transactional Queries

Whilst almost all queries are either Entity based or Member based, there are a few query endpoints which break this pattern. The best example is perhaps when querying Activities.

The endpoints look like this:

GET /loyalty/v1/{space}/activities
GET /loyalty/v1/{space}/relationships
etc

These query endpoints can return vast amounts of data, and it's therefore important to limit the result as much as possible using query parameters. The common ones usually supported are:

Request parametersDescription
memberOne or more comma-separated Member Lookup Ids. Limits the result to rows relevant for one or a set of Members. The Member Lookup Id can be any of Member Id, External Id, email etc, but if more than one value then all Lookup Ids have to be of the same type.
entityOne or more comma-separated Entity Lookup Ids. Limits the result to rows relevant for one or a set of Entities. The Entity Lookup Id can be any of Entity Id, External Id, name, but if more than one value then all Lookup Ids have to be of the same type.
qry, qry_*Gives the ability to filter by one or more result attributes. The attributes that can be used are specific to each endpoint.
dimf, dimf_*Gives the ability to filter by one or more Dimension values stored with the data.
page, pageSizeFor pagination. See Pagination page.
sortAllows sorting of the result based on one or more of the result attributes. See Pagination page.
countTotalsIf set to true, counts and returns information about the total number of rows and pages that match the query. Note that whilst this may be useful to display in user interfaces, this can be a very heavy operation on large datasets. This parameter is therefore false by default. Use with caution.

As with Member based queries, the cross-entity queries don't limit the result based on Entities' Dimension Filters or states, so even data relating to archived Entities are returned.

The result of cross-Entity queries have the same format as Entity-based Queries.

View a single result

It's possible to just populate a single piece of content (rather than doing paginated queries). To do this you need to know the exact identifier of the content piece.

NEON generally doesn't have global unique identifiers for the content. In most cases the content is identified by the Entity Lookup Id and Member Lookup Id.

Examples include:

  • Votes. There can only be one answer per Vote and Member. The vote answer is therefore identified by passing in the Vote Entity and Member Lookup Ids.
  • Orders. The order number series is unique within an Order Set (allowing multiple partner orders to be tracked without the risk of Order numbers clashing between partners). The Orders are therefore identified by Order Set Lookup Id and Order number.
  • Games. Each Game play is identified by the Game Lookup Id and a Game play instance number generated each time a Game play is saved.

The above examples have in common that the Entity Lookup Id is required, and the standard Dimension checks are applied. The following standard query attributes are therefore supported:

Request parametersDescription
dim, dim_*The dimensions for the request, for example country, promotion. This is matched against the specified Entity Lookup Id's DimensionFilter, and an error is thrown if the dim field doesn't match. The Dimensions can either be specified as one concatenated string in a single dim parameter, or broken up into separate parameters prefixed by dim_
bypassDimensionFilterThis parameter, if set to true, bypasses the filtering by DimensionFilter. This requires special permissions and is mainly useful for portal and reporting applications and integrations
includeUnpublishedBy default, only ACTIVE (Published) Entities are considered. By setting this parameter to true, unpublished Entities are also returned. This requires special permissions.

To look up an individual piece of content we use the format of Entity-based queries and just add the missing key at the end, as per these examples:

GET /loyalty/v1/{space}/competitions/{lookupId}/entries/{entryId}
GET /loyalty/v1/{space}/surveys/{lookupId}/members/{memberLookupId}
GET /loyalty/v1/{space}/forms/{lookupId}/members/{memberLookupId}
GET /loyalty/v1/{space}/ordersets/{lookupId}/orders/{orderNo}
GET /loyalty/v1/{space}/offers/{lookupId}/instances/{instanceNo}
GET /loyalty/v1/{space}/games/{lookupId}/plays/{playId}
etc

Note that for Sheets which may have multiple composite keys, the keys are concatenated by comma, for example

// Single key
GET /loyalty/v1/{space}/sheets/{lookupId}/rows/{key}

// Composite key
GET /loyalty/v1/{space}/sheets/{lookupId}/rows/{key1},{key2},{key3}

// Form Member Sheets, the first key is the memberId which can optionally be separated out
GET /loyalty/v1/{space}/sheets/{lookupId}/rows/{key2},{key3}?member={memberLookupId}

The result of single result queries just contain the resource

{
  // The content attributes...
}

If the row can't be found one of the following errors is returned (see Error section):

  • InvalidEntity. If the entityLookupId in the urls can't be found or has the wrong status
  • DimensionFilter. If the Entity Lookup Id in the url can be found but the Dimension Filter prevents access
  • InvalidMember. If the MemberLookupId in the url can't be found or is deleted
  • RowNotFound. For any other reason