Table of Contents

Introduction

Liftoff’s reporting API enables automated access to campaign reports with groupings and metrics of your choice. Discover insights on campaign performance by analyzing funnel metrics: impressions, clicks, installs and in-app events across different groupings (e.g. country, publisher app, ad format, creatives, etc). Perform cohort analysis through the API by specifying the look-back window relative to the install.

Getting started

  1. Contact your CSM to get API username and password emailed to you
  2. Explore the various entities associated with your account (i.e. apps, creatives, campaigns, events) via the following endpoints. (You will be prompted for a password.)

    curl --user 'username' 'https://data.liftoff.io/api/v1/apps'
    curl --user 'username' 'https://data.liftoff.io/api/v1/creatives'
    curl --user 'username' 'https://data.liftoff.io/api/v1/campaigns'
    curl --user 'username' 'https://data.liftoff.io/api/v1/events'

  3. Create a report request and validate it with a ?test=true parameter. This ensures that you don’t run into rate limits while testing.

    curl --header "Content-Type: application/json" \
    --request POST \
    --data
    '{"start_time":"2019-01-01T00:00:00Z","end_time":"2019-01-03T00:00:00Z"}' \
    --user 'username' https://data.liftoff.io/api/v1/reports?test=true

  4. Check that it passes without errors

    {"message":"Validation passed without errors."}

  5. Generate the report without the test parameter

    curl --header "Content-Type: application/json" \
    --request POST \
    --data
    '{"start_time":"2019-01-01T00:00:00Z","end_time":"2019-01-03T00:00:00Z"}' \
    --user 'username' https://data.liftoff.io/api/v1/reports

  6. The report response will contain a report id if it was successfully created

    {
    "id": "abc123",
    "created_at": "2019-04-08T21:54:35Z",
    "state": "queued",
    "parameters": {
    "start_time": "2019-01-01T00:00:00Z",
    "end_time": "2019-01-03T00:00:00Z"
    }
    }

  7. The status of the report can be polled via the following:
    1. [Recommended] Provide a callback URL with the report request. When the report is completed/failed/cancelled, a message will be sent to the provided callback URL. An OPTIONS request is made to the endpoint before report creation to verify the host is reachable.
    2. Poll the /status end point with an interval of 1 per 10 min.

    curl --user 'username'
    'https://data.liftoff.io/api/v1/reports/abc123/status'

    {
    "id": "abc123",
    "created_at": "2019-04-08T21:54:35Z",
    "state": "queued",
    "parameters": {
    "start_time": "2019-01-01T00:00:00Z",
    "end_time": "2019-01-03T00:00:00Z"
    }
    }

  8. When the report is generated, its state will be marked as “completed”, and the report data
    can be obtained at the following:

    curl --user 'username' 'https://data.liftoff.io/api/v1/reports/abc123/data'

Authentication

Liftoff’s reporting API supports HTTP Basic authentication. Here’s a quick example curl:

curl --request GET \
--url 'https://data.liftoff.io/api/v1/reports' \
--user 'username:password'

API structure

Base url

All API URLs start with https://data.liftoff.io/api/v1. Different end-points can be called by appending to the base url. All available end points are described in the table below:

End points HTTP Request Method Usage Description
/reports GET Lookup metadata around recently submitted reports
POST Generate a report
/reports/<id>/status GET Get the status of the report.
/reports/<id>/data GET Download the report in CSV or JSON
/<entity_type>

Entity type = apps, campaigns, creatives, events

GET Get the descriptions around relevant entities (apps, campaigns, creatives, events)

Throttling

All endpoints are rate-limited:

  • /api/v1/reports (GET): 60/hour
  • /api/v1/reports (POST): 30/hour
  • /api/v1/reports?test=true (POST): 60/hour
  • /api/v1/reports/<id>/status: 1000/hour
  • /api/v1/reports/<id>/data: 10/hour
  • /api/v1/<entity_type> (grouped together): 60/hour
  • Not found endpoints (404): ignored

Note: responses to any rate-limited endpoints will have x-rate-limit-max and x-rate-limit-remaining
headers

Endpoints

/reports

GET

  • Use case: look up metadata around recently submitted reports.
  • Response: Returns a list of latest 100 report ids along with the following metadata:
Name Type Description
id String ID of the report
created_at Timestamp (string) UTC timestamp.
parameters Report Parameters (object) JSON body posted during initial request populated with defaults.
state String Queued, cancelled, completed, failed.

Sample curl

curl --user 'username' 'https://data.liftoff.io/api/v1/reports'

Sample response header


content-type: application/json;charset=utf-8
x-rate-limit-max: 60
x-rate-limit-remaining: 52

