What is the best way to make this code dry? I have a script that makes a bunch of api calls (xml) and it's not adhering to DRY because I am repeating a lot of the code in the functions, what would be the best way to clean this up and reduce the amount of repeat code?
def get_api_key(hostname, username, password):
    url = 'https://' + hostname + '/api'
    values = {'type': 'keygen', 'user': username, 'password': password}
    response = requests.post(url, params=values, verify=False, proxies=proxies)
    return ET.fromstring(response.text).find('.//result/key').text

def add_template(hostname, api_key, template_name, name):
    url = 'https://' + hostname + '/api'
    values = {'type': 'config',
        'action': 'set',
        'xpath': f&quot;entry[@name='{template_name}']/&quot;,
        'element': f&quot;&lt;tag&gt;{name}&lt;/tag&gt;&quot;,
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(template_name)

def add_template_stack(hostname, api_key, stack_name, template_name):
    url = 'https://' + hostname + '/api'
    values = {'type': 'config',
        'action': 'set',
        'xpath': f&quot;entry[@name='{stack_name}']&quot;,
        'element': f&quot;&lt;tag&gt;{template_name}&lt;/tag&gt;&quot;,
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(stack_name)

def add_variable(template_name, var_name, netmask, hostname, api_key): 
    url = 'https://' + hostname + '/api'
    values = {'type': 'config',
        'action': 'set',
        'xpath': f&quot;entry[@name='{template_name}']/variable/entry[@name='{var_name}']&quot;,
        'element': f&quot;&lt;tag&gt;{netmask}&lt;/tag&gt;&quot;,
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(var_name)
I think a good way to reduce the WET code here is to consolidate and generalize the core functionality to a single function, and tweak the arguments going into it accordingly. I left the get_api_key function alone and focused on the other ones as they are the most similar. See below:
def add_template_2(hostname, api_key, template_name, name):
    return add(hostname, api_key, template_name, name)


def add_template_stack_2(hostname, api_key, stack_name, template_name):
    return add(hostname, api_key, stack_name, template_name)


def add_variable_2(template_name, var_name, netmask, hostname, api_key):
    return add(hostname, api_key, template_name, netmask, var_name)


def add(hostname, api_key, xpath_name, element, xpath_var=None):
    url = f'https://{hostname}/api'

    if xpath_var:
        xpath = f&quot;entry[@name='{xpath_name}']/variable/entry[@name='{xpath_var}']&quot;
        ret_val = xpath_var
    else:
        xpath = f&quot;entry[@name='{xpath_name}']&quot;
        ret_val = xpath_name

    values = {'type': 'config',
        'action': 'set',
        'xpath': xpath,
        'element': f&quot;&lt;tag&gt;{element}&lt;/tag&gt;&quot;,
        'key': api_key
        }
    requests.post(url, params=values, verify=False, proxies=proxies)
    return(ret_val)