Documentation

Get statistics for agency clients

Python version 2 or 3 using JSON with the Requests library

This example shows how to use the AgencyClients.get method to get a list of agency clients and then execute requests to the Reports service to get statistics for advertiser accounts for the past day. The mode for generating the report is selected automatically. If the report is added to the queue in offline mode, repeated requests are made.

To use the example, specify the OAuth access token that you received for the agency representative in the input data.

# -*- coding: utf-8 -*-
import requests
from requests.exceptions import ConnectionError
from time import sleep
import json
from datetime import date, timedelta
from time import time

# Method for correctly parsing UTF-8 encoded strings for both Python 3 and Python 2
import sys

if sys.version_info < (3,):
    def u(x):
        try:
            return x.encode("utf8")
        except UnicodeDecodeError:
            return x
else:
    def u(x):
        if isinstance(x, bytes):
            return x.decode('utf8')
        else:
            return x

# --- Input data ---
# Address of the AgencyClients service for sending JSON requests (case-sensitive)
AgencyClientsURL = 'https://api.direct.yandex.com/json/v5/agencyclients'

# Address of the Reports service for sending JSON requests (case-sensitive)
ReportsURL = 'https://api.direct.yandex.com/json/v5/reports'

# OAuth token of the agency representative that requests will be made on behalf of
token = 'TOKEN'

# --- Preparing the request to the AgencyClients service ---
# Creating HTTP request headers
headers = {
           # OAuth token. The word Bearer must be used
           "Authorization": "Bearer " + token,
           # Language for response messages
           "Accept-Language": "en"
           }

AgencyClientsBody = {
    "method": "get",
    "params": {
        "SelectionCriteria": {
            "Archived": "NO"   # Only get active clients
        },
        "FieldNames": ["Login"],
        "Page": {
            "Limit": 10000,  # Get a maximum of 10000 clients in the server response
            "Offset": 0
        }
    }
}

# --- Executing requests to the AgencyClients service ---
# If the LimitedBy parameter is not in the response, it means
# that all clients were received
HasAllClientLoginsReceived = False
ClientList = []

while not HasAllClientLoginsReceived:
    ClientsResult = requests.post(AgencyClientsURL, json.dumps(AgencyClientsBody), headers=headers).json()
    for Client in ClientsResult['result']['Clients']:
        ClientList.append(Client["Login"])
    if ClientsResult['result'].get("LimitedBy", False):
        AgencyClientsBody['Page']['Offset'] = ClientsResult['result']["LimitedBy"]
    else:
        HasAllClientLoginsReceived = True

# --- Preparing the request to the Reports service ---
# Creating the request message body
# The report contains statistics on clicks, impressions, and expenditures for all the client's campaigns
body = {
    "params": {
        "SelectionCriteria": {},
        "FieldNames": [
            "Impressions",
            "Clicks",
            "Cost"
        ],
        "ReportName": u("ACCOUNT_PERFORMANCE"),
        "ReportType": "ACCOUNT_PERFORMANCE_REPORT",
        "DateRangeType": "AUTO",
        "Format": "TSV",
        "IncludeVAT": "NO",
        "IncludeDiscount": "NO"
    }
}

# Creating output data
resultcsv = "Login;Impressions;Clicks;Costs\n"

# Additional HTTP headers for requesting reports
headers['skipReportHeader'] = "true"
headers['skipColumnHeader'] = "true"
headers['skipReportSummary'] = "true"
headers['returnMoneyInMicros'] = "false"

# --- Executing requests to the Reports service ---
for Client in ClientList:
    # Adding the "Client-Login" HTTP header
    headers['Client-Login'] = Client
    # Encoding the request message body as JSON
    requestBody = json.dumps(body, indent=4)
    # Starting the request execution loop
    # If HTTP response code 200 is returned, the report data is added to the output data
    # If HTTP response code 201 or 202 is returned, repeated requests are made
    while True:
        try:
            req = requests.post(ReportsURL, requestBody, headers=headers)
            req.encoding = 'utf-8'  # Mandatory response processing in UTF-8
            if req.status_code == 400:
                print("Invalid request parameters, or the request queue is full")
                print("RequestId: {}".format(req.headers.get("RequestId", False)))
                print("JSON code for the request: {}".format(u(body)))
                print("JSON code for the server response: \n{}".format(u(req.json())))
                break
            elif req.status_code == 200:
                print("Report for account {} created successfully".format(str(Client)))
                print("RequestId: {}".format(req.headers.get("RequestId", False)))
                if req.text != "":
                    tempresult = req.text.split('\t')
                    resultcsv += "{};{};{};{}\n".format(Client, tempresult[0], tempresult[1], str(tempresult[2]).replace('.', ','))
                else:
                    resultcsv += "{};0;0;0\n".format(Client)
                break
            elif req.status_code == 201:
                print("Report for account {} successfully added to the offline queue".format(str(Client)))
                retryIn = int(req.headers.get("retryIn", 60))
                print("Request will be repeated in {} seconds".format(retryIn))
                print("RequestId: {}".format(req.headers.get("RequestId", False)))
                sleep(retryIn)
            elif req.status_code == 202:
                print("Report is being created in offline mode".format(str(Client)))
                retryIn = int(req.headers.get("retryIn", 60))
                print("Request will be repeated in {} seconds".format(retryIn))
                print("RequestId: {}".format(req.headers.get("RequestId", False)))
                sleep(retryIn)
            elif req.status_code == 500:
                print("Error occurred when creating the report. Please repeat the request again later.")
                print("RequestId: {}".format(req.headers.get("RequestId", False)))
                print("JSON code for the server response: \n{}".format(u(req.json())))
                break
            elif req.status_code == 502:
                print("Exceeded the server limit on report creation time.")
                print(
                    "Please try changing the request parameters: reduce the time period and the amount of data requested.")
                print("JSON code for the request: {}".format(body))
                print("RequestId: {}".format(req.headers.get("RequestId", False)))
                print("JSON code for the server response: \n{}".format(u(req.json())))
                break
            else:
                print("Unexpected error")
                print("RequestId: {}".format(req.headers.get("RequestId", False)))
                print("JSON code for the request: {}".format(body))
                print("JSON code for the server response: \n{}".format(u(req.json())))
                break

        # Error handling if the connection with the Yandex.Direct API server could not be established
        except ConnectionError:
            # In this case, we recommend repeating the request again later
            print("Error connecting to the Yandex.Direct API server")
            # Forced exit from loop
            break

        # If any other error occurred
        except:
            # In this case, we recommend analyzing the application's actions
            print("Unexpected error")
            # Forced exit from loop
            break

print("Finished creating reports for accounts")

# Creating and saving the file
filename = "AccountsPerfomanceReport_{}.csv".format(str(time()))
resultfile = open(filename, 'w+')
resultfile.write(resultcsv)
resultfile.close()

print("Results are saved in the file {}".format(filename))