Skip to main content

Reporting API

Getting Started​

Ask your Liftoff contact for your publisher API key and API secret.

Integrate Liftoff’s Ad SDK and confirm it’s working in production following LiftoffAds’ SDK integration instructions. Once your app is successfully calling Liftoff ads in production, create a test report following the instructions below.

NOTE: Python examples assume that you have Requests installed.

Authentication​

Liftoff’s Reporting API supports HTTP basic authentication.

curl --request GET \
--user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports

Integrate Liftoff’s Ad SDK and confirm it’s working in production following LiftoffAds’ SDK integration instructions. Once your app is successfully calling Liftoff ads in production, create a test report following the instructions below.

Reporting API Setup​

Create a report request with the test=true query parameter. This ensures that you don’t run into rate limits while testing.

curl --header "Content-Type: application/json" \
--request POST \
--data '{"start_time":"2022-02-01","end_time":"2022-03-01"}' \
--user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports?test=true

Check that the request passed without errors.

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

After you generate the report without the test query parameter, the report response should contain a report id.

{
"id": "abc123",
"created_at": "2022-03-15T00:00:00Z",
"state": "queued",
"parameters": {
"start_time": "2022-02-01",
"end_time": "2022-03-01"
}
}

You can fetch the report using the following commands:

# Check the report status
curl --user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports/{ID}/status
# Download the report
curl --user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports/{ID}/data

API Structure​

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

EndpointsHTTP MethodDescription
/reportsGETLook up metadata for recently submitted reports.
/reportsPOSTGenerate a report.
/reports/{ID}/statusGETGet the status of a report.
/reports/{ID}/dataGETDownload the report in CSV or JSON format.
/{ENTITY_TYPE}GETGet entity details (apps or ad_units).

Rate Limits​

All valid endpoints are rate-limited and will return the following headers:

  • x-rate-limit-max
  • x-rate-limit-remaining
EndpointHTTP MethodHourly Rate Limit
/api/publishers/v1/reportsGET60
/api/publishers/v1/reportsPOST30
/api/publishers/v1/reports?test=truePOST60
/api/publishers/v1/reports/{ID}/statusGET1000
/api/publishers/v1/reports/{ID}/dataGET30
/api/publishers/v1/{ENTITY_TYPE}GET60

Errors​

The following errors can be returned by the API:

  • 400 "BAD REQUEST"
  • 403 "ACCESS DENIED"
  • 404 "NOT FOUND"
  • 429 "TOO MANY REQUESTS"
  • 500 "INTERNAL ERROR"
  • 503 "SERVICE UNAVAILABLE"

Error Format:

NameTypeDescription
error_typestringError type (e.g. "BAD REQUEST").
messagestringGeneral message on possible error cause.
errorsarray of strings (nullable)List of issues with request.

Sample Error:

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

Endpoints​

GET /reports​

This endpoint allows you to look up metadata for recently submitted reports.

curl --user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports

Response Format:

NameTypeDescription
idstringThe report ID.
created_attimestamp (string)Timestamp in UTC (e.g. "2022-02-01T00:00:00Z").
parametersobjectThe JSON body that was provided by the POST request.
statestring"queued", "cancelled", "completed" or "failed".

Sample Response:

[
{
"id": "abc123",
"created_at": "2022-03-15T00:00:00Z",
"state": "completed",
"parameters": {
"start_time": "2022-02-01",
"end_time": "2022-03-01"
}
}
]

POST /reports​

This endpoint allows you to generate a report. 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 compared to requests without the query parameter.

curl --header "Content-Type: application/json" \
--request POST \
--data '{"group_by":["app_id","ad_unit_id"],"start_time":"2022-02-01","end_time":"2022-03-01"}' \
--user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports

Request Format:

NameTypeDefaultDescription
app_idsarray of stringsnullOnly include specified app IDs or all.
start_timetimestamp (string)RequiredTimestamp in UTC (e.g. "2022-02-01T00:00:00Z") or date (e.g. "2022-02-01").
end_timetimestamp (string)RequiredTimestamp in UTC (e.g. "2022-02-01T00:00:00Z") or date (e.g. "2022-02-01").
group_byarray of strings["app_id"]Group by the following dimensions: "app_id", "ad_size", "country", "ad_unit_id", "is_rewarded".
formatstring"json""csv" or "json".
callback_urlstringnullA URL that will receive a POST request once the report completed or failed.
timezonestring"UTC"A TZ database name to use for date groupings.
remove_zero_rowsbooleanfalseDrop all rows whose numeric metrics are equal to 0.

