Table of content

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 1
  • client_secret: the API secret from step 1
  • username: login email address of the Dailymotion channel owner
  • password: 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 to https://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
Important:
  • Parameters are case sensitive: make sure to use them as they are indicated in the Reporting API Reference
  • Metrics and dimensions aren’t all compatible with each other: refer to the Compatibility matrix for guidance
  • CSV reports are generated in UTC timezone

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.

Note:

Requests for bigger reports can generate several report files. In this case, make sure to download all the files in order to get a complete report.


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.

Bash
PHP
Python
#!/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)