Python Forum

Full Version: API Post issue "TypeError: 'str' object is not callable"
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi, I am new to the forums and this is my first post.

I am new to python, more familiar with bash scripting, however I am trying to write a python script/program that will update a work repository for storing information on IP network information.

i.e. Network name, IPv4 range, IPv4 CIDR, IPv6 range, IPv6 CIDR, etc. etc. There are quite a lot of fields. Each network record is stored in a dictionary.

e.g (Values removed)

{'name': 'xxxx', 'ipv4_start': 'xxxx', 'ipv4_cidr': xx, 'ipv4_address_domain_id': xxxx, 'INFO-ipv4_address_domain_name': 'xxxx', 'ipv4_address_domain_range_id': xxxx, 'INFO-ipv4_address_domain_range_name': 'xxxxx', 'ipv4_allocation_template_id': xxxx, 'dhcp_relay_id': '', 'ipv6_start': 'xxxx::', 'ipv6_cidr': 64.0, 'ipv6_address_domain_id': xxxx, 'INFO-ipv6_address_domain_id': 'xxxxx', 'ipv6_address_domain_range_id': xxxxx, 'INFO-ipv6_address_domain_range_name': 'xxxxxx::/49', 'ipv6_allocation_template_id': xxxx, 'dhcpv6_relay_id': '', 'l2_vni_value': '', 'INFO-l2_vni_name': '', 'l2_domain_id': '', 'INFO-l2_domain_name': '', 'dns_domain_id': '', 'INFO-dns_domain_name': '', 'is_infoblox_synced': xxxx, 'is_private': xxxx, 'tenant_id': xxxx, 'INFO-tenant_name': 'xxxx', 'partition_id': xxxx, 'INFO-partition_name': 'xxxx', 'provider_id': xxxx, 'INFO-provider_name': 'xxxxx', 'consumer_id': xxxx, 'INFO-resp_consumer_name': 'xxxx', 'other_consumers': '', 'INFO-other_consumer_names': '', 'vlan_tag': xxxx, 'INFO-vlan_name': '', 'description': '', 'hashtags': '', 'discovery_organization_id': '', 'INFO-discovery_organization_name': 'xxxx', 'discovery_credential_id': '', 'INFO-discovery_credential_name': 'xxxx', 'discovery_scanner_id': '', 'INFO-discovery_scanner_name': 'xxxx', 'discovery_exclude_justification': 'xxxx', 'INFO-Comments-Notes': ''}

Not every key will have a value. Some networks might be IPv4 only for instance, so no IPv6 values. I used the "df.fillna" method to change the pandas "nan" values to be an empty string with " ".

I am testing a single dictionary entry against a test repository but I am getting an error "'str' object is not callable".

My code (using Jupyter Notebook)

import requests import json token = '12345678987654321' network = {'name': 'xxxx', 'ipv4_start': 'xxxx', 'ipv4_cidr': xx, 'ipv4_address_domain_id': xxxx, 'INFO-ipv4_address_domain_name': 'xxxx', 'ipv4_address_domain_range_id': xxxx, 'INFO-ipv4_address_domain_range_name': 'xxxxx', 'ipv4_allocation_template_id': xxxx, 'dhcp_relay_id': '', 'ipv6_start': 'xxxx::', 'ipv6_cidr': 64.0, 'ipv6_address_domain_id': xxxx, 'INFO-ipv6_address_domain_id': 'xxxxx', 'ipv6_address_domain_range_id': xxxxx, 'INFO-ipv6_address_domain_range_name': 'xxxxxx::/49', 'ipv6_allocation_template_id': xxxx, 'dhcpv6_relay_id': '', 'l2_vni_value': '', 'INFO-l2_vni_name': '', 'l2_domain_id': '', 'INFO-l2_domain_name': '', 'dns_domain_id': '', 'INFO-dns_domain_name': '', 'is_infoblox_synced': xxxx, 'is_private': xxxx, 'tenant_id': xxxx, 'INFO-tenant_name': 'xxxx', 'partition_id': xxxx, 'INFO-partition_name': 'xxxx', 'provider_id': xxxx, 'INFO-provider_name': 'xxxxx', 'consumer_id': xxxx, 'INFO-resp_consumer_name': 'xxxx', 'other_consumers': '', 'INFO-other_consumer_names': '', 'vlan_tag': xxxx, 'INFO-vlan_name': '', 'description': '', 'hashtags': '', 'discovery_organization_id': '', 'INFO-discovery_organization_name': 'xxxx', 'discovery_credential_id': '', 'INFO-discovery_credential_name': 'xxxx', 'discovery_scanner_id': '', 'INFO-discovery_scanner_name': 'xxxx', 'discovery_exclude_justification': 'xxxx', 'INFO-Comments-Notes': ''} response = requests.post('https://<url for repository>', auth=(token), data=json.dumps(network)) print(response)
The trace back I receive is

