To enjoy all our Developer Portal features, please switch to Microsoft Edge, Google Chrome or Mozilla Firefox browsers.

Reporting API Documentation

Overview

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.

Reporting parameters

The Dailymotion reporting API accepts dimensions, filters, and metrics as parameters:

  • Dimensions are used to organize metrics across common criteria. For example: visitor country and visitor device type.
  • Filters are used to scope down the result set. For example, media type and visitor domain group.
  • Metrics are measurements related to activity. For example: number of views and time watched.

Refer to these tables for detailed information: Dimensions, filters, and metrics and Compatibility matrix.

Reporting constraints

Key points to note before you begin:

  • Reports are generated asynchronously; data is pulled and collected in a CSV
  • You can generate a maximum of two reports concurrently
  • A report can take up to two hours to generate
  • The API supports granularity no smaller than one day
  • A date range is required for every request
  • The date range filter cannot exceed a period of 180 days
  • A maximum of eight dimensions can be passed in a single report
  • Reports are deleted after 48 hours

How to generate a report

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.

Step 1: Generate an API key and secret.

  1. Go to the Partner HQ.
  2. Scroll down to Manage your API keys. Click Create a new key and fill out the form. Use http://localhost.com in the Website and Callback URL fields if you don’t have a specific website to use.
  3. Click Create. Your API key and secret will be displayed and stored here for future reference.
  4. Contact your Dailymotion content manager with the API key (but not the secret) and request reporting API access be enabled. Move to step 2 once this is done.

Step 2: Perform authentication.

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"
}

Step 3: Request the report.

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"
        }
    }
}
  1. Pass in the dimensions, metrics, filters and date range you want to generate the report for. 
  2. Replace the <ACCESS_TOKEN> with the one generated from authentication request. 

Table for guidance.

Example of response body:

{
    "data": {
        "askPartnerReportFile": {
            "reportFile" {
                "reportToken":"eyJ0eX...sAG7__nZ7w"
            }
        }
    }
}

Step 4: Check report status.

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>"
    }
}
  1. Make sure to replace <REPORT_TOKEN> with the token generated from the previous request.
  2. Send a check status request. Make sure to replace the <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..."
                            }
                        }
                    ]
                }
            }
        }
    }
}

Step 5: Download the generated report.

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.

Code samples

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.

  • 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 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")
    # You can only provide one metric at a time
    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'];
    // You can only provide one metric at a time
    $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'),
        # You can only provide one metric at a time
        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)
    

Dimensions, filters, and metrics

Note: dimensions, filters, and metrics are case sensitive and must be utilized as shown in this tables.

DimensionDefinitions
MONTHMonth
DAYDay
CHANNEL_SLUGChannel owner's channel URL
VIDEO_OWNER_CHANNEL_SLUGContent owner's channel URL
VIDEO_IDVideo ID
VIDEO_TITLETitle of the video
MEDIA_TYPEType of video: LIVE or VIDEO
VISITOR_DOMAIN_GROUPVisitor domain
VISITOR_COUNTRYVisitor country
VIDEO_DEVICE_TYPEVisitor device type
MONETIZATION_TYPEMonetization category: video or website
FiltersDefinitionsTypePossible values
channelSlugLimits the result set to a specific channelVariable valuesN/A
videoOwnerChannelSlugLimits the result set to a specific video owner channelVariable valuesN/A
mediaTypeLimits the result set to a specific media type: LIVE or VIDEOFixed valuesVIDEO, LIVE
visitorDomainGroupLimits the result set to a specific visitor domain groupVariable valuesN/A
monetizationTypeLimits the monetization category to either Video Monetization or Website MonetizationFixed valuesVideo monetization, Website monetization, claim
MetricsDefinitions
VIEWSNumber of views
TIME_WATCHED_SECONDSTime watched in seconds
IMPRESSIONSNumber of impressions generated
ESTIMATED_EARNINGS_USDEstimated earnings in USD
ESTIMATED_EARNINGS_EUREstimated earnings in EUR

Note: You can only provide one metric at a time

Compatibility matrix

Not all metrics and dimensions can be combined in a single report. Refer to this table for guidance.

DimensionsVIEWSTIME_WATCHED_SECONDSIMPRESSIONSESTIMATED_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
FiltersVIEWSTIME_WATCHED_SECONDSIMPRESSIONSESTIMATED_EARNINGS_*
channelSlug
videoOwnerChannelSlug
mediaType
visitorDomainGroup
monetizationType