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/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 pointsHTTP Request MethodUsage Description
/reportsGETLookup metadata around recently submitted reports
POSTGenerate a report
/reports/<id>/statusGETGet the status of the report.
/reports/<id>/dataGETDownload the report in CSV or JSON
/<entity_type>

Entity type = apps, campaigns, creatives, events

GETGet 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:
NameTypeDescription
idStringID of the report
created_atTimestamp (string)UTC timestamp.
parametersReport Parameters (object)JSON body posted during initial request populated with defaults.
stateStringQueued, 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:
NameTypeDescriptionWhen value is not specified
app_idsArray of strings (nullable)Filters the report to only app external_ids providedAll app_ids belonging to the account
campaign_idsArray of strings (nullable)Filters the report to only campaign external_ids provided.All campaign_ids belonging to the account
event_idsArray of Strings (nullable)All events belonging to the accountFilters for the app event selected for optimization
start_timeTimestamp (string)UTC timestamp.Throws an exception (400), since this is a required parameter
end_timeTimestamp (string)UTC timestamp.Throws an exception (400), since this is a required parameter
group_byArray of preset string combinationsGroup 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, creatives
  • apps, campaigns, creatives, country
  • apps, campaigns, creatives, publisher
  • apps, campaigns, creatives, country, publisher
[apps, campaigns]
cohort_windowInteger (1 – 90) (nullable)Number of days since install. If this is specified, events will be counted since the day of installNull
formatString (nullable)Output format of the report. Either CSV or JSONCSV
callback_urlString (nullable)Specify an endpoint to receive a status message of the reportNull
timezoneString (nullable)Specify a TZ database name to use for date groupings.UTC
include_repeat_eventsBoolean (nullable)When enabled, all instances of post-install events will be counted, instead of just first occurrences.true
remove_zero_rowsBoolean (nullable)When enabled, all rows whose numeric metrics are equal to 0 will be excluded from output.false
use_two_letter_countryBoolean (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:
NameTypeDescription
idStringID of the report
created_atTimestamp (string)UTC timestamp of report generation
parametersReport Parameters (object)JSON body posted during initial request
stateStringqueued, 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
NameTypeDescription
error_typestringError type (i.e. “BAD REQUEST”)
messagestringGeneral message on possible error cause.
errorsArray 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:
NameTypeDescription
dateDateyyyy-MM-dd (in UTC timezone)
app_idStringID of the app that is being advertised
campaign_idStringID of the advertising campaign
creative_idStringID of the creative
country_codeString (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_idString (nullable)Bundle IDs of the publisher app
publisher_nameString (nullable)Display name of the publisher app
ad_formatString (nullable)Format of the ad unit
spendFloatAmount of budget that was spent in that time period
impressionsIntegerAd impressions shown
clicksIntegerNumber of clicks on the ads
installsIntegerNumber of installs resulting from the ads
<event_name>IntegerNumber of events resulting from the ads. Note that an event has to be specified.
cpmFloatCost per thousand impressions. Cost is defined as ad spend.
cpcFloatCost per click. Cost is defined as ad spend.
ctrFloatClick through rate. Cost is defined as ad spend.
cpiFloatCost per install. Cost is defined as ad spend.
cpaFloatCost 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
NameTypeDescription
error_typestringError type (i.e. “BAD REQUEST”)
messagestringGeneral 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

NameTypeDescription
idStringID of the app that is being advertised
nameStringApp title
app_store_idStringApple/Play store app ID
bundle_idStringApp bundle/package ID
titleStringApp title (as appears in creatives)
platformStringiOS or Android
optimization_eventEvent (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

NameTypeDescription
idStringID of the advertising campaign
app_idStringID of the app
nameStringName of the advertising campaign
campaign_typeStringType of campaign (UA: User acquisition, RE: Re-engagement campaigns)

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”

},

]

Creatives

NameTypeDescription
idStringID of the ad creative
nameString (nullable)Name of the ad creative
preview_urlString (nullable)URL to preview the creative
widthInteger (nullable)Width of the creative, in pixels
heightInteger (nullable)Height of the creative, in pixels
creative_typeStringThe 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

NameTypeDescription
idStringID of the in-app event
app_idStringID of the advertising app
nameStringName 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”

},

]