Offers API¶
Healthcheck Routes¶
Healthcheck¶
GET /healthcheck
Validates if the app is still up, including its database connection.
Success Response
Code:
200
Content:
{ "healthy": true }
Error Response It will return an internal error if it failed to connect to the database.
Code:
500
Content:
{ "healthy": false "error": "DatabaseError", "code": "OFF-000", "description": [string] // error description }
Game Routes¶
Upsert Game¶
PUT /games/:id
Updates an existing Game or insert a new Game into database. :id
must match ^[^-][a-zA-Z0-9-_]*$
.
Requires basic auth.
Payload
{ "name": [string], // required, 255 characters max "metadata": [json] // optional }
- Field Descriptions
- id: Unique ID that identifies the game
- name: Prettier game identifier to show on UI
- metadata: Any additional information one would like to access later
- Field Descriptions
Metadata
The metadata field is optional, but there are two keys that have direct impact in the
GET /available-offers
route.{ cacheMaxAge: <ttl in seconds>, allowInefficientQueries: <bool> }
- Field Descriptions
- cacheMaxAge: TTL in seconds returned in the
Cache-Control max-age
header. If not configured in the game, offers-api default value will be used. - allowInefficientQueries: If set to true the API will match offers containing filters with intervals (
gte
,lt
) and offers without any filters. This is less efficient because these queries do not make proper use of GIN index.
- cacheMaxAge: TTL in seconds returned in the
- Field Descriptions
Success Response
Code:
200
Content:
{ "gameId": [string] }
Error response
If missing or invalid arguments
Code:
422
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
It will return an error if the query on db (upsert) failed
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
List Games¶
GET /games
Lists all existing games.
Requires basic auth.
Success Response
- Code:
200
- Content:
[ { "id": [string], "name": [string], "metadata": [json] }, ... ]
- Code:
Error response
It will return an error if the query on db failed
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Offer Routes¶
Create Offer¶
POST /offers
Inserts a new Offer into the database.
Requires basic auth.
Payload
{ "name": [string], // required, 255 characters max "productId": [string], // 255 characters max, required if cost is not defined "cost": [json], // required if productId is not defined "gameId": [string], // required, matches ^[^-][a-zA-Z0-9-_]*$ "contents": [json], // required "placement": [string], // required, 255 characters max "period": { // required "every": [string], // required "max": [int] // required }, "frequency": { // required "every": [string], // required "max": [int] // required }, "trigger": { // required "from": [int], // required "to": [int] // required }, "metadata": [json], // optional "filters": [json] // optional }
- Field Descriptions
- name: Prettier game identifier to show on UI.
- productId: Identifier of the item to be bought on PlayStore or AppStore. It is required if cost is not set.
- cost: A JSON indicating the offer cost in terms of the game currency (ex.: { “gems”: 500 }). It is required if productId is not set.
- gameId: ID of the game this template was made for (must exist on Games table on DB).
- contents: What the offer provides (ex.: { “gem”: 5, “gold”: 100 }).
- metadata: Any information the Front wants to access later.
- period: Enable player to buy offer every x times, at most y times.
- every: decimal number with unit suffix, such as “300ms”, “-1.5h” or “2h45m”. Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”
- max: maximum number of times this offer can be bought by the player
- frequency: Enable player to see offer on UI x/unit of time, at most y times.
- every: decimal number with unit suffix, such as “300ms”, “-1.5h” or “2h45m”. Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”
- max: maximum number of times this offer can be seen by the player
- trigger: Time when the offer is available.
- filters: The filters for the offer, they can be of three different types for a given attribute:
- interval: the attribute must define the beginning and/or end of the interval with “geq” and “lt”, the interval includes the beginning but not the end
- equality: the attribute must define the “eq”, the value that the filter expects the attribute to be equal to, it should be a string
- difference: the attribute must define “neq”, the value that the filter expects the attribute to be different from, it should be a string
allowInefficientQueries
property set totrue
. - enabled: True if the offer is enabled.
- placement: Where the offer is shown in the UI.
- version: Offer current version.
- Field Descriptions
Success Response
Code:
200
Content:
{ "id": [uuidv4], // offer unique identifier "name": [string], "productId": [string], "cost": [json], "gameId": [string], "contents": [json], "metadata": [json], "placement": [string], "period": { "every": [string], "max": [int] }, "frequency": { "every": [string], "max": [int] }, "trigger": { "from": [int], "to": [int] }, "enabled": true, // created offer are enabled by default "version": 1, // created offer version is 1 by default "filters": [json] }
Error response
It will return an error if the request has missing or invalid arguments
Code:
422
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
It will return an error if the query on db (insert) failed
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Update Offer¶
PUT /offers/:id
Updates the offer with given id in the database.
Requires basic auth.
Payload
{ "name": [string], // required, 255 characters max "productId": [string], // 255 characters max, required if cost is not defined "cost": [json], // required is productId is not defined "gameId": [string], // required, matches ^[^-][a-zA-Z0-9-_]*$ "contents": [json], // required "placement": [string], // required, 255 characters max "period": { // required "every": [string], // required "max": [int] // required }, "frequency": { // required "every": [string], // required "max": [int] // required }, "trigger": { // required "from": [int], // required "to": [int] // required }, "metadata": [json], // optional "filters": [json] // optional }
- Field Descriptions
- name: Prettier game identifier to show on UI.
- productId: Identifier of the item to be bought on PlayStore or AppStore. It is required if cost is not set.
- cost: A JSON indicating the offer cost in terms of the game currency (ex.: { “gems”: 500 }). It is required if productId is not set.
- gameId: ID of the game this template was made for (must exist on Games table on DB).
- contents: What the offer provides (ex.: { “gem”: 5, “gold”: 100 }).
- metadata: Any information the Front wants to access later.
- period: Enable player to buy offer every x times, at most y times.
- every: decimal number with unit suffix, such as “300ms”, “-1.5h” or “2h45m”. Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”
- max: maximum number of times this offer can be bought by the player
- frequency: Enable player to see offer on UI x/unit of time, at most y times.
- every: decimal number with unit suffix, such as “300ms”, “-1.5h” or “2h45m”. Valid time units are “ns”, “us” (or “µs”), “ms”, “s”, “m”, “h”
- max: maximum number of times this offer can be seen by the player
- trigger: Time when the offer is available.
- filters: The filters for the offer, they can be of three different types for a given attribute:
- interval: the attribute must define the beginning and/or end of the interval with “geq” and “lt”, the interval includes the beginning but not the end
- equality: the attribute must define the “eq”, the value that the filter expects the attribute to be equal to, it should be a string
- difference: the attribute must define “neq”, the value that the filter expects the attribute to be different from, it should be a string
- enabled: True if the offer is enabled.
- placement: Where the offer is shown in the UI.
- version: Offer current version.
- Field Descriptions
Success Response
Code:
200
Content:
{ "id": [uuidv4], // offer unique identifier "version": [int] // updated offer version }
Error response
It will return an error if the offer with given id does not exist in the database
Code:
404
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
It will return an error if the request has missing or invalid arguments
Code:
422
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
It will return an error if the query on db (insert) failed
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Enable offer¶
PUT /offers/:id/enable?game-id=<required-game-id>
Enables an offer. :id
must be an uuidv4
.
Requires basic auth.
Success Response
Code:
200
Content:
{}
Error Response
It will return status code 404 if the offer with given ID does not exist
Code:
404
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
It will return status code 500 internal error occurred
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Disable offer template¶
PUT /offers/:id/disable?game-id=<required-game-id>
Disables an offer template. :id
must be an uuidv4
.
Requires basic auth.
Success Response
Code:
200
Content:
{}
Error Response
It will return status code 404 if the offer with given ID does not exist
Code:
404
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
It will return status code 500 internal error occurred
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
List Offers¶
GET /offers?game-id=<required-game-id>&limit=<optional-limit>&offset=<optional-offset>
- game-id: the given game id.
- limit: how many offers will be returned (the page size); default is 50.
- offset: the page number; default is 0.
Lists all game’s offers.
Requires basic auth.
Success Response
- Code:
200
- Content:
{ "offers": [ { "id": [uuidv4], // offer template unique identifier "key": [uuidv4], "name": [string], "productId": [string], "cost": [json], "gameId": [string], "contents": [json], "metadata": [json], "placement": [string], "period": { "every": [string], "max": [int] }, "frequency": { "every": [string], "max": [int] }, "trigger": { "from": [int], "to": [int] }, "enabled": [bool], "version": [int], "filters": [json] }, ... ], "pages": [int] }
- Code:
Error response
It will return an error if the query on db failed
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Offer Request Routes¶
There are the routes accessed by the offers lib.
Get Available Offers¶
GET /available-offers?player-id=<required-player-id>&game-id=<required-game-id>&<attr1>=<val1>&...
Gets the available offers for a player of a game. An offer is available if it respects the frequency (last time player saw the offer), respects the period (last time player claimed the offer), is triggered (current time is between “from” and “to”), matches the filters of the offer for the parameters sent in the query string and is enabled. The success response is a JSON where each key is a placement on the UI and the value is a list of available offers.If an attribute sent in the query string doesn’t exist in a filter it is ignored and the extra parameters for a filter are ignored if the request doesn’t send a value for them. If the filter defines an interval the query string parameter value must be a number. There is no limit in the amount of attributes that can be sent to be used in the filters.
Success Response
Code:
200
Content:
{ "placement-1": [ { "id": [uuidv4], // offer id "productId": [string], // 255 characters max "cost": [json], // offer cost as registered in the offer template "contents": [json], // offer contents as registered in the offer template "metadata": [json], // offer metadata as registered in the offer template "expireAt": [int64] // timestamp (seconds since epoch) until when the offer is valid }, ... ] "placement-2": [ ... ], ... }
Header: A max-age header is sent to indicate how long the response returned by get available offers can be cached.
Cache-Control: max-age=<seconds>
Error Response
Code:
400
, if player-id is not informedCode:
400
, if game-id is not informedCode:
500
, if server failed in any other wayContent:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Claim Offer¶
PUT /offers/claim
Claims a player’s offer. Should only be called after payment confirmation. :id
must be an uuidv4
.
Payload
{ "gameId": [string], // required, matches ^[^-][a-zA-Z0-9-_]*$ "playerId": [string], // required, 255 characters max "productId": [string], // 255 characters max, required if id is not defined "timestamp": [int64], // required, unix timestamp of the purchase "transactionId": [string], // required, unique identifier of the purchase "id": [uuidv4] // optional, the id of the offer being claimed, required if productId is not defined }
If the id of the offer being claimed is sent it will be used to find the offer, increment the claim counter and the timestamp of the last time this offer was claimed. If not, the other information present in the payload will be used to try to identify the offer that is being claimed.
Success Response
Code:
200
Content: if the player can still see the offer:
{ "contents": [json] "nextAt": [int64] // unix timestamp of the next time the offer can be shown }
if the player can no longer see the offer
{ "contents": [json] }
If the player claimed an offer that he already claimed its contents are returned but with another status code, so the caller can decide whether to give the player the offer contents or not.
Code:
409
Content: if the player can still see the offer:
{ "contents": [json] "nextAt": [int64] // unix timestamp of the next time the offer can be shown }
if the player can no longer see the offer
{ "contents": [json] }
Error Response
If a offer with id, gameId and playerId was not found in database.
Code:
404
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
If any internal error occurred.
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Offer Impressions¶
PUT /offers/:id/impressions
Updates the time when the offer was last seen by the player and increments an impressions counter. :id
must be an uuidv4
.
Payload
{ "gameId": [string], // required, matches ^[^-][a-zA-Z0-9-_]*$ "playerId": [string], // required, 255 characters max "impressionId" [uuidv4] // required, unique identifier for this impression }
The
impressionId
field is used so this request can be idempotent. If more than one request is sent with the sameimpressionId
the counter and the last impression timestamp will not be updated.Success Response
Code:
200
Content: if the player can still see the offer:
{ "nextAt": [int64] // unix timestamp of the next time the offer can be shown }
if the player can no longer see the offer
{}
Conflict Response (if the
impressionId
was already sent in a previous request):Code:
200
Content: if the player can still see the offer:
{ "nextAt": [int64] // unix timestamp of the next time the offer can be shown }
if the player can no longer see the offer:
{}
Error Response
If missing or invalid arguments.
Code:
422
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
If a offer with id, gameId and playerId was not found in database.
Code:
404
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
If any internal error occurred.
Code:
500
Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }
Get Offer Info¶
GET /offer-info?player-id=<required-player-id>&game-id=<required-game-id>&offer-id=<required-offer-id>
Gets information about a specific offer. This route can be used by a player that for some reason lost the information of a still valid offer and wants to retrieve it. The success response is a JSON object with the offer’s attributes.
Success Response
Code:
200
Content:
{ "id": [uuidv4], // offer id "productId": [string], // 255 characters max "cost": [json], // offer cost as registered in the offer template "contents": [json], // offer contents as registered in the offer template "metadata": [json], // offer metadata as registered in the offer template "expireAt": [int64] // timestamp (seconds since epoch) until when the offer is valid }
Header: A max-age header is sent to indicate how long the response returned by get offer info can be cached.
Cache-Control: max-age=<seconds>
Error Response
- Code:
400
, if player-id is not informed - Code:
400
, if game-id is not informed - Code:
400
, if offer-id is not informed
- Code:
* Code: 404
, if the offer was not found
* Code: 500
, if server failed in any other way
* Content:
{ "error": [string], // error "code": [string], // error code "description": [string] // error description }