Handle error 152 “Insufficient points”
Python version 2 or 3 using JSON with the Requests library
In version 5 of the Yandex Direct API, points are awarded to all advertisers every 60 minutes, but each advertiser has its own schedule for awarding points that is not related to the beginning of the astronomical hour. The example shows how requests are executed if the first request returns the 152 error code.
For demonstration purposes, it uses the sleep
function, which allows you to set delays for running the script. The delays are set in seconds in the delays
array, so that after the first attempt no more than 5 repeat requests are sent with increasing intervals that cover the next 60 minutes after receiving the first error.
# -*- coding: utf-8 -*-
import sys
from time import sleep
import json
import requests
if sys.version_info < (3,):
def u(x):
try:
return x.encode("utf8")
except UnicodeDecodeError:
return x
else:
def u(x):
if type(x) == type (b''):
return x.decode('utf8')
else:
return x
# --- Settings ---
# Output debugging information
debug = True
# Array of delay intervals
delays = [360, 540, 720, 900, 1080]
# "Insufficient points" error
notEnoughUnitsError = "152"
# --- Input data ---
# Address of the Campaigns service for sending JSON requests (case-sensitive)
CampaignsURL = 'https://api.direct.yandex.com/json/v5/campaigns'
# OAuth token of the user that requests will be made on behalf of
token = 'TOKEN'
# Login of an advertising agency client
# Required parameter if requests are made on behalf of an advertising agency
clientLogin = 'CLIENT_LOGIN'
# --- Preparing the request ---
# Creating HTTP request headers
headers = {
"Authorization": "Bearer" + token, # OAuth token. The word Bearer must be used
"Client-Login": clientLogin, # Login of the advertising agency client
"Accept-Language": "ru", # Language for response messages
}
# Creating the request body
body = {"method": "get", # Method to use.
"params": {
"SelectionCriteria": {}, # Criteria for filtering campaigns. To get all campaigns, leave it emtpy
"FieldNames": ["Id", "Name"] # Names of parameters to get
}
}
# Transforming input data to JSON
jsonBody = json.dumps(body, ensure_ascii=False).encode('utf8')
# --- Performing tasks ---
# Starting the request execution loop. If the first request finished successfully, meaning it did not return error 152,
# a list of campaigns is returned.
# If the first request failed with this error, repeat requests are performed with the delays,
# that are set in the delays array.
for delay in delays:
try:
# Executing the request and getting the result
result = requests.post(CampaignsURL, jsonBody, headers=headers)
# Debugging information
if debug:
print("Request headers: {}".format(result.request.headers))
print("Request: {}".format(u(result.request.body)))
print("Response headers: {}".format(result.headers))
print("Response: {}".format(u(result.text)))
print("\n")
# Request handling
if result. status_code == 200:
# If HTTP 200 was received, the response message body is processed
# Output the RequestId and information about points
print("RequestId: {}".format(result.headers.get("RequestId", False)))
print("Information about points: {}".format(result.headers.get("Units", False)))
# If the output data doesn't contain the first error key, it means the request was processed successfully
if not result.json().get ("error", False):
# Output the list of campaigns
for campaign in result.json()["result"]["Campaigns"]:
print("Ad campaign: {} №{}".format (u(campaign['Name']), campaign['Id']))
# If the response contains the LimitedBy parameter, it means not all available objects were output.
if result.json()['result'].get('LimitedBy', False):
# In this case, send additional requests to get all objects.
# Details on paginated selections - https://tech.yandex.ru/direct/doc/dg/best-practice/get-docpage/#page
print("Not all objects received.")
# Forced exit from loop
break
# Processing errors for a request to the Yandex Direct API server
elif result.json().get("error", False):
print("An error occurred when accessing the Yandex Direct API server.")
print("Error code: {}".format(result.json()["error"] ["error_code"]))
print("Error description: {}".format(u(result.json()["error"]["error_detail"])))
if result.json()['error'].get('error_code', 0) == notEnoughUnitsError:
# Insufficient points to execute the request
print("Resending in {} seconds".format (delay))
# Delay before the next request
sleep (delay)
# Handling other errors
else:
print("An error occurred when accessing the Yandex Direct API server.")
print("HTTP error code: {}".format(u(result.status_code)))
# Describe here what to do for HTTP request errors
# Handling an error in connecting to the Yandex Direct API server
except ConnectionError:
# In this case, we recommend repeating the request later
print("Error connecting to the 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 occurred.")
# Forced exit from loop
break