Sample response body

[{
"id": "abc123",
"created_at": "2019-02-08T21:54:35Z,
"state": "completed",
"parameters": {
"app_ids": ["fgh456","xyz789"],
"start_time": "2019-02-01T21:54:35Z",
"end_time": "2019-02-02T21:54:35Z"
}
},
...
]

POST

  • Content Type: application/json
  • Query Parameters:
    • test (boolean): When the test query parameter is set, no report is generated but the request will still get validated. This also has a separate rate-limit then the requests without this query parameter
  • Body:
Name Type Description When value is not specified
app_ids Array of strings (nullable) Filters the report to only app external_ids provided All app_ids belonging to the account
campaign_ids Array of strings (nullable) Filters the report to only campaign external_ids provided. All campaign_ids belonging to the account
event_ids Array of Strings (nullable) All events belonging to the account Filters for the app event selected for optimization
start_time Timestamp (string) ISO date and time in UTC, or ISO date (with time at start of day for given timezone). Throws an exception (400), since this is a required parameter
end_time Timestamp (string) ISO date and time in UTC, or ISO date (with time at start of day for given timezone). Throws an exception (400), since this is a required parameter
group_by Array of preset string combinations Group metrics by the following combinations of entities:

  • apps, campaigns
  • apps, campaigns, ad_format
  • apps, campaigns, publisher
  • apps, campaigns, country
  • apps, campaigns, country, publisher
  • apps, campaigns, non_personalized
  • apps, campaigns, creatives
  • apps, campaigns, creatives, country
  • apps, campaigns, creatives, publisher
  • apps, campaigns, creatives, country, publisher
[apps, campaigns]
cohort_window Integer (1 - 90) (nullable) Number of days since install. If this is specified, events will be counted since the day of install Null
format String (nullable) Output format of the report. Either CSV or JSON CSV
callback_url String (nullable) Specify an endpoint to receive a status message of the report Null
timezone String (nullable) Specify a TZ database name to use for date groupings. UTC
include_repeat_events Boolean (nullable) When enabled, all instances of post-install events will be counted, instead of just first occurrences. true
remove_zero_rows Boolean (nullable) When enabled, all rows whose numeric metrics are equal to 0 will be excluded from output. false
use_two_letter_country Boolean (nullable) When enabled, reports will use the two letter country code (as opposed to the default three letter code). false

Sample request body

{
"app_ids": ["xyz123","abc123"],
"campaign_ids": ["jkl123"],
"cohort_window": 1,
"group_by": ["apps","campaigns", "creatives"]

}

  • Response:
Name Type Description
id String ID of the report
created_at Timestamp (string) UTC timestamp of report generation
parameters Report Parameters (object) JSON body posted during initial request
state String queued, cancelled, completed, failed

Sample curl

curl --header "Content-Type: application/json" \
--request POST \
--data
'{"start_time":"2019-01-01T00:00:00Z","end_time":"2019-01-03T00:00:00Z"}' \
--user 'username' https://data.liftoff.io/api/v1/reports

Sample response: header


content-type: application/json;charset=utf-8
x-rate-limit-max: 5
x-rate-limit-remaining: 0

Sample response: body

{
"id": "abc123",
"created_at": "2019-02-08T21:54:35Z",
"state": "queued",
"parameters": {
"app_ids": ["xyz123","abc123"],
"campaign_ids": ["jkl123"],
"cohort_by": "install",
"cohort_window": 1,
"group_by": ["apps","campaigns", "creatives"],
"start_time": "2019-02-01T21:54:35Z",
"end_time": "2019-02-02T21:54:35Z"

}

}

  • Exception (Bad Request):
    • 400 bad request (https required)
    • 403 unauthorized (bad credentials)
    • 429 rate limit exceeded
    • 500 internal error
Name Type Description
error_type string Error type (i.e. “BAD REQUEST”)
message string General message on possible error cause.
errors Array of Strings (Nullable) List of issues with request

Sample error: body

{
"error_type": "NOT FOUND",
"message": "Please correct the following issues with the request.",
"errors": [
"start_time should be before end_time.",
"Max allowable date range is one year."

],

}

/reports/<id>/status

This endpoint allows you to get the status of the report.

  • Request Method: GET
  • Content Type: application/json
  • Similar to /reports, but returns a single report’s status and metadata but with a higher rate limit.

Sample curl

curl --user 'username'
'https://data.liftoff.io/api/v1/reports/abc123/status'

Sample response

{
"id": "abc123",
"created_at": "2019-02-08T21:54:35Z",
"state": "failed",

}