TypeError Traceback (most recent call last) ~\AppData\Local\Temp\ipykernel_27884\2338555186.py in <module> 6 network = {'name': 'xxxx', 'ipv4_start': 'xxxx', 'ipv4_cidr': xx, 'ipv4_address_domain_id': xxxx, 'INFO-ipv4_address_domain_name': 'xxxx', 'ipv4_address_domain_range_id': xxxx, 'INFO-ipv4_address_domain_range_name': 'xxxxx', 'ipv4_allocation_template_id': xxxx, 'dhcp_relay_id': '', 'ipv6_start': 'xxxx::', 'ipv6_cidr': 64.0, 'ipv6_address_domain_id': xxxx, 'INFO-ipv6_address_domain_id': 'xxxxx', 'ipv6_address_domain_range_id': xxxxx, 'INFO-ipv6_address_domain_range_name': 'xxxxxx::/49', 'ipv6_allocation_template_id': xxxx, 'dhcpv6_relay_id': '', 'l2_vni_value': '', 'INFO-l2_vni_name': '', 'l2_domain_id': '', 'INFO-l2_domain_name': '', 'dns_domain_id': '', 'INFO-dns_domain_name': '', 'is_infoblox_synced': xxxx, 'is_private': xxxx, 'tenant_id': xxxx, 'INFO-tenant_name': 'xxxx', 'partition_id': xxxx, 'INFO-partition_name': 'xxxx', 'provider_id': xxxx, 'INFO-provider_name': 'xxxxx', 'consumer_id': xxxx, 'INFO-resp_consumer_name': 'xxxx', 'other_consumers': '', 'INFO-other_consumer_names': '', 'vlan_tag': xxxx, 'INFO-vlan_name': '', 'description': '', 'hashtags': '', 'discovery_organization_id': '', 'INFO-discovery_organization_name': 'xxxx', 'discovery_credential_id': '', 'INFO-discovery_credential_name': 'xxxx', 'discovery_scanner_id': '', 'INFO-discovery_scanner_name': 'xxxx', 'discovery_exclude_justification': 'xxxx', 'INFO-Comments-Notes': ''} 7 ----> 8 response = requests.post('https://<url for respoitory>', auth=(token), data=json.dumps(network)) ~\Anaconda3\lib\site-packages\requests\api.py in post(url, data, json, **kwargs) 113 """ 114 --> 115 return request("post", url, data=data, json=json, **kwargs) 116 117 ~\Anaconda3\lib\site-packages\requests\api.py in request(method, url, **kwargs) 57 # cases, and look like a memory leak in others. 58 with sessions.Session() as session: ---> 59 return session.request(method=method, url=url, **kwargs) 60 61 ~\Anaconda3\lib\site-packages\requests\sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json) 571 hooks=hooks, 572 ) --> 573 prep = self.prepare_request(req) 574 575 proxies = proxies or {} ~\Anaconda3\lib\site-packages\requests\sessions.py in prepare_request(self, request) 482 483 p = PreparedRequest() --> 484 p.prepare( 485 method=request.method.upper(), 486 url=request.url, ~\Anaconda3\lib\site-packages\requests\models.py in prepare(self, method, url, headers, files, data, params, auth, cookies, hooks, json) 370 self.prepare_cookies(cookies) 371 self.prepare_body(data, files, json) --> 372 self.prepare_auth(auth, url) 373 374 # Note that prepare_auth must be last to enable authentication schemes ~\Anaconda3\lib\site-packages\requests\models.py in prepare_auth(self, auth, url) 601 602 # Allow auth to make its changes. --> 603 r = auth(self) 604 605 # Update self to reflect the auth changes. TypeError: 'str' object is not callable
I have looked on google, stackoverflow, youtube but I have not found any resolutions to this issue. If I run this same code into "https://httpbin.org/post" I receive a "200" response Huh

I am hoping that someone here may be able to point me in the right direction to resolve this issue.

Any assistance provide would be very much appreciated.

Cheers
your strings must be enclosed in single or double quotes.
here's a display routine that accesses all nodes of structure:
ipstructure = {'name': 'xxxx', 'ipv4_start': 'xxxx', 'ipv4_cidr': 'xx', 'ipv4_address_domain_id': 'xxxx', 'INFO-ipv4_address_domain_name': 'xxxx', 'ipv4_address_domain_range_id': 'xxxx', 'INFO-ipv4_address_domain_range_name': 'xxxxx', 'ipv4_allocation_template_id': 'xxxx', 'dhcp_relay_id': '', 'ipv6_start': 'xxxx::', 'ipv6_cidr': 64.0, 'ipv6_address_domain_id': 'xxxx', 'INFO-ipv6_address_domain_id': 'xxxxx', 'ipv6_address_domain_range_id': 'xxxxx', 'INFO-ipv6_address_domain_range_name': 'xxxxxx::/49', 'ipv6_allocation_template_id': 'xxxx', 'dhcpv6_relay_id': '', 'l2_vni_value': '', 'INFO-l2_vni_name': '', 'l2_domain_id': '', 'INFO-l2_domain_name': '', 'dns_domain_id': '', 'INFO-dns_domain_name': '', 'is_infoblox_synced': 'xxxx', 'is_private': 'xxxx', 'tenant_id': 'xxxx', 'INFO-tenant_name': 'xxxx', 'partition_id': 'xxxx', 'INFO-partition_name': 'xxxx', 'provider_id': 'xxxx', 'INFO-provider_name': 'xxxxx', 'consumer_id': 'xxxx', 'INFO-resp_consumer_name': 'xxxx', 'other_consumers': '', 'INFO-other_consumer_names': '', 'vlan_tag': 'xxxx', 'INFO-vlan_name': '', 'description': '', 'hashtags': '', 'discovery_organization_id': '', 'INFO-discovery_organization_name': 'xxxx', 'discovery_credential_id': '', 'INFO-discovery_credential_name': 'xxxx', 'discovery_scanner_id': '', 'INFO-discovery_scanner_name': 'xxxx', 'discovery_exclude_justification': 'xxxx', 'INFO-Comments-Notes': ''} def display_dict(dictname, level=0): indent = " " * (4 * level) for key, value in dictname.items(): if isinstance(value, dict): print(f'\n{indent}{key}') level += 1 self.display_dict(value, level) else: print(f'{indent}{key}: {value}') if level > 0: level -= 1 display_dict(ipstructure)
Results:
Output:
name: xxxx ipv4_start: xxxx ipv4_cidr: xx ipv4_address_domain_id: xxxx INFO-ipv4_address_domain_name: xxxx ipv4_address_domain_range_id: xxxx INFO-ipv4_address_domain_range_name: xxxxx ipv4_allocation_template_id: xxxx dhcp_relay_id: ipv6_start: xxxx:: ipv6_cidr: 64.0 ipv6_address_domain_id: xxxx INFO-ipv6_address_domain_id: xxxxx ipv6_address_domain_range_id: xxxxx INFO-ipv6_address_domain_range_name: xxxxxx::/49 ipv6_allocation_template_id: xxxx dhcpv6_relay_id: l2_vni_value: INFO-l2_vni_name: l2_domain_id: INFO-l2_domain_name: dns_domain_id: INFO-dns_domain_name: is_infoblox_synced: xxxx is_private: xxxx tenant_id: xxxx INFO-tenant_name: xxxx partition_id: xxxx INFO-partition_name: xxxx provider_id: xxxx INFO-provider_name: xxxxx consumer_id: xxxx INFO-resp_consumer_name: xxxx other_consumers: INFO-other_consumer_names: vlan_tag: xxxx INFO-vlan_name: description: hashtags: discovery_organization_id: INFO-discovery_organization_name: xxxx discovery_credential_id: INFO-discovery_credential_name: xxxx discovery_scanner_id: INFO-discovery_scanner_name: xxxx discovery_exclude_justification: xxxx INFO-Comments-Notes:
(Oct-29-2022, 08:13 PM)Larz60+ Wrote: [ -> ]your strings must be enclosed in single or double quotes.
here's a display routine that accesses all nodes of structure:

Hi Larz60

Thank you for the response, it is very much appreciated.

I believe my strings were all in quotes, however I did notice that when I used the "fillna" method I used double quotes to replace the pandas "nan" values instead of single quotes and all other string "Key/pair" values used double quotes. So I changed the "fillna" to use single quotes to make everything the same, but it still does not work. I also checked against what the API is expecting to make sure I was using the correct names and types for the dictionary key/value pairs and I am.

I am wondering if my issue could be with the way I am trying to use the API key/token?

The token provided consists of numbers and letters and when I use the assignment method token ='123a456b798c8766d534f321e1' I get the error "TypeError: 'str' object is not callable" as reported.

However I have been watching some YouTube videos on using API POST requests where the showed to use something like "my_headers = {'Authorization': 'Bearer {123a456b798c8766d534f321e1}'}" and then add "headers=my_headers" to the URL. When I try this method of sending the API key I get a SSL error

--------------------------------------------------------------------------- SSLCertVerificationError Traceback (most recent call last) File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py:703, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw) 702 # Make the request on the httplib connection object. --> 703 httplib_response = self._make_request( 704 conn, 705 method, 706 url, 707 timeout=timeout_obj, 708 body=body, 709 headers=headers, 710 chunked=chunked, 711 ) 713 # If we're going to release the connection in ``finally:``, then 714 # the response doesn't need to know about the connection. Otherwise 715 # it will also try to release it and we'll have a double-release 716 # mess. File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py:386, in HTTPConnectionPool._make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw) 385 try: --> 386 self._validate_conn(conn) 387 except (SocketTimeout, BaseSSLError) as e: 388 # Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout. File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py:1042, in HTTPSConnectionPool._validate_conn(self, conn) 1041 if not getattr(conn, "sock", None): # AppEngine might not have `.sock` -> 1042 conn.connect() 1044 if not conn.is_verified: File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connection.py:414, in HTTPSConnection.connect(self) 412 context.load_default_certs() --> 414 self.sock = ssl_wrap_socket( 415 sock=conn, 416 keyfile=self.key_file, 417 certfile=self.cert_file, 418 key_password=self.key_password, 419 ca_certs=self.ca_certs, 420 ca_cert_dir=self.ca_cert_dir, 421 ca_cert_data=self.ca_cert_data, 422 server_hostname=server_hostname, 423 ssl_context=context, 424 tls_in_tls=tls_in_tls, 425 ) 427 # If we're using all defaults and the connection 428 # is TLSv1 or TLSv1.1 we throw a DeprecationWarning 429 # for the host. File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\util\ssl_.py:449, in ssl_wrap_socket(sock, keyfile, certfile, cert_reqs, ca_certs, server_hostname, ssl_version, ciphers, ssl_context, ca_cert_dir, key_password, ca_cert_data, tls_in_tls) 448 if send_sni: --> 449 ssl_sock = _ssl_wrap_socket_impl( 450 sock, context, tls_in_tls, server_hostname=server_hostname 451 ) 452 else: File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\util\ssl_.py:493, in _ssl_wrap_socket_impl(sock, ssl_context, tls_in_tls, server_hostname) 492 if server_hostname: --> 493 return ssl_context.wrap_socket(sock, server_hostname=server_hostname) 494 else: File ~\AppData\Local\Programs\Python\Python39\lib\ssl.py:500, in SSLContext.wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname, session) 494 def wrap_socket(self, sock, server_side=False, 495 do_handshake_on_connect=True, 496 suppress_ragged_eofs=True, 497 server_hostname=None, session=None): 498 # SSLSocket class handles server_hostname encoding before it calls 499 # ctx._wrap_socket() --> 500 return self.sslsocket_class._create( 501 sock=sock, 502 server_side=server_side, 503 do_handshake_on_connect=do_handshake_on_connect, 504 suppress_ragged_eofs=suppress_ragged_eofs, 505 server_hostname=server_hostname, 506 context=self, 507 session=session 508 ) File ~\AppData\Local\Programs\Python\Python39\lib\ssl.py:1040, in SSLSocket._create(cls, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname, context, session) 1039 raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets") -> 1040 self.do_handshake() 1041 except (OSError, ValueError): File ~\AppData\Local\Programs\Python\Python39\lib\ssl.py:1309, in SSLSocket.do_handshake(self, block) 1308 self.settimeout(None) -> 1309 self._sslobj.do_handshake() 1310 finally: SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123) During handling of the above exception, another exception occurred: MaxRetryError Traceback (most recent call last) File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py:489, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies) 488 if not chunked: --> 489 resp = conn.urlopen( 490 method=request.method, 491 url=url, 492 body=request.body, 493 headers=request.headers, 494 redirect=False, 495 assert_same_host=False, 496 preload_content=False, 497 decode_content=False, 498 retries=self.max_retries, 499 timeout=timeout, 500 ) 502 # Send the request. 503 else: File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py:787, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw) 785 e = ProtocolError("Connection aborted.", e) --> 787 retries = retries.increment( 788 method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2] 789 ) 790 retries.sleep() File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\util\retry.py:592, in Retry.increment(self, method, url, response, error, _pool, _stacktrace) 591 if new_retry.is_exhausted(): --> 592 raise MaxRetryError(_pool, url, error or ResponseError(cause)) 594 log.debug("Incremented Retry for (url='%s'): %r", url, new_retry) MaxRetryError: HTTPSConnectionPool(host='<FQDN of API>', port=443): Max retries exceeded with url:<End Point> (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)'))) During handling of the above exception, another exception occurred: SSLError Traceback (most recent call last) Cell In [13], line 9 6 my_headers = {'Authorization': 'Bearer {123a456b798c8766d534f321e1}'} 7 network = {'name': 'xxxx', 'ipv4_start': 'xxxx', 'ipv4_cidr': 'xx', 'ipv4_address_domain_id': 'xxxx', 'INFO-ipv4_address_domain_name': 'xxxx', 'ipv4_address_domain_range_id': 'xxxx', 'INFO-ipv4_address_domain_range_name': 'xxxxx', 'ipv4_allocation_template_id': 'xxxx', 'dhcp_relay_id': '', 'ipv6_start': 'xxxx::', 'ipv6_cidr': 64.0, 'ipv6_address_domain_id': 'xxxx', 'INFO-ipv6_address_domain_id': 'xxxxx', 'ipv6_address_domain_range_id': 'xxxxx', 'INFO-ipv6_address_domain_range_name': 'xxxxxx::/49', 'ipv6_allocation_template_id': 'xxxx', 'dhcpv6_relay_id': '', 'l2_vni_value': '', 'INFO-l2_vni_name': '', 'l2_domain_id': '', 'INFO-l2_domain_name': '', 'dns_domain_id': '', 'INFO-dns_domain_name': '', 'is_infoblox_synced': 'xxxx', 'is_private': 'xxxx', 'tenant_id': 'xxxx', 'INFO-tenant_name': 'xxxx', 'partition_id': 'xxxx', 'INFO-partition_name': 'xxxx', 'provider_id': 'xxxx', 'INFO-provider_name': 'xxxxx', 'consumer_id': 'xxxx', 'INFO-resp_consumer_name': 'xxxx', 'other_consumers': '', 'INFO-other_consumer_names': '', 'vlan_tag': 'xxxx', 'INFO-vlan_name': '', 'description': '', 'hashtags': '', 'discovery_organization_id': '', 'INFO-discovery_organization_name': 'xxxx', 'discovery_credential_id': '', 'INFO-discovery_credential_name': 'xxxx', 'discovery_scanner_id': '', 'INFO-discovery_scanner_name': 'xxxx', 'discovery_exclude_justification': 'xxxx', 'INFO-Comments-Notes': ''} ----> 9 response = requests.post('https://<URL to API + End Point>/', headers=my_headers, data=network ) 10 print(response) File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\api.py:115, in post(url, data, json, **kwargs) 103 def post(url, data=None, json=None, **kwargs): 104 r"""Sends a POST request. 105 106 :param url: URL for the new :class:`Request` object. (...) 112 :rtype: requests.Response 113 """ --> 115 return request("post", url, data=data, json=json, **kwargs) File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\api.py:59, in request(method, url, **kwargs) 55 # By using the 'with' statement we are sure the session is closed, thus we 56 # avoid leaving sockets open which can trigger a ResourceWarning in some 57 # cases, and look like a memory leak in others. 58 with sessions.Session() as session: ---> 59 return session.request(method=method, url=url, **kwargs) File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py:587, in Session.request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json) 582 send_kwargs = { 583 "timeout": timeout, 584 "allow_redirects": allow_redirects, 585 } 586 send_kwargs.update(settings) --> 587 resp = self.send(prep, **send_kwargs) 589 return resp File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py:701, in Session.send(self, request, **kwargs) 698 start = preferred_clock() 700 # Send the request --> 701 r = adapter.send(request, **kwargs) 703 # Total elapsed time of the request (approximately) 704 elapsed = preferred_clock() - start File ~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py:563, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies) 559 raise ProxyError(e, request=request) 561 if isinstance(e.reason, _SSLError): 562 # This branch is for urllib3 v1.22 and later. --> 563 raise SSLError(e, request=request) 565 raise ConnectionError(e, request=request) 567 except ClosedPoolError as e: SSLError: HTTPSConnectionPool(host='<URL to API>', port=443): Max retries exceeded with url: <End Point>/ (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)')))
I tried using "verify=False" in the URL but that just gave me a 401 and a warning advising that "Adding verification is strongly advised".

I have not been successful in getting a GET request to work from python, but it works from a Linux distro (WSL) on my laptop using the "curl" command.

If anyone has any more pointers it woudl be much appreciated.

Cheers.