--- title: "REST API" slug: "rest-api-v6-7" description: "Explore AppGate ZTNA's REST API for Controller management, enabling scriptable actions like policy entitlement updates and user management." tags: ["REST API"] updated: 2026-03-17T15:57:20Z published: 2026-04-03T16:41:06Z canonical: "support.appgate.com/rest-api-v6-7" --- > ## Documentation Index > Fetch the complete documentation index at: https://support.appgate.com/llms.txt > Use this file to discover all available pages before exploring further. # REST API The admin UI for AppGate ZTNA exclusively uses REST API calls to the Controller. AppGate provides a sub-set of these Controller APIs written in OpenApi v3 format for general usage. If you specifically need to use an undocumented API call, contact [Appgate support](/v1/docs/contact-support). The Controller APIs will let you do pretty much everything the admin can do through the UI. If you want to add an entitlement to a policy, this can be scripted on an external system and actioned using the appropriate REST API call. For instance, this would allow some provisioning system to add the related entitlement for a new server instance it has just created. ## Getting started with the Controller REST API You will need: - [Admin access](/v1/docs/adminapi-tls-connection-v6-7) to port 8443 of a Controller appliance. - An API user with relevant permissions set and excluded from 2FA, in [Settings > Admin OTP](/v1/docs/mfa-for-admins-v6-7). - The [API Specification](https://support.appgate.com/apidocs). The same admin rights that have been set up for that user in the admin UI apply to these REST APIs also. So an admin who only has admin rights for entitlements will only be able to use get /entitlements, get /entitlements/{id}, put /entitlements/{id} and post /entitlements. The code example below will listen to AppGate ZTNA audit logs (via rsyslog messages) and act on ALERT messages, such as removing users' onboarding cookie or adding the user to the denylist. ## Code Example using Controller APIs ```python import json        import socketserver        import sys        import os        import requests        # edit the values below        CONTROLLER_URL = "https://controller1.company.com:8443"        CA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "ca.pem")        PROVIDER = "local"        USERNAME = "username"        PASSWORD = "password"        API_VERSION = 22        # do not edit anything below        LISTEN_HOST, LISTEN_PORT = "127.0.0.1", 5140        class SyslogHandler(socketserver.BaseRequestHandler):        def handle(self):        data = bytes.decode(self.request[0].strip())        if len(data) == 0:        print("zero len message received")        return        # parse to JSON        jlog = json.loads(data)        # print(jlog["event_type"] + " received")        if jlog["event_type"] == "ip_access" and jlog["action"] == "alert":        dn = jlog["distinguished_name"]        print(f"ALERT received for {dn}")        blacklist_user(dn)        revoke_tokens(dn)        else:        # print("skipping " + jlog["event_type"])        pass        def login():        headers = {"Accept": f"application/vnd.appgate.peer-v{API_VERSION}+json",        "Content-Type": "application/JSON"}        # authenticate        data = {"machineId": "f0031c00-0522-43b3-a642-ae23cfd1bc22",        "providerName": PROVIDER, "username": USERNAME, "password": PASSWORD}        res = requests.post(f"{CONTROLLER_URL}/admin/login",        verify=CA_PATH, headers=headers, data=json.dumps(data), timeout=5)        if res.status_code != 200:        print(f"CONTROLLER_URL login failed with http {str(res.status_code)}")        sys.exit(-1)        token = json.loads(res.text)["token"]        headers["Authorization"] = f"Bearer {token}"        return headers        def blacklist_user(dn):        auth_headers = login()        # dn without deviceid        user_dn = dn.split(",", 1)[1]        data = {"userDistinguishedName": user_dn, "reason": "suspicious traffic"}        res = requests.post(f"{CONTROLLER_URL}/admin/blacklist",        data=json.dumps(data), verify=CA_PATH, headers=auth_headers)        print(f"{user_dn} blacklisted {str(res.status_code)}")        return res.status_code        def revoke_tokens(dn):        auth_headers = login()        data = {"distinguishedNameFilter": dn, "revocationReason": "api revocation for alert", "delayMinutes": 0}        res = requests.post(f"{CONTROLLER_URL}/admin/on-boarded-devices/revoke-tokens",        data=json.dumps(data), verify=CA_PATH, headers=auth_headers)        print(f"{dn} tokens revoked {str(res.status_code)}")        return res.status_code        if __name__ == "__main__":        print("========================================================")        print(f"Appgate SDP Alert Handler Started on {str(LISTEN_PORT)}")        print("========================================================")        with socketserver.UDPServer((LISTEN_HOST, LISTEN_PORT), SyslogHandler) as server:        server.serve_forever(poll_interval=0.5) ``` AppGate reserves the right to change any of the REST API calls when a new version of AppGate ZTNA is released. Where any changes are made, the documentation will be updated accordingly. Any script provided from the AppGate Professional Services team or as example scripts from the manual are delivered as is, without warranty of any kind. AppGate disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. Any maintenance needs arising out of the use or performance of these sample scripts (and related documentation) remains the responsibility of the customer.