The full power of API interaction is revealed when used alongside programming code, allowing for the dynamic generation of API requests and tools for analyzing API responses. However, it remains relatively unnoticed that Python Software Development Kit (hereinafter referred to as Python SDK) for Check Point Management API, which is a pity. It significantly simplifies the lives of developers and automation enthusiasts. Python has gained immense popularity recently, and I decided to fill the gap by reviewing the main capabilities of . This article serves as a great supplement to another article on Habr . We will discuss how to write scripts using the Python SDK and delve deeper into the new features of the Management API in version 1.6 (supported starting from R80.40). Basic knowledge of working with APIs and Python will be necessary to understand the article.
Check Point is actively developing its API, and currently, the following have been released:
- — interaction with the management server via API (including the ability to execute scripts on gateways under the control of the management server)
- — interaction with security gateways
- — working with the sandbox in Check Point's cloud
- — working with the Identity Awareness blade on gateways
- — working with the portal for managing SMB gateways ()
- — interaction with IoT controllers
- — working with (an SD-WAN security solution)
- — working with
The Python SDK currently supports interaction only with the Management API and Gaia API. We will explore the most important classes, methods, and variables in this module.

Module Installation
Module cpapi installs quickly and easily from the using pip. Detailed installation instructions can be found in . This module is adapted for use with Python versions 2.7 and 3.7. In this article, examples will be provided using Python 3.7. However, the Python SDK can be run directly from the Check Point management server (Smart Management), but only version 2.7 is supported there, so code for version 2.7 will be provided in the last section. Right after installing the module, I recommend looking at the examples in the directories examples_python2 and examples_python3.
Getting Started
In order to work with the components of the cpapi module, it is necessary to import from the module cpapi at least two necessary classes:
APIClient and APIClientArgs
from cpapi import APIClient, APIClientArgs
Class APIClientArgs is responsible for the connection parameters to the API server, while the class APIClient is responsible for interacting with the API.
Defining connection parameters
To define various connection parameters to the API, an instance of the class needs to be created APIClientArgs. Basically, its parameters are predefined and do not need to be specified when running the script on the management server.
client_args = APIClientArgs()However, when running on a third-party host, you need to specify at least the IP address or hostname of the API server (the management server). In the example below, we define the connection parameter server and assign it the IP address of the management server as a string.
client_args = APIClientArgs(server='192.168.47.241')Let's take a look at all the parameters and their default values that can be used when connecting to the API server:
Arguments of the __init__ method of the APIClientArgs class
class APIClientArgs:
"""
This class provides arguments for APIClient configuration.
All the arguments are configured with their default values.
"""
# port is set to None by default, but it gets replaced with 443 if not specified
# context possible values - web_api (default) or gaia_api
def __init__(self, port=None, fingerprint=None, sid=None, server="127.0.0.1", http_debug_level=0,
api_calls=None, debug_file="", proxy_host=None, proxy_port=8080,
api_version=None, unsafe=False, unsafe_auto_accept=False, context="web_api"):
self.port = port
# management server fingerprint
self.fingerprint = fingerprint
# session-id.
self.sid = sid
# management server name or IP-address
self.server = server
# debug level
self.http_debug_level = http_debug_level
# an array with all the api calls (for debug purposes)
self.api_calls = api_calls if api_calls else []
# name of debug file. If left empty, debug data will not be saved to disk.
self.debug_file = debug_file
# HTTP proxy server address (without "http://")
self.proxy_host = proxy_host
# HTTP proxy port
self.proxy_port = proxy_port
# Management server's API version
self.api_version = api_version
# Indicates that the client should not check the server's certificate
self.unsafe = unsafe
# Indicates that the client should automatically accept and save the server's certificate
self.unsafe_auto_accept = unsafe_auto_accept
# The context of using the client - defaults to web_api
self.context = contextI believe the arguments that can be used in instances of the APIClientArgs class are intuitive for Check Point administrators and require no additional comments.
Connecting via APIClient and the context manager
Class APIClient is most conveniently done through the context manager. All that needs to be passed to the APIClient instance are the connection parameters defined in the previous step.
with APIClient(client_args) as client:
The context manager will not automatically execute the login call to the API server, however it will execute the logout call upon exit. If for some reason a logout is not required after working with the API calls, you need to start working without using the context manager:
client = APIClient(client_args)Connection check
The easiest way to verify if the connection parameters are passed correctly is by using the method check_fingerprint. If the SHA1 hash check for the API server's fingerprint certificate fails (the method returned False), this is usually due to connection issues, and we can either terminate the program (or allow the user to correct the connection data):
if client.check_fingerprint() is False:
print("Could not get the server's fingerprint - Check connectivity with the server.")
exit(1)
Note that the class APIClient will check the SHA1 fingerprint of the API server's certificate with every API call (methods api_call and api_query, which will be discussed shortly), and if an error is detected during the SHA1 fingerprint check (the certificate is unknown or has been changed), the method check_fingerprint will provide an opportunity to add/change the information about it on the local machine automatically. This check can be completely disabled (but this is only recommended when running scripts directly on the API server, when connecting to 127.0.0.1) using the APIClientArgs argument — unsafe_auto_accept (see more about APIClientArgs earlier in 'Defining connection parameters').
client_args = APIClientArgs(unsafe_auto_accept=True)Login to the API server
The APIClient there are a total of 3 methods for logging in to the API server, and each of them remembers the value sid(session-id), which is automatically used in each subsequent API call in the header (the name in the header for this parameter — X-chkp-sid), so there is no need to handle this parameter separately.
Login method
Option using login and password (in the example, the username admin and password 1q2w3e are passed as positional arguments):
login = client.login('admin', '1q2w3e') In the login method, additional optional parameters are also available; I list their names and default values:
continue_last_session=False, domain=None, read_only=False, payload=NoneLogin_with_api_key method
Option using an API key (supported from version R80.40 / Management API v1.6, "3TsbPJ8ZKjaJGvFyoFqHFA==") This is the API key value for one of the users on the management server using the API key authorization method:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==') In the method login_with_api_key the same optional parameters are available as in the method login.
The method login_as_root
The local machine login option with the API server:
login = client.login_as_root()For this method, only two optional parameters are available:
domain=None, payload=NoneAnd finally, the API calls themselves
We have two options for making API calls through methods api_call and api_query. Let's break down the differences between them.
api_call
This method is applicable for any calls. We need to pass the last part for the API call and the payload in the request body if necessary. If the payload is empty, it can be omitted altogether:
api_versions = client.api_call('show-api-versions') The output for this request is below:
In [23]: api_versions
Out[23]:
APIResponse({
"data": {
"current-version": "1.6",
"supported-versions": [
"1",
"1.1",
"1.2",
"1.3",
"1.4",
"1.5",
"1.6"
]
},
"res_obj": {
"data": {
"current-version": "1.6",
"supported-versions": [
"1",
"1.1",
"1.2",
"1.3",
"1.4",
"1.5",
"1.6"
]
},
"status_code": 200
},
"status_code": 200,
"success": true
})
show_host = client.api_call('show-host', {'name' : 'h_8.8.8.8'})The output for this request is below:
In [25]: show_host
Out[25]:
APIResponse({
"data": {
"color": "black",
"comments": "",
"domain": {
"domain-type": "domain",
"name": "SMC User",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"groups": [],
"icon": "Objects/host",
"interfaces": [],
"ipv4-address": "8.8.8.8",
"meta-info": {
"creation-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"creator": "admin",
"last-modifier": "admin",
"last-modify-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"lock": "unlocked",
"validation-state": "ok"
},
"name": "h_8.8.8.8",
"nat-settings": {
"auto-rule": false
},
"read-only": false,
"tags": [],
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
},
"res_obj": {
"data": {
"color": "black",
"comments": "",
"domain": {
"domain-type": "domain",
"name": "SMC User",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"groups": [],
"icon": "Objects/host",
"interfaces": [],
"ipv4-address": "8.8.8.8",
"meta-info": {
"creation-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"creator": "admin",
"last-modifier": "admin",
"last-modify-time": {
"iso-8601": "2020-05-01T21:49+0300",
"posix": 1588358973517
},
"lock": "unlocked",
"validation-state": "ok"
},
"name": "h_8.8.8.8",
"nat-settings": {
"auto-rule": false
},
"read-only": false,
"tags": [],
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
},
"status_code": 200
},
"status_code": 200,
"success": true
})
api_query
First, I should mention that this method is applicable only for calls whose output involves an offset. Such output occurs when it contains, or may contain, a large amount of information. For instance, this could be a request for a list of all created objects of the host type on the management server. For such requests, the API returns a list of 50 objects by default (which can be increased to 500 objects in the response). To avoid fetching information multiple times by changing the offset parameter in the API request, there is the api_query method that automates this task. Examples of calls where this method is needed: show-sessions, show-hosts, show-networks, show-wildcards, show-groups, show-address-ranges, show-simple-gateways, show-simple-clusters, show-access-roles, show-trusted-clients, show-packages. In fact, in the names of these API calls, we see words in the plural, so these calls will be easier to handle through api_query
show_hosts = client.api_query('show-hosts') The output for this request is below:
In [21]: show_hosts
Out[21]:
APIResponse({
"data": [
{
"domain": {
"domain-type": "domain",
"name": "SMC User",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "192.168.47.1",
"name": "h_192.168.47.1",
"type": "host",
"uid": "5d7d7086-d70b-4995-971a-0583b15a2bfc"
},
{
"domain": {
"domain-type": "domain",
"name": "SMC User",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "8.8.8.8",
"name": "h_8.8.8.8",
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
}
],
"res_obj": {
"data": {
"from": 1,
"objects": [
{
"domain": {
"domain-type": "domain",
"name": "SMC User",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "192.168.47.1",
"name": "h_192.168.47.1",
"type": "host",
"uid": "5d7d7086-d70b-4995-971a-0583b15a2bfc"
},
{
"domain": {
"domain-type": "domain",
"name": "SMC User",
"uid": "41e821a0-3720-11e3-aa6e-0800200c9fde"
},
"ipv4-address": "8.8.8.8",
"name": "h_8.8.8.8",
"type": "host",
"uid": "c210af07-1939-49d3-a351-953a9c471d9e"
}
],
"to": 2,
"total": 2
},
"status_code": 200
},
"status_code": 200,
"success": true
})
Processing API call results
After this, you can use the class's variables and methods APIResponse(both inside and outside the context manager). The class APIResponse defines 4 methods and 5 variables, we will focus in detail on the most important ones.

success
To start, it would be good to ensure that the API call was successful and returned a result. There is a method for this success:
In [49]: api_versions.success
Out[49]: True
Returns True if the API call was successful (Response code — 200) and False if unsuccessful (any other response code). Convenient to use immediately after the API call to display different information based on the response code.
if api_ver.success:
print(api_versions.data)
else:
print(api_versions.err_message) statuscode
Returns the response code after the API call execution.
In [62]: api_versions.status_code
Out[62]: 400
Possible response codes: 200,400,401,403,404,409,500,501.
set_success_status
At the same time, there may be a need to change the status value of success. Technically, anything can be placed there, even a regular string. However, a real example might be resetting this parameter to False under certain accompanying conditions. Below, note the example where there are tasks executed on the management server, but we will consider this request unsuccessful (setting the success variable to False, even though the API call was successful and returned code 200).
for task in task_result.data["tasks"]:
if task["status"] == "failed" or task["status"] == "partially succeeded":
task_result.set_success_status(False)
breakresponse()
The response method allows you to see the dictionary with the response code (status_code) and the response body (body).
In [94]: api_versions.response()
Out[94]:
{'status_code': 200,
'data': {'current-version': '1.6',
'supported-versions': ['1', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6']}}
data
Allows you to see only the response body (body) without unnecessary information.
In [93]: api_versions.data
Out[93]:
{'current-version': '1.6',
'supported-versions': ['1', '1.1', '1.2', '1.3', '1.4', '1.5', '1.6']}
error_message
This information is available only when there was an error processing the API request (response code do not 200). Example output
In [107]: api_versions.error_message
Out[107]: 'code: generic_err_invalid_parameter_nname: Unrecognized parameter [1]n'
Useful examples
Below are examples that utilize API calls added in Management API version 1.6.
First, let's consider how the calls work add-host and add-address-range. Suppose we need to create host-type objects for all IP addresses in the subnet 192.168.0.0/24, where the last octet equals 5, and all other IP addresses should be recorded as address range-type objects. In this case, the subnet address and the broadcast address should be excluded.
So, below is a script that solves this task and creates 50 host-type objects and 51 address range-type objects. The task requires 101 API calls (not counting the final publish call). Additionally, using the timeit module, we measure the time taken to execute the script until the changes are published.
Script using add-host and add-address-range
import timeit
from cpapi import APIClient, APIClientArgs
start = timeit.default_timer()
first_ip = 1
last_ip = 4
client_args = APIClientArgs(server="192.168.47.240")
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
for ip in range(5,255,5):
add_host = client.api_call("add-host", {"name" : f"h_192.168.0.{ip}", "ip-address": f'192.168.0.{ip}'})
while last_ip < 255:
add_range = client.api_call("add-address-range", {"name": f"r_192.168.0.{first_ip}-{last_ip}", "ip-address-first": f"192.168.0.{first_ip}", "ip-address-last": f"192.168.0.{last_ip}"})
first_ip+=5
last_ip+=5
stop = timeit.default_timer()
publish = client.api_call("publish")
print(f'Time to execute batch request: {stop - start} seconds')
In my lab environment, the execution of this script takes between 30 to 50 seconds depending on the load on the management server.
Now let's look at how to solve the same task using an API call add-objects-batch, support for which was added in API version 1.6. This call allows you to create multiple objects in one API request. Moreover, these can be objects of different types (for example, hosts, subnets, and address ranges). Thus, our task can be accomplished within a single API call.
Script using add-objects-batch
import timeit
from cpapi import APIClient, APIClientArgs
start = timeit.default_timer()
client_args = APIClientArgs(server="192.168.47.240")
objects_list_ip = []
objects_list_range = []
for ip in range(5,255,5):
data = {"name": f'h_192.168.0.{ip}', "ip-address": f'192.168.0.{ip}'}
objects_list_ip.append(data)
first_ip = 1
last_ip = 4
while last_ip < 255:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}", "ip-address-first": f"192.168.0.{first_ip}", "ip-address-last": f"192.168.0.{last_ip}"}
objects_list_range.append(data)
first_ip+=5
last_ip+=5
data_for_batch = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip
}, {
"type" : "address-range",
"list" : objects_list_range
}]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
add_objects_batch = client.api_call("add-objects-batch", data_for_batch)
stop = timeit.default_timer()
publish = client.api_call("publish")
print(f'Time to execute batch request: {stop - start} seconds')
The execution of this script in my lab environment takes between 3 to 7 seconds depending on the load on the management server. This means that, on average, for 101 objects, the batch API call runs 10 times faster. The difference will be even more impressive with a larger number of objects.
Now let's see how to work with set-objects-batch. With this API call, we can mass modify any parameter. Let's set the color sienna for the first half of the addresses from the previous example (up to .124 for hosts, as well as for ranges) and assign the color khaki to the second half of the addresses.
Changing the color of the objects created in the previous example
from cpapi import APIClient, APIClientArgs
client_args = APIClientArgs(server="192.168.47.240")
objects_list_ip_first = []
objects_list_range_first = []
objects_list_ip_second = []
objects_list_range_second = []
for ip in range(5,125,5):
data = {"name": f'h_192.168.0.{ip}', "color": "sienna"}
objects_list_ip_first.append(data)
for ip in range(125,255,5):
data = {"name": f'h_192.168.0.{ip}', "color": "khaki"}
objects_list_ip_second.append(data)
first_ip = 1
last_ip = 4
while last_ip < 125:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}", "color": "sienna"}
objects_list_range_first.append(data)
first_ip+=5
last_ip+=5
while last_ip < 255:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}", "color": "khaki"}
objects_list_range_second.append(data)
first_ip+=5
last_ip+=5
data_for_batch_first = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip_first
}, {
"type" : "address-range",
"list" : objects_list_range_first
}]
}
data_for_batch_second = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip_second
}, {
"type" : "address-range",
"list" : objects_list_range_second
}]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
set_objects_batch_first = client.api_call("set-objects-batch", data_for_batch_first)
set_objects_batch_second = client.api_call("set-objects-batch", data_for_batch_second)
publish = client.api_call("publish")
You can delete multiple objects in a single API call using delete-objects-batch. Now, let's look at a code example that deletes all hosts created earlier through add-objects-batch.
Deleting objects using delete-objects-batch
from cpapi import APIClient, APIClientArgs
client_args = APIClientArgs(server="192.168.47.240")
objects_list_ip = []
objects_list_range = []
for ip in range(5,255,5):
data = {"name": f'h_192.168.0.{ip}'}
objects_list_ip.append(data)
first_ip = 1
last_ip = 4
while last_ip < 255:
data = {"name": f"r_192.168.0.{first_ip}-{last_ip}"}
objects_list_range.append(data)
first_ip+=5
last_ip+=5
data_for_batch = {
"objects" : [ {
"type" : "host",
"list" : objects_list_ip
}, {
"type" : "address-range",
"list" : objects_list_range
}]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
delete_objects_batch = client.api_call("delete-objects-batch", data_for_batch)
publish = client.api_call("publish")
print(delete_objects_batch.data)
All the features that appear in new releases of Check Point software immediately gain API calls. For instance, R80.40 introduced features such as Revert to revision and Smart Task, and corresponding API calls were prepared for them right away. Moreover, all functionalities during the transition from Legacy consoles to Unified Policy mode are also gaining API support. For example, a highly anticipated update in software version R80.40 was the migration of the HTTPS Inspection policy from Legacy mode to Unified Policy mode, and this functionality immediately received API calls. Here’s an example of code that adds a rule to the top position of the HTTPS Inspection policy, exempting three categories (Health, Finance, Government services) from inspection, which is prohibited under the legislation in several countries.
Add a rule to the HTTPS Inspection policy
from cpapi import APIClient, APIClientArgs
client_args = APIClientArgs(server="192.168.47.240")
data = {
"layer" : "Default Layer",
"position" : "top",
"name" : "Legal Requirements",
"action": "bypass",
"site-category": ["Health", "Government / Military", "Financial Services"]
}
with APIClient(client_args) as client:
login = client.login_with_api_key('3TsbPJ8ZKjaJGvFyoFqHFA==')
add_https_rule = client.api_call("add-https-rule", data)
publish = client.api_call("publish")
Running Python scripts on the Check Point management server
The same applies here contains information on how to run Python scripts directly from the management server. This can be convenient when you do not have the ability to connect to the API server from another machine. I recorded a six-minute video where I discuss the installation of the module cpapi and the specifics of running Python scripts on the management server. As an example, a script is run that automates the configuration of a new gateway for a task such as network auditing. Security CheckUp. The challenges encountered included: in Python version 2.7 the function inputhas not yet appeared, so the function raw_inputis used to process the information that the user inputs. Otherwise, the code is the same as when running from other machines; it is just more convenient to use the function login_as_root, to avoid entering your own username, password, and server management IP address again.

Script for quick setup of Security CheckUp
from __future__ import print_function
import getpass
import sys, os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from cpapi import APIClient, APIClientArgs
def main():
with APIClient() as client:
# if client.check_fingerprint() is False:
# print("Could not get the server's fingerprint - Check connectivity with the server.")
# exit(1)
login_res = client.login_as_root()
if login_res.success is False:
print("Login failed:n{}".format(login_res.error_message))
exit(1)
gw_name = raw_input("Enter the gateway name:")
gw_ip = raw_input("Enter the gateway IP address:")
if sys.stdin.isatty():
sic = getpass.getpass("Enter one-time password for the gateway(SIC): ")
else:
print("Attention! Your password will be shown on the screen!")
sic = raw_input("Enter one-time password for the gateway(SIC): ")
version = raw_input("Enter the gateway version(like RXX.YY):")
add_gw = client.api_call("add-simple-gateway", {'name' : gw_name, 'ipv4-address' : gw_ip, 'one-time-password' : sic, 'version': version.capitalize(), 'application-control' : 'true', 'url-filtering' : 'true', 'ips' : 'true', 'anti-bot' : 'true', 'anti-virus' : 'true', 'threat-emulation' : 'true'})
if add_gw.success and add_gw.data['sic-state'] != "communicating":
print("Secure connection with the gateway hasn't established!")
exit(1)
elif add_gw.success:
print("The gateway was added successfully.")
gw_uid = add_gw.data['uid']
gw_name = add_gw.data['name']
else:
print("Failed to add the gateway - {}".format(add_gw.error_message))
exit(1)
change_policy = client.api_call("set-access-layer", {"name" : "Network", "applications-and-url-filtering": "true", "content-awareness": "true"})
if change_policy.success:
print("The policy has been changed successfully")
else:
print("Failed to change the policy- {}".format(change_policy.error_message))
change_rule = client.api_call("set-access-rule", {"name" : "Cleanup rule", "layer" : "Network", "action": "Accept", "track": {"type": "Detailed Log", "accounting": "true"}})
if change_rule.success:
print("The cleanup rule has been changed successfully")
else:
print("Failed to change the cleanup rule- {}".format(change_rule.error_message))
# publish the result
publish_res = client.api_call("publish", {})
if publish_res.success:
print("The changes were published successfully.")
else:
print("Failed to publish the changes - {}".format(install_tp_policy.error_message))
install_access_policy = client.api_call("install-policy", {"policy-package" : "Standard", "access" : 'true', "threat-prevention" : 'false', "targets" : gw_uid})
if install_access_policy.success:
print("The access policy has been installed")
else:
print("Failed to install access policy - {}".format(install_tp_policy.error_message))
install_tp_policy = client.api_call("install-policy", {"policy-package" : "Standard", "access" : 'false', "threat-prevention" : 'true', "targets" : gw_uid})
if install_tp_policy.success:
print("The threat prevention policy has been installed")
else:
print("Failed to install threat prevention policy - {}".format(install_tp_policy.error_message))
# add passwords and passphrases to dictionary
with open('additional_pass.conf') as f:
line_num = 0
for line in f:
line_num += 1
add_password_dictionary = client.api_call("run-script", {"script-name" : "Add passwords and passphrases", "script" : "printf "{}" >> $FWDIR/conf/additional_pass.conf".format(line), "targets" : gw_name})
if add_password_dictionary.success:
print("The password dictionary line {} was added successfully".format(line_num))
else:
print("Failed to add the dictionary - {}".format(add_password_dictionary.error_message))
main() Example file with a password dictionary additional_pass.conf
{
"passwords" : ["malware","malicious","infected","Infected"],
"phrases" : ["password","Password","Pass","pass","code","key","pwd","password","Password","Key","key","cipher","Cipher"]
}
Conclusion
This article discusses only the basic functionalities. Python SDK and the module cpapi(as you might have guessed, these are actually synonyms), and by examining the code in this module, you will discover even more possibilities for working with it. It's possible that you'll want to enhance it with your own classes, functions, methods, and variables. You can always share your developments and explore other scripts for Check Point in the section in the community , which brings together both product developers and users.
Happy coding and thank you for reading to the end!
Source: habr.com
