The Dailymotion reporting API provides the ability to build custom reports based on aggregated performance measurements across a set of dimensions and filters. The flexible interface allows you to ingest data at your convenience and in the format you need. The reporting API is only available to our verified partners.
The Dailymotion reporting API accepts dimensions, filters, and metrics as parameters:
Refer to these tables for detailed information: Dimensions, filters, and metrics and Compatibility matrix.
Key points to note before you begin:
You can follow these steps to generate a report. We've included code samples in each step for reference, but you'll find complete code samples (in BASH (with cURL), PHP, and Python) at the end of this section.
Pass in the Dailymotion login credentials along with the API key and secret generated in step 1.
Use this endpoint to request the access token:
POST https://graphql.api.dailymotion.com/oauth/token
Example of request (using cURL):
curl -s -X POST https://graphql.api.dailymotion.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=<YOUR_API_KEY>&client_secret=<YOUR_API_SECRET>&username=<YOUR_USERNAME>&password=<YOUR_PASSWORD>&grant_type=password&version=2"
Example of response body:
{
"access_token": "eyJ0eXAiOiJK...jO67fL658U",
"expires_in": 36000,
"refresh_token": "eyJ0eXAiOiJK...LFPA1uDBD0",
"scope": "",
"token_type": "Bearer"
}
Use this endpoint for all subsequent API calls:
POST https://graphql.api.dailymotion.com
Example of request header:
Content-Type: application/json
Authorization: Bearer <ACCESS_TOKEN>
Example of request body:
{
"query": "mutation ($input: AskPartnerReportFileInput!) {
askPartnerReportFile(input: $input) {
reportFile {
reportToken
}
}
}",
"variables": {
"input": {
"metrics": ["VIEWS"],
"dimensions": ["DAY", "VIDEO_TITLE"],
"filters": {
"videoOwnerChannelSlug": "<your_channel_slug>"
},
"startDate": "2018-07-01",
"endDate": "2018-07-04"
}
}
}
<ACCESS_TOKEN> with the one generated from authentication request. Table for guidance.
Example of response body:
{
"data": {
"askPartnerReportFile": {
"reportFile" {
"reportToken":"eyJ0eX...sAG7__nZ7w"
}
}
}
}
It can take up to two hours to generate the report once a job has been created. To check the status:
POST https://graphql.api.dailymotion.com
Example of request header:
Content-Type: application/json
Authorization: Bearer <ACCESS_TOKEN>
Example of request body:
{
"query": "query PartnerGetReportFile($reportToken: String!) {
partner {
reportFile(reportToken: $reportToken) {
status
downloadLinks {
edges {
node {
link
}
}
}
}
}
}",
"variables": {
"reportToken": "<REPORT_TOKEN>"
}
}
<REPORT_TOKEN> with the token generated from the previous request.<ACCESS_TOKEN> with the one generated from the authentication request.Example of response body (report generation still in progress):
{
"data": {
"partner": {
"reportFile": {
"status": "IN_PROGRESS",
"downloadLinks": {
"edges": []
}
}
}
}
}
Example of response body (report generation finished):
{
"data": {
"partner": {
"reportFile": {
"status":"FINISHED",
"downloadLinks": {
"edges": [
{
"node": {
"link":"https://storage.googleapis.com/dailymotion-stats-report/21da4e2e74..."
}
}
]
}
}
}
}
}
You can download the report once the status displays FINISHED. The download link is located in the response (inside the downloadLinks node).
Please note that big report requests can lead to several report files. Be sure to download all the files in order to get a complete report.
You can use the following code samples in order to test report generation and automatically download the resulting files.
Don't forget to change the variable values (app key, app secret, username, password, report dimensions, report metrics, report filters and report start/end date) to match your configuration and needs.
#!/usr/bin/env bash
# Authenticate on the API in order to get an access token
get_access_token () {
local APP_KEY=$1
local APP_SECRET=$2
local USERNAME=$3
local PASSWORD=$4
ACCESS_TOKEN=$(curl -s -X POST \
https://graphql.api.dailymotion.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=$APP_KEY&client_secret=$APP_SECRET&username=$USERNAME&password=$PASSWORD&grant_type=password&version=2" \
| jq '.access_token' | sed -e 's/^"//' -e 's/"$//' | cat)
}
# Creating a report request
create_report_request () {
declare -a DIMENSIONS=("${!1}")
declare -a METRICS=("${!2}")
local START_DATE=$3
local END_DATE=$4
declare -a FILTERS=("${!5}")
local GRAPHQL_FILTERS=""
local firstItem=1
for filter in ${FILTERS[@]}; do
if [ "$firstItem" -eq 1 ]; then separator=''; else separator=','; fi
filter_parts=($(echo $filter | tr "=" " "))
GRAPHQL_FILTERS="${GRAPHQL_FILTERS}${separator}\"${filter_parts[0]}\": \"${filter_parts[1]}\""
firstItem=0
done
local GRAPHQL_DIMENSIONS=""
local firstItem=1
for dimension in ${DIMENSIONS[@]}; do
if [ "$firstItem" -eq 1 ]; then separator=''; else separator=','; fi
GRAPHQL_DIMENSIONS="${GRAPHQL_DIMENSIONS}${separator}\"$dimension\""
firstItem=0
done
local GRAPHQL_METRICS=""
local firstItem=1
for metric in ${METRICS[@]}; do
if [ "$firstItem" -eq 1 ]; then separator=''; else separator=','; fi
GRAPHQL_METRICS="${GRAPHQL_METRICS}${separator}\"$metric\""
firstItem=0
done
local REQUEST
read -r -d '' REQUEST <<EOF
{
"query": "mutation (\$input: AskPartnerReportFileInput!) {
askPartnerReportFile(input: \$input) {
reportFile {
reportToken
}
}
}",
"variables": {
"input": {
"metrics": [$GRAPHQL_METRICS],
"dimensions": [$GRAPHQL_DIMENSIONS],
"filters": {$GRAPHQL_FILTERS},
"startDate": "$START_DATE",
"endDate": "$END_DATE"
}
}
}
EOF
REPORT_TOKEN=$(echo $REQUEST | jq -c '.' | curl -s -X POST \
https://graphql.api.dailymotion.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d @- | jq '.data.askPartnerReportFile.reportFile.reportToken' | sed -e 's/^"//' -e 's/"$//' | cat)
}
# Checking the status of the reporting request
function check_report_status () {
read -r -d '' REQUEST <<EOF
{
"query": "query PartnerGetReportFile(\$reportToken: String!) {
partner {
reportFile(reportToken: \$reportToken) {
status
downloadLinks {
edges {
node {
link
}
}
}
}
}
}",
"variables": {
"reportToken": "$REPORT_TOKEN"
}
}
EOF
local report=$(echo $REQUEST | jq -c '.' | curl -s -X POST \
https://graphql.api.dailymotion.com \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d @- | jq '.data.partner.reportFile' | cat)
local report_status=$(echo $report | jq '.status' | sed -e 's/^"//' -e 's/"$//' | cat)
if [ "$report_status" == "FINISHED" ]; then
download_links=$(echo $report | jq '.downloadLinks.edges[].node.link' | sed -e 's/^"//' -e 's/"$//' | cat)
fi
}
# Downloading the report files
function download_report () {
local base_path=$PWD
if [ -n "$1" ]; then
base_path=$1
fi
local cpt=1
local file_path
for url in ${download_links[@]}; do
file_path="$base_path/report_$cpt.csv"
curl -s $url --output "$file_path"
echo "Report file $cpt downloaded: $file_path"
let cpt++
done
}
# Generate an access token
APP_KEY='<your_api_key>'
APP_SECRET='<your_api_secret>'
USERNAME='<your_username>'
PASSWORD='<your_password>'
echo "Generating access token..."
get_access_token $APP_KEY $APP_SECRET $USERNAME $PASSWORD
echo "Creating report request..."
dimensions=("DAY" "VIDEO_TITLE")
metrics=("VIEWS")
start_date="2018-07-01"
end_date="2018-07-04"
filters=("videoOwnerChannelSlug=<your_channel_slug>")
create_report_request dimensions[@] metrics[@] $start_date $end_date filters[@]
download_links=()
while [ ${#download_links[@]} -eq 0 ]; do
echo "Checking report status..."
# Checks every 15secs the report status
sleep 15
check_report_status
done
download_report
#!/usr/bin/env php
<?php
/**
* Authenticate on the API in order to get an access token
*/
function get_access_token($app_key, $app_secret, $username, $password) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://graphql.api.dailymotion.com/oauth/token');
$headers = [
'Content-Type: application/x-www-form-urlencoded'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'client_id' => $app_key,
'client_secret' => $app_secret,
'username' => $username,
'password' => $password,
'grant_type' => 'password',
'version' => '2'
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$tokens = json_decode($response, true);
if (false === $tokens) {
throw new \Exception('Invalid authentication response');
}
return $tokens['access_token'];
}
/**
* Creating a report request
*/
function create_report_request($access_token, array $dimensions, array $metrics, $start_date, $end_date, array $filters = []) {
$report_request = [
'query' => '
mutation ($input: AskPartnerReportFileInput!) {
askPartnerReportFile(input: $input) {
reportFile {
reportToken
}
}
}',
'variables' => [
'input' => [
'metrics' => $metrics,
'dimensions' => $dimensions,
'filters' => $filters,
'startDate' => $start_date,
'endDate' => $end_date
]
]
];
$report_request = json_encode($report_request);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://graphql.api.dailymotion.com');
$headers = [
'Authorization: Bearer '.$access_token,
'Content-Type: application/json',
'Content-Length: ' . strlen($report_request)
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $report_request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$report_info = json_decode($response, true);
if (false === $report_info) {
throw new \Exception('Invalid response');
}
return $report_info['data']['askPartnerReportFile']['reportFile']['reportToken'];
}
/**
* Checking the status of the reporting request
*/
function check_report_status($access_token, $report_token) {
$report_check_request = [
'query' => '
query PartnerGetReportFile ($reportToken: String!) {
partner {
reportFile(reportToken: $reportToken) {
status
downloadLinks {
edges {
node {
link
}
}
}
}
}
}
',
'variables' => [
'reportToken' => $report_token
]
];
$report_check_request = json_encode($report_check_request);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://graphql.api.dailymotion.com');
$headers = [
'Authorization: Bearer '.$access_token,
'Content-Type: application/json',
'Content-Length: ' . strlen($report_check_request)
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $report_check_request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$report_info = json_decode($response, true);
if (false === $report_info) {
throw new \Exception('Invalid response');
}
$report_status = $report_info['data']['partner']['reportFile']['status'];
if ($report_status === 'FINISHED') {
$download_links = [];
foreach ($report_info['data']['partner']['reportFile']['downloadLinks']['edges'] as $edge) {
$download_links[] = $edge['node']['link'];
}
return $download_links;
} else {
return null;
}
}
/**
* Downloading the report files
*/
function download_report($download_links, $base_path = null) {
$cpt = 1;
if (null === $base_path) {
$base_path = getcwd();
}
foreach ($download_links as $url) {
$file_path = sprintf("%s/report_%s.csv", $base_path, $cpt);
file_put_contents($file_path, fopen($url, 'r'));
echo sprintf("Raport file %s downloaded: %s\n", $cpt, $file_path);
$cpt += 1;
}
}
$app_key = '<your_api_key>';
$app_secret = '<your_api_secret>';
$username = '<your_username>';
$password = '<your_password>';
echo "Generating access token...\n";
$access_token = get_access_token($app_key, $app_secret, $username, $password);
$dimensions = ['DAY', 'VIDEO_TITLE'];
$metrics = ['VIEWS'];
$filters = [
'videoOwnerChannelSlug' => '<your_channel_slug>'
];
$start_date = '2018-07-01';
$end_date = '2018-07-04';
echo "Creating report request...\n";
$report_token = create_report_request($access_token, $dimensions, $metrics, $start_date, $end_date, $filters);
$download_links = null;
while (!$download_links) {
echo "Checking report status...\n";
// Checks every 15secs the report status
sleep(15);
$download_links = check_report_status($access_token, $report_token);
}
download_report($download_links);
#!/usr/bin/env python
import requests
import os
import time
def get_access_token(app_key, app_secret, username, password):
'''
Authenticate on the API in order to get an access token
'''
response = requests.post('https://graphql.api.dailymotion.com/oauth/token', data={
'client_id': app_key,
'client_secret': app_secret,
'username': username,
'password': password,
'grant_type': 'password',
'version': '2'
})
if response.status_code != 200 or not 'access_token' in response.json():
raise Exception('Invalid authentication response')
return response.json()['access_token']
def create_report_request(access_token, dimensions, metrics, start_date, end_date, filters = None):
'''
Creating a report request
'''
reportRequest = """
mutation ($input: AskPartnerReportFileInput!) {
askPartnerReportFile(input: $input) {
reportFile {
reportToken
}
}
}
"""
response = requests.post(
'https://graphql.api.dailymotion.com',
json={
'query': reportRequest,
'variables': {
'input': {
'metrics': metrics,
'dimensions': dimensions,
'filters': filters,
'startDate': start_date,
'endDate': end_date,
}
}
},
headers={'Authorization': 'Bearer ' + access_token}
)
if response.status_code != 200 or not 'data' in response.json():
raise Exception('Invalid response')
return response.json()['data']['askPartnerReportFile']['reportFile']['reportToken'];
def check_report_status(access_token, report_token):
'''
Checking the status of the reporting request
'''
report_request_status_check = """
query PartnerGetReportFile ($reportToken: String!) {
partner {
reportFile(reportToken: $reportToken) {
status
downloadLinks {
edges {
node {
link
}
}
}
}
}
}
"""
response = requests.post(
'https://graphql.api.dailymotion.com',
json={
'query': report_request_status_check,
'variables': {
'reportToken': report_token
}
},
headers={'Authorization': 'Bearer ' + access_token}
)
if response.status_code != 200 or not 'data' in response.json():
raise Exception('Invalid response')
status = response.json()['data']['partner']['reportFile']['status'];
if (status == 'FINISHED'):
download_links = []
for url in map(lambda edge: edge['node']['link'], response.json()['data']['partner']['reportFile']['downloadLinks']['edges']):
download_links.append(url)
return download_links
else:
return None
def download_report(download_links, base_path=None):
'''
Downloading the report files
'''
cpt = 1
if not base_path:
base_path = os.getcwd()
for url in download_links:
r = requests.get(url)
filename = 'report_{}.csv'.format(cpt)
file_path = os.path.join(base_path, filename)
open(file_path, 'wb').write(r.content)
print('Report file {} downloaded: {}'.format(cpt, file_path))
cpt += 1
print('Generating access token...')
access_token = get_access_token(
app_key='<your_api_key>',
app_secret='<your_api_secret>',
username='<your_username>',
password='<your_password>'
)
print('Creating report request...')
report_token = create_report_request(
access_token=access_token,
dimensions=('DAY', 'VIDEO_TITLE'),
metrics=('VIEWS'),
filters={'videoOwnerChannelSlug': '<your_channel_slug>'},
start_date='2018-07-01',
end_date='2018-07-04'
)
download_links = None
while not download_links:
print('Checking report status...')
# Checks every 15secs the report status
time.sleep(15)
download_links = check_report_status(
access_token=access_token,
report_token=report_token
)
download_report(download_links=download_links)
Note: dimensions, filters, and metrics are case sensitive and must be utilized as shown in this tables.
| Dimension | Definitions |
|---|---|
| MONTH | Month |
| DAY | Day |
| CHANNEL_SLUG | Channel owner's channel URL |
| VIDEO_OWNER_CHANNEL_SLUG | Content owner's channel URL |
| VIDEO_ID | Video ID |
| VIDEO_TITLE | Title of the video |
| MEDIA_TYPE | Type of video: LIVE or VIDEO |
| VISITOR_DOMAIN_GROUP | Visitor domain |
| VISITOR_COUNTRY | Visitor country |
| VIDEO_DEVICE_TYPE | Visitor device type |
| MONETIZATION_TYPE | Monetization category: video or website |
| Filters | Definitions | Type | Possible values |
|---|---|---|---|
| channelSlug | Limits the result set to a specific channel | Variable values | N/A |
| videoOwnerChannelSlug | Limits the result set to a specific video owner channel | Variable values | N/A |
| mediaType | Limits the result set to a specific media type: LIVE or VIDEO | Fixed values | VIDEO, LIVE |
| visitorDomainGroup | Limits the result set to a specific visitor domain group | Variable values | N/A |
| monetizationType | Limits the monetization category to either Video Monetization or Website Monetization | Fixed values | Video monetization, Website monetization, claim |
| Metrics | Definitions |
|---|---|
| VIEWS | Number of views |
| TIME_WATCHED_SECONDS | Time watched in seconds |
| IMPRESSIONS | Number of impressions generated |
| ESTIMATED_EARNINGS_USD | Estimated earnings in USD |
| ESTIMATED_EARNINGS_EUR | Estimated earnings in EUR |
Not all metrics and dimensions can be combined in a single report. Refer to this table for guidance.
| Dimensions | VIEWS | TIME_WATCHED_SECONDS | IMPRESSIONS | ESTIMATED_EARNINGS_* |
|---|---|---|---|---|
| DAY | ✔ | ✔ | ✔ | ✔ |
| MONTH | ✔ | ✔ | ✔ | ✔ |
| CHANNEL_SLUG | ✔ | |||
| VIDEO_OWNER_CHANNEL_SLUG | ✔ | ✔ | ✔ | |
| VIDEO_ID | ✔ | ✔ | ✔ | ✔ |
| VIDEO_TITLE | ✔ | ✔ | ✔ | ✔ |
| MEDIA_TYPE | ✔ | ✔ | ||
| VISITOR_DOMAIN_GROUP | ✔ | ✔ | ✔ | ✔ |
| VISITOR_COUNTRY | ✔ | ✔ | ✔ | ✔ |
| VISITOR_DEVICE_TYPE | ✔ | ✔ | ✔ | |
| MONETIZATION_TYPE | ✔ |
| Filters | VIEWS | TIME_WATCHED_SECONDS | IMPRESSIONS | ESTIMATED_EARNINGS_* |
|---|---|---|---|---|
| channelSlug | ✔ | |||
| videoOwnerChannelSlug | ✔ | ✔ | ✔ | |
| mediaType | ✔ | ✔ | ||
| visitorDomainGroup | ✔ | ✔ | ✔ | ✔ |
| monetizationType | ✔ |