Sample Response:

{
"id": "abc123",
"created_at": "2022-03-15T00:00:00Z",
"state": "queued",
"parameters": {
"group_by": ["app_id", "ad_unit_id"],
"start_time": "2022-02-01",
"end_time": "2022-03-01"
}
}

Note: The earliest date that data is available via this API is 2022-01-07. If you require data from before that time, please reach out to your Liftoff POC.

GET /reports/{ID}/status​

This endpoint allows you to fetch the status of a single report. Similar to /reports endpoint but with a higher rate limit.

curl --user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports/{ID}/status

Sample Response:

{
"id": "abc123",
"created_at": "2022-03-15T00:00:00Z",
"state": "failed",
"parameters": {
"group_by": ["app_id", "ad_unit_id"],
"start_time": "2022-02-01",
"end_time": "2022-03-01"
}
}

GET /reports/{ID}/data​

This endpoint allows you to download the completed report. The report can either be JSON/CSV depending on the format provided at report creation.

curl --user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/reports/{ID}/data

Report Row Format:

NameTypeDescription
datestringDate (YYYY-MM-dd) for the report timezone.
app_idstringID of the app showing Liftoff ads.
app_namestringApp's title (implicitly included when grouping by app_id).
platformstring"iOS" or "Android" (implicitly included when grouping by app_id).
country_codestring2 letter country code (e.g. "US").
ad_sizestringSize of the ad unit (e.g. "320x50").
ad_unit_idstringAd unit's ID.
ad_unit_namestringAd unit's display name (implicitly included when grouping by ad_unit_id).
is_rewardedbooleanWhether or not the ad unit is a rewarded ad.
impressionsintNumber of ad impressions shown.
clicksintNumber of clicks on the ads.
ctrfloatClick through rate.
revenuefloatRevenue from the ads shown (USD).
ecpmfloatEffective cost per thousand impressions (USD).
requestsintNumber of times the app requested an ad.
fill_ratefloatImpressions divided by requests.

Sample Response:

{
"columns": ["date", "app_id", "app_name", "platform", "country_code", ...],
"rows": [
["2022-02-01", "xyz456", "Sample App", "Android", "US", ...]
]
}

GET /apps​

This endpoint allows you to fetch app details.

curl --user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/apps

Response Format:

NameTypeDescription
idstringApp's ID.
namestringApp's title.
bundle_idstringApp’s bundle ID.
app_store_idstringApp’s app store ID.
platformstring"iOS" or "Android".

Sample Response:

[
{
"id": "xyz456",
"name": "Sample App",
"app_store_id": "io.liftoff.sample",
"bundle_id": "io.liftoff.sample",
"platform": "Android"
}
]

GET /ad_units​

This endpoint allows you to fetch ad unit details.

curl --user 'API_KEY:API_SECRET' \
--url https://data.liftoff.io/api/publishers/v1/ad_units

Response Format:

NameTypeDescription
idstringAd unit's ID.
namestringAd unit's display name.
app_idstringID of the app that owns the ad unit.

Sample Response:

[
{
"id": "qwerty123",
"name": "Sample Ad Unit",
"app_id": "xyz456"
}
]

Sample Workflow​

The following is a sample Python script for requesting and downloading reports.

import requests
import time

api_key = "API_KEY"
api_secret = "API_SECRET"

# Submit request to generate a new report.
report_response = requests.post(
"https://data.liftoff.io/api/publishers/v1/reports",
json={
"start_time": "2022-01-01",
"end_time": "2022-02-01",
},
auth=(api_key, api_secret),
headers={"Content-Type": "application/json"},
)
report_id = report_response.json()["id"]
print(f"Report requested. ID: {report_id}")

# Poll for report status until in a finished state.
state = ""
while state not in {"completed", "failed", "cancelled"}:
print("Waiting 30 seconds to check status...")
time.sleep(30)
status_response = requests.get(
f"https://data.liftoff.io/api/publishers/v1/reports/{report_id}/status",
auth=(api_key, api_secret),
)
state = status_response.json()["state"]
print(f"Current state: {state}")

# Download the completed report.
if state == "completed":
data_response = requests.get(
f"https://data.liftoff.io/api/publishers/v1/reports/{report_id}/data",
auth=(api_key, api_secret),
)
data_response.raise_for_status()
# Handle your raw report data here.
with open("report_response.csv", "w") as f:
f.write(data_response.text)

print("Report downloaded successfully!")