/reports/<id>/data

This endpoint allows you to download the report

  • Request Method: GET
  • Content Type: application/json or text/csv
  • Response:
Name Type Description
date Date yyyy-MM-dd (in UTC timezone)
app_id String ID of the app that is being advertised
campaign_id String ID of the advertising campaign
creative_id String ID of the creative
country_code String (nullable) 2 letter country-code of countries in which the ad is being shown. Only available if group by (apps, campaigns, country) is selected
publisher_app_store_id String (nullable) Bundle IDs of the publisher app
publisher_name String (nullable) Display name of the publisher app
ad_format String (nullable) Format of the ad unit
spend Float Amount of budget that was spent in that time period
impressions Integer Ad impressions shown
clicks Integer Number of clicks on the ads
installs Integer Number of installs resulting from the ads
<event_name> Integer Number of events resulting from the ads. Note that an event has to be specified.
cpm Float Cost per thousand impressions. Cost is defined as ad spend.
cpc Float Cost per click. Cost is defined as ad spend.
ctr Float Click through rate. Cost is defined as ad spend.
cpi Float Cost per install. Cost is defined as ad spend.
cpa Float Cost per action. Cost is defined as ad spend. Action refers to in-app events.

Sample response (JSON)

[
"columns": ["date","app_id","campaign_id","spend","impressions", ...],
"rows": [
["2019-02-08","abc123","zxy123",123.12,12, ...],
...

]

]

Sample response (CSV)

date, app_id, campaign_id, spend, impressions, clicks, installs, cpm, cpc, ctr, cpi, cpa, Tutorial (event), Login (event)
2019-02-08, abc123, zxy123, 123.12, 123, 12, 2, 0.2, 0.2, 0.2, 0.2, 0.2, 12, 12

  • Exception (Bad Request):
    • 400 bad request (https required)
    • 403 unauthorized (bad credentials)
    • 429 rate limit exceeded
    • 500 internal error
Name Type Description
error_type string Error type (i.e. “BAD REQUEST”)
message string General message on possible error cause.

Sample error (body)

{
"error_type": "NOT FOUND",
"message": "No app found with id abc123."

}

/<entity_type>

This endpoint allows you to query the metadata around relevant entities (apps, campaigns,
creatives, events)

  • Request Method: GET
  • Content Type: application/json
  • Response: Supported entity types are apps, events, campaigns, or creatives. Returns list of entities belonging to that type.

Entity Models

Apps

Name Type Description
id String ID of the app that is being advertised
name String App title
app_store_id String Apple/Play store app ID
bundle_id String App bundle/package ID
title String App title (as appears in creatives)
platform String iOS or Android
optimization_event Event (nullable) Event selected for ML optimization

Sample curl

curl --user 'username' 'https://data.liftoff.io/api/v1/apps'

Sample response body

[
{
"id": "abc123",
"name": "Sample",
"app_store_id": "io.liftoff.sample",
"bundle_id": "io.liftoff.sample",
"title": "Sample",
"platform": "Android",
"optimization_event": {
"id": "abc123",
"name": "Tutorial"

}

},
...

]

Campaigns

Name Type Description
id String ID of the advertising campaign
app_id String ID of the app
name String Name of the advertising campaign
campaign_type String Campaign type (i. e. "user-acquisition", "reengagement", etc.)
tracker_type String Tracker type used to measure down-funnel metrics (i. e. "MMP", "SKAN")

Sample curl

curl --user 'username' 'https://data.liftoff.io/api/v1/campaigns'

Sample response body

[
{
"id": "abc123",
"app_id": "fgh456",
"name": "App - iOS - JP",
"campaign_type": "reengagement",
"tracker_type": "MMP"
},

...
]

Creatives

Name Type Description
id String ID of the ad creative
name String (nullable) Name of the ad creative
preview_url String (nullable) URL to preview the creative
width Integer (nullable) Width of the creative, in pixels
height Integer (nullable) Height of the creative, in pixels
creative_type String The technology used to render the creative: native, native_video, html, vast

Sample curl

curl --user 'username' 'https://data.liftoff.io/api/v1/creatives'

Sample response body

[
{
"id": "abc123",
"name": "320x480_sample_html",
"width": 480,
"height": 320,
"preview_url": "https://...",
"creative_type": "html"
},
...

]

Events

Name Type Description
id String ID of the in-app event
app_id String ID of the advertising app
name String Name of the event

Sample curl

curl --user 'username' 'https://data.liftoff.io/api/v1/events'

Sample response body

[
{
"id": "abc123",
"app_id": "fgh456",
"name": "Tutorial"

},
...

]