The Authenticated Digital Bidstream Optimizer is driven by a RESTful API. The following document explains the basic concepts behind Optimizer, and how to use the Optimizer API.
Your account with Authenticated is needed to access any part of the Authenticated API. The most important thing to know about your account is how to get a token. A user must first log in to access the API and obtain a token to be used for all subsequent requests. The Optimizer API uses the JSON web tokens (JWT) methodology.
To obtain a JSON web token, you must send your username and password as follows:
curl -v -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-d '{ "email": "<email>", "password": "<password>" }' \
'https://optimizer.authenticated.digital/api/login'
Note: Change <email>
and <password>
above with the email account and password associated with your Optimizer user account.
The response will look similar to this:
HTTP/1.1 200 OK authorization: Bearer eyJhbGciOiABC6IkpXVCJ9.eyJhdWQiOiJVc2VyOjEiLCJleHAiOjE0NzDEFXNzIjoiUnRiUHJveHlXZWIiLCJqdGkimqIlMmEtOGIzNi1lNmIzNjYxZmY3ZjciLCJwZW0iOnt9LCJzdWIKyOjEiLCJ0eXAiOiJ0b2tlbiJ9.vIUenWRk9Zu9weBLhfbvcc9pgAXKsw-8ltdkNclfpDJiTR_DvaunI_ipEI5zx4hTDCDpeVT5olFQ cache-control: max-age=0, private, must-revalidate content-type: application/json; charset=utf-8 date: Fri, 09 Sep 2016 13:56:02 GMT server: Cowboy x-expires: 1476021363 x-request-id: b2avdie34gqnls4ubvahab18tg474 Content-Length: 323 Connection: keep-alive * Connection #0 to host optimizer.authenticated.digital left intact {"data":{"jwt":"eyJhbGciOiABC6IkpXVCJ9.eyJhdWQiOiJVc2VyOjEiLCJleHAiOjE0NzDEFXNzIjoiUnRiUHJveHlXZWIiLCJqdGkimqIlMmEtOGIzNi1lNmIzNjYxZmY3ZjciLCJwZW0iOnt9LCJzdWIKyOjEiLCJ0eXAiOiJ0b2tlbiJ9.vIUenWRk9Zu9weBLhfbvcc9pgAXKsw-8ltdkNclfpDJiTR_DvaunI_ipEI5zx4hTDCDpeVT5olFQ","exp":1476021363}}
Note the authorization
header and the data/jwt
node in the JSON contain the same string of characters. These characters are a token which will be used for all subsequent requests to the API. Copy this token down, and replace in the authorization
header for all other requests, as follows:
curl 'https://optimizer.authenticated.digital/api/filters' \
-H 'Authorization: Bearer eyJhbGciOiABC6IkpXVCJ9.eyJhdWQiOiJVc2VyOjEiLCJleHAiOjE0NzDEFXNzIjoiUnRiUHJveHlXZWIiLCJqdGkimqIlMmEtOGIzNi1lNmIzNjYxZmY3ZjciLCJwZW0iOnt9LCJzdWIKyOjEiLCJ0eXAiOiJ0b2tlbiJ9.vIUenWRk9Zu9weBLhfbvcc9pgAXKsw-8ltdkNclfpDJiTR_DvaunI_ipEI5zx4hTDCDpeVT5olFQ
Remember to replace the above (non-working) token above with your token!
Optimizer accepts inbound bidstreams from various suppliers, filters the bidstreams, and then passes the bid requests on to your bidder. The Authenticated streams
endpoint refers to a bidstream from a supplier. Because suppliers can have more than one bidstream, they are grouped by a suppliers
endpoint.
To view all of the streams that are configured for your account, use the streams
endpoint:
curl 'https://optimizer.authenticated.digital/api/streams' \
-H 'Authorization: Bearer <enter your token here>'
You will get a JSON response similar to the following:
{
"data":[
{
"supplier":{
"name":"OpenX",
"id":1
},
"seat_id":"123",
"id":3,
"endpoint_path":"/42eaaaaaaa4eeabeeeecc77836adde6/bids",
"customer_endpoint":"http://bidder.customer.com/bids",
"client_id":"42eaaaaaaa4eeabeeeecc77836adde6"
},
{
"supplier":{
"name":"OpenX",
"id":1
},
"seat_id":"123",
"id":4,
"endpoint_path":"/42eaaabbbbdd444dde6/bids",
"customer_endpoint":"http://bidder.customer.com/bids",
"client_id":"42eaaabbbbdd444dde6"
}
]
}
Here is a description of the fields in the streams
endpoint:
FIELD | TYPE | DESCRIPTION |
---|---|---|
id |
integer | The autogenerated internal ID for the stream |
client_id |
string | The unique ID of the bidstream that Optimizer will use to identify the customer/stream |
supplier.name |
string | The name of the SSP / Exchange / Publisher that provides a raw input bidstream |
supplier.id |
integer | Autogenerated ID for this supplier |
seat_id |
string | The seat ID that the bidder uses to identify their bids to a supplier bidstream |
endpoint_path |
string | The path of the URL for the Optimizer raw bidstream endpoint |
customer_endpoint |
string | The URL of the upstream bidder that Optimizer will pass filtered bids to |
Note that streams are organized in hierarchical fashion by supplier. If you subscribe to multiple bidstreams more than one stream will share the same suppler (like the example above).
To get a list of suppliers, use the suppliers
endpoint:
curl 'https://optimizer.authenticated.digital/api/suppliers' \
-H 'Authorization: Bearer <enter your token here>'
You will get a response similar to the following:
{
"data":[
{
"name":"OpenX",
"id":1
},
{
"name":"Opera",
"id":2
}
]
}
Here is a description of the fields in the suppliers
endpoint:
FIELD | TYPE | DESCRIPTION |
---|---|---|
id |
integer | Autogenerated ID for this supplier |
name |
string | The name of the SSP / Exchange / Publisher that provides a raw input bidstream |
Customer settings can be viewed and updated. This includes a global qps as well as rules around how the customer will receive bids and wins.
FIELD | TYPE | DESCRIPTION |
---|---|---|
id |
integer | Autogenerated ID for the customer record |
name |
string | The customer name |
slug |
string | Human readable unique identifier for customer |
qps |
integer | Designated maximum qps |
redirect_wins |
boolean | If true, a 302 code with upstream win url is responsed on a win notice |
inject_tag |
boolean | If true, injects the authenticated digital tag in customer creative |
keep_nurl |
boolean | If true, keeps customer bidder nurl instead of proxying through optimizer |
To get customer information
curl 'https://optimizer.authenticated.digital/api/customer' \
-H 'Authorization: Bearer <enter your token here>'
Customer information can be updated for the following fields qps
, redirect_wins
, inject_tag
, keep_nurl
.
curl -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Authorization: Bearer <your jwt token>' -d '{ "customer": { "qps": 1000,"redirect_wins": false, "inject_tag": true, "keep_nurl": false }}' 'http://localhost:4000/api/customer'
A core feature of Optimizer is to use filters to tune the traffic that is sent to your bidder. By default, a filter will be added to all new accounts. Filters are highly configurable, and while it takes a bit of time to understand why they work the way they do, they are extremely powerful.
A single filter is a simple set of instructions that control whether or not a bid request is blocked (e.g. a 204 HTTP response is sent back) or passed through to the upstream bidder. A filter takes the shape of a simple JSON object, like the following example:
{
"id": 1,
"field_type": "size",
"operator": "equals",
"list": ["300x250","320x100","320x50"],
"filter_type": "white"
}
The filter attributes are defined below.
ATTRIBUTE | DESCRIPTION | TYPE | VALUES | NOTES |
---|---|---|---|---|
id |
The ID of the filter, which is auto-generated when the filter is created. When filters are chained together in hierarical fashion, this ID is used as the reference in the parent_filter_id field. |
integer | ||
field_type |
The type of field. There are different field types, which generally represent a) bid request fields; b) enriched data from the fields (such as the recycled field from Authenticated); c) composites (and and or ) which then chain filters together. |
string | user , country , size , stream , supplier , authed , and , or |
More information about field types below |
operator |
The operation to perform on the filter. For example, the equals operator checks to see if one of the values in the list is the same as the specified field. |
string | lessthan , equals , greaterthan |
|
list |
A JSON array list of values from which to apply the operator. | array | For list filters only | |
threshold |
The threshold score value for threshold filter types |
float | For threshold filters only | |
filter_type |
The filter type. | string | white , black , boolean , threshold |
More information about filter types below |
parent_filter_id |
The parent filter which connects this filter to its siblings | integer | Parent filter can only have filter_type of boolean |
FIELD TYPE | VALID FILTER TYPES | DATA ELEMENT | DESCRIPTION |
---|---|---|---|
country |
white , black |
bidrequest.device.geo.country |
Country where the visitor is located from the bid request - 2 char uppercase ISO code |
user |
white , black |
bidrequest.user.id |
The ID of the visitor's device |
stream |
white , black |
stream.id |
The Authenticated Digital ID of the bidstream |
supplier |
white , black |
supplier.id |
The ID of the supplier from the bid request |
size |
white , black |
bidrequest.imp.banner.[wxh] |
The size of the impression (e.g. 300x250 ) |
authed |
threshold |
bidrequest.ext.authenticated.authed.score |
The score value of the authed model from Authenticated |
and |
boolean |
Combines child filters (that have a parent_filter_id of this filter's ID) and evaluates using AND boolean logic. |
|
or |
boolean |
Combines child filters (that have a parent_filter_id of this filter's ID) and evaluates using OR boolean logic. |
OPERATOR | DESCRIPTION |
---|---|
lessthan |
A model's predicted score is less than the specified threshold |
equals |
A field value is the same as an item in the list array |
greaterthan |
A model's predicted score is greater than the specified threshold |
FILTER TYPE | DESCRIPTION |
---|---|
white |
A white list - the field must exist in the list array |
black |
A black list - field must not exist in the list array |
threshold |
A threshold contains a prediction model score to filter quality and commercial traffic |
boolean |
A filter that connects other filters together, and evaluates all filters according to boolean logic (e.g. AND, OR) |
The following filter passes through bids with creatives of the specified sizes (300x250
, 320x100
, 320x50
):
{
"id": 2,
"field_type": "size",
"operator": "equals",
"list": ["300x250","320x100","320x50"],
"filter_type": "white"
}
The following filter passes thorugh bids with a quality threshold of at least 0.5:
{
"id": 3,
"field_type": "authed",
"operator": "greaterthan",
"threshold": 0.5,
"filter_type": "threshold"
}
Filters can be combined, to contain more sophisticated and powerful logic. For example, the creative size filter and the quality filter above can be combined if you want to only show bid inventory with the three creative sizes with a quality threshold:
[{
"id": 2,
"field_type": "size",
"operator": "equals",
"list": ["300x250","320x100","320x50"],
"filter_type": "white",
"parent_id": 4
},
{
"id": 3,
"field_type": "authed",
"operator": "greaterthan",
"threshold": 0.5,
"filter_type": "threshold",
"parent_id": 4
},
{
"id": 4,
"field_type": "and",
"filter_type": "boolean"
}]
Filters can continue to be constructed in a hierarchical fashion. For example, if you only want the combined filter above to run with UK traffic, and with the other traffic you want to run a high quality threshold:
First, update or create the top level filter which will be an "OR" filter, meaning that there are more than one scenarios that could be run:
[{
"id": 1,
"field_type": "or",
"filter_type": "boolean"
}]
Next, use the filter criteria created in the "Combining Filters" section above and add the UK geotargeting filter:
[{
"id": 2,
"field_type": "size",
"operator": "equals",
"list": ["300x250","320x100","320x50"],
"filter_type": "white",
"parent_id": 4
},
{
"id": 3,
"field_type": "authed",
"operator": "greaterthan",
"threshold": 0.5,
"filter_type": "threshold",
"parent_id": 4
},
{
"id": 4,
"field_type": "and",
"filter_type": "boolean",
"parent_id": 1
},
{
"id": 5,
"field_type": "country",
"operator": "equals",
"list": ["UK"],
"filter_type": "white",
"parent_id": 4
}]
Note the parent IDs of the filters connect the AND filter, except for the AND filter itself, which is connected to the top-level OR filter.
At this point, you have configured a filter which has the following functionality in boolean logic:
IF ANY OF THE STATEMENTS IS TRUE:
IF ALL OF THE STATMENTS IS TRUE:
CREATIVE SIZE IS EITHER 300x250,320x100 OR 320x50
QUALITY THRESHOLD IS AT LEAST 0.5
COUNTRY IS UK
Finally, create the filter for the other traffic:
[{
"id": 6,
"field_type": "authed",
"operator": "greaterthan",
"threshold": 0.7,
"filter_type": "threshold",
"parent_id": 8
},
{
"id": 7,
"field_type": "country",
"operator": "equals",
"list": ["UK"],
"filter_type": "black",
"parent_id": 8
},
{
"id": 8,
"field_type": "and",
"filter_type": "boolean",
"parent_id": 1
}]
Now you have the filtering scheme you want! The boolean logic is now as follows:
IF ANY OF THE STATEMENTS IS TRUE:
IF ALL OF THE STATMENTS IS TRUE:
CREATIVE SIZE IS EITHER 300x250,320x100 OR 320x50
QUALITY THRESHOLD IS AT LEAST 0.5
COUNTRY IS UK
IF ALL OF THE STATMENTS IS TRUE:
QUALITY THRESHOLD IS AT LEAST 0.7
COUNTRY IS NOT UK
In general, filters are set up and not changed often - sort of like firewall rules. However, the lists referenced by filters change often - sometimes multiple times per day. Bidstream Optimizer is engineered for this use case.
For example, if a bidder only wants to see a bid if it comes from a pool of device IDs that they have verified, they could update the list as follows:
To create a device ID filter:
curl -X POST -H 'Authorization: Bearer <enter your token here>' -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ "filter": { "operator": "equals","list": [4] }}' 'http://localhost:4000/api/filters'
A response would be as follows:
To update this filter:
curl -X PUT -H 'Authorization: Bearer <enter your token here>' -H 'Content-Type: application/json' -H 'Accept: application/json' -d '{ "filter": { "operator": "equals","list": [4] }}' 'http://localhost:4000/api/filters/36'
A successful response contains the tree based list of your filters
{
"data": {
"id": 24,
"filters": [{
"id": 27,
"filters": [{
"operator": "equals",
"list": ["4", "5", "6"],
"id": 29,
"filter_type": "black",
"field_type": "user"
}, {
"operator": "equals",
"list": ["5x5"],
"id": 30,
"filter_type": "black",
"field_type": "size"
}],
"filter_type": "boolean",
"field_type": "or"
}, {
"operator": "equals",
"list": ["1", "2", "3"],
"id": 28,
"filter_type": "black",
"field_type": "user"
}, {
"id": 32,
"filters": [{
"id": 33,
"filters": [{
"operator": "equals",
"list": "List too long to return: 5000000",
"id": 31,
"filter_type": "white",
"field_type": "user"
}, {
"operator": "equals",
"list": [3],
"id": 35,
"filter_type": "white",
"field_type": "stream"
}],
"filter_type": "boolean",
"field_type": "and"
}, {
"operator": "equals",
"list": [3],
"id": 36,
"filter_type": "black",
"field_type": "stream"
}],
"filter_type": "boolean",
"field_type": "or"
}],
"filter_type": "boolean",
"field_type": "and"
}
}
This would update filter id 36
curl -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Authorization: Bearer <your jwt token>' -d '{ "filter": { "operator": "equals","list": [4] }}' 'http://localhost:4000/api/filters/36'
A successful response will return the updated filter
{
"data": {
"operator": "equals",
"list": [
3
],
"id": 36,
"filter_type": "black",
"field_type": "stream"
}
}
The following example is a filter that allows different users for different countries using or and and filters.
It also limits the second country set to just one size:
{
"filter_type": "boolean",
"field_type": "and",
"filters": [{
"filter_type": "boolean",
"field_type": "and",
"filters":[{
"filter_type": "white",
"field_type": "country",
"operator": "equals",
"list":["US","CA"]
},
{
"filter_type": "white",
"field_type": "user",
"operator": "equals",
"list":["user1","user2"]
}
]
},
{
"filter_type": "boolean",
"field_type": "and",
"filters":[{
"filter_type": "white",
"field_type": "country",
"operator": "equals",
"list":["GB","IE","DE"]
},
{
"filter_type": "white",
"field_type": "size",
"operator": "equals",
"list":["300x250"]
},
{
"filter_type": "white",
"field_type": "user",
"operator": "equals",
"list":["user3","user4"]
}
]
}
],
"filter_type": "boolean",
"field_type": "or"
}]
}
Here is how this would be created when no filters are set.
First get your existing filters there should only be one.
curl -H 'Authorization: Bearer <your jwt token> 'http://localhost:4000/api/filters'
Take the id of the topmost filter. Then create the or filter.
curl -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Authorization: Bearer <your jwt token>' -d '{ "filter": { "filter_type": "boolean", "field_type": "or", "parent_filter_id": <parent_filter_id> }}' 'http://localhost:4000/api/filters'
The filter should return with the generated filter id.
The and filters can be added in bulk.
curl -X POST 'https://optimizer.authenticated.digital/api/filters' \
-d '{ "filters": [
{ "filter_type": "boolean", "field_type": "and", "parent_filter_id": 1 },
{ "filter_type": "boolean", "field_type": "and", "parent_filter_id": 1 },
{ "filter_type": "boolean", "field_type": "and", "parent_filter_id": 1 }
]}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <your jwt token>'
The corresponding list filters can now be added in bulk as well
curl -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Authorization: Bearer <your jwt token>' -d '{ "filters": [{"filter_type":"white","field_type":"country","operator":"equals","list":["US","CA"],"parent_filter_id":"<first_and_filter_id>"},{"filter_type":"white","field_type":"user","operator":"equals","list":["user1","user2"],"parent_filter_id":"<first_and_filter_id>"},{"filter_type":"white","field_type":"country","operator":"equals","list":["GB","IE","DE"],"parent_filter_id":"<second_and_filter_id>"},{"filter_type":"white","field_type":"size","operator":"equals","list":["300x250"],"parent_filter_id":"<second_and_filter_id>"},{"filter_type":"white","field_type":"user","operator":"equals","list":["user3","user4"],"parent_filter_id":"<second_and_filter_id>"}] }' 'http://localhost:4000/api/filters'