Generate reports using a public API key
In this guide, we’ll show you the steps to generate reports via the Reporting API using a public API key.
If you’re using a private API key instead (only available for verified Partners), please follow the dedicated guide.
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 article.
1. Generate a public API key
Follow the dedicated guide to easily create a public API Key from your Dailymotion Studio.
Once created, you’ll retrieve an API key and API secret: reach out to your Dailymotion Account Manager (or Support team) with the API key (but not the secret) to request access to the Reporting API.
Move on to step 2 once this is done.
2. Perform authentication
To authenticate against the Reporting API, pass in the Dailymotion login credentials (username and password) along with the API key and secret generated in step 1.
Make a POST
request to the access token server https://graphql.api.dailymotion.com/oauth/token
with the following parameters:
grant_type
: specify the grant type flow used –password
client_id
: the API key from step 1client_secret
: the API secret from step 1username
: login email address of the Dailymotion channel ownerpassword
: login password of the Dailymotion channel owner
Request example:
POST /oauth/token HTTP/1.1
Host: graphql.api.dailymotion.com
Content-Type: application/x-www-form-urlencoded
grant_type=password
&client_id=<YOUR_API_KEY>
&client_secret=<YOUR_API_SECRET>
&username=<YOUR_USERNAME>
&password=<YOUR_PASSWORD>
Response example:
If successful, you will get a JSON response containing the access token in the following format:
{
"access_token": "eyJ0eXAiOiJK...jO67fL658U",
"expires_in": 36000,
"refresh_token": "eyJ0eXAiOiJK...LFPA1uDBD0",
"scope": "",
"token_type": "Bearer"
}
The access token is returned in the access_token
parameter and remains valid for the time defined in expires_in
(time in seconds = 10 hours).
The refresh_token
enables you to request another access token without the need to ask for the resource owner credentials again. Check our dedicated guide to know how to refresh a token.
You have now retrieved an access token and have have been authorized to access your reporting data via the API. Move on to step 3 to see how to generate a report.
3. Generate report
You will now be able to generate reports of your Dailymotion channel performances by including the following elements in your API request:
- Endpoint: make a
POST
call tohttps://graphql.api.dailymotion.com
for all subsequent API calls - Access token: pass it in the request header for each API call. Replace the
<ACCESS_TOKEN>
below with the one generated from the authentication request in step 2. - Query: pass in the metrics, dimensions, filters, product and date range needed
Request example:
POST / HTTP/1.1
Host: graphql.api.dailymotion.com
Content-Type: application/json
Authorization: Bearer <ACCESS_TOKEN>
{
"query": "mutation ($input: AskPartnerReportFileInput!) {
askPartnerReportFile(input: $input) {
reportFile {
reportToken
}
}
}",
"variables": {
"input": {
"metrics": ["VIEWS"],
"dimensions": ["DAY", "VIDEO_TITLE"],
"filters": {
"videoOwnerChannelSlug": "<your_channel_slug>"
},
"product": "CONTENT",
"startDate": "2023-07-01",
"endDate": "2023-07-04"
}
}
}
In this example, we are generating a report gathering the VIEWS
per DAY
and VIDEO_TITLE
for the Dailymotion channel defined in the filter videoOwnerChannelSlug
. This report will only show data from the channel’s uploaded CONTENT
for the time frame 2023-07-01
to 2023-07-04
.
See all metrics, dimensions, filters and products available in the Reporting API Reference.
Response example:
{
"data": {
"askPartnerReportFile": {
"reportFile" {
"reportToken":"eyJ0eX...sAG7__nZ7w"
}
}
}
}
As a response to your request, you’ll receive a reportToken
that you can use to check the status of your report and access it once ready.
4. Check report status
To check the status of your report, use the code sample below:
- Replace
<ACCESS_TOKEN>
with the one generated from the authentication request in step 2 - Replace
<REPORT_TOKEN>
with the report token received in the previous step
Request example:
POST / HTTP/1.1
Host: graphql.api.dailymotion.com
Content-Type: application/json
Authorization: Bearer <ACCESS_TOKEN>
{
"query": "query PartnerGetReportFile($reportToken: String!) {
partner {
reportFile(reportToken: $reportToken) {
status
downloadLinks {
edges {
node {
link
}
}
}
}
}
}",
"variables": {
"reportToken": "<REPORT_TOKEN>"
}
}
Response examples:
- Report generation still in progress
{
"data": {
"partner": {
"reportFile": {
"status": "IN_PROGRESS",
"downloadLinks": {
"edges": []
}
}
}
}
}
In this example, the generation of the report is still IN_PROGRESS
as indicated in the status parameter.
It can take up to two hours for a report to be generated.
- Report generation finished
{
"data": {
"partner": {
"reportFile": {
"status":"FINISHED",
"downloadLinks": {
"edges": [
{
"node": {
"link":"https://storage.googleapis.com/dailymotion-stats-report/21da4e2e74..."
}
}
]
}
}
}
}
}
In this example, the report has been generated, as indicated by the status FINISHED
.
5. Download the report
You can download the report once the status displays FINISHED
. The download link is located in the response, inside the downloadLinks
node.
Code samples
You can use the following code samples to test report generation and automatically download the resulting files.
Don’t forget to change the variable values (API key, API secret, username, password, report dimensions, metrics, filters, product and 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 PRODUCT=$6
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",
"product": "$PRODUCT"
}
}
}
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"
product="CONTENT"
filters=("videoOwnerChannelSlug=<your_channel_slug>")
create_report_request dimensions[@] metrics[@] $start_date $end_date filters[@] $product
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, $product, 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,
'product' => $product
]
]
];
$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';
$product = 'CONTENT';
echo "Creating report request...\n";
$report_token = create_report_request($access_token, $dimensions, $metrics, $start_date, $end_date, $product, $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, product, 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,
'product': product,
}
}
},
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',
product='CONTENT',
)
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)