Python requests.put() is giving error: Invalid API call, Wrong method or URL - python-3.x

I have been trying to do a put request via BambooHR api to add a time off request. But it gives 404 and the header gives "Invalid API call, Wrong method or URL"
I couldn't understand what's wrong with my code. Add a time off request from Bamboo HR documentation is /api/gateway.php/{company}/v1/employees/{employee id}/time_off/request/ Sample: PUT /api/gateway.php/test/v1/employees/1/time_off/request/
import requests
url = 'https://api.bamboohr.com/api/gateway.php/johnsnowlabs/v1/employees/96/time_off/requests/?status=requested'
response1= requests.put(url, auth=('68d4165c9262fcf2302745a6d791b23dsfsd4107','John11')
print(response1.status_code)
it gives 404 and when response1.headers then the error message says Invalid API call, Wrong method or URL
I tried different combination of inputs in url but none seems to be working. However, all the GET requests are working, it's only the PUT one is not working.

Related

aiohttp response.json raises getaddrinfo failed error if after response.status but works ok if before

---UPDATED 10/20/2022---
After some further digging, it turns out the problem described below has nothing to do with aiohttp. The issue is that the response (which is a FHIR resource bundle) contains paginated data. And the URL that the server was returning for the pagination links was invalid (it has the hshweb domain referenced in my question below; my guess is it referred to some internal address that's not exposed outside their firewall). My sample code below shows fetching the initial response, what's not shown is that there is additional processing to get subsequent pages. And because the pagination links were invalid, it was those subsequent page fetches that were failing.
---ORIGINAL POST---
Background
I've been using aiohttp to fetch JSON data from APIs of different companies; my code has been running fine for over a year now.
In the code snippet below, I query the endpoint, and if the status is OK I then get the JSON content using response.json
async with await session.get(url, headers=self.headers) as response:
logger.info(f'Received response to {url}',
extra={**self.log_dict, 'httpstatus': response.status}
)
if response.status in [200, 206]:
try:
response_json = await response.json(content_type=None)
break
except json.decoder.JSONDecodeError:
response_json = None
logger.warning((f'Invalid JSON querying {url}; '
f'status code {response.status}. Skipping.'),
extra=self.log_dict
)
break
This has been working as expected so far.
Problem
With the latest company whose API I'm attempting to integrate with, I'm hitting API https://api.mvphealthcare.com.... and am getting a 200 response status, however when attempting to then get the JSON payload with response.json() I get the following error:
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host hshweb.mvphealthcare.com:443 ssl:default [getaddrinfo failed]
The identical GET request from Postman works exactly as expected.
Note that the URL in this error message (hshweb.mvphealthcare.com) is different from the original that I queried (api.mvphealthcare.com).
Attempting to ping hshweb.mvphealthcare.com from the command line results in Ping request could not find host hshweb.mvphealthcare.com. Please check the name and try again. so the getaddrinfo failed error itself sort of makes sense. What's unclear is why aiohttp is attempting to hit that other address.
While not exactly the same issue, this SO question suggested that there are instances where using response.json() after response.ok could be problematic. So I temporarily modified my code to call await response.json() before the call to response.status and was able to get the response! As the SO answer suggested the issue is fixed in aiohttp 3.8, I upgraded my library (was previously using 3.7.4). However, that did not resolve the problem if calling response.json() was after response.status.
Questions
Why does calling reponse.json() work if it is before response.status, but not after?
What's going on behind the scenes that's causing the URL to change (and if hshweb.mvphealthcare.com is not resolvable anyway, why does it work if response.json() is called before response.status)
What do I need to do to make this work?

400 and 404 error mismatch / inconsistent for get and post

I am working on an API Specification in Swagger which is behaving in an unknown manner.
Request URL: https://api-de.test.com.au/v2/poc/quotes/12345/tc
Request Type : GET
Here 12345 is the id that needs to be passed to fetch info
If ID is blank : https://api-de.test.com.au/v2/poc/quotes//tc
I am not getting 404 Resource Not Found
Wherein, I have created another API that has a similar type of URL but the API is of type POST, there the status code is returning 404.
My question is why a similar type of URL is getting me a different status code for GET and POST.

Error: Invalid WSDL URL, seems like "?wsdl" is being replaced by "xsd=xsd1"

I'm using a node soap client to connect to the Bing Ads API and I log the URL within the sendRequest() method:
https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?wsdl
Which is correct according to the Bing docs here.
But when I get the error output (after the code hangs) it's a different URL. The entire error is:
Error: Invalid WSDL URL: https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?xsd=xsd1
Side by side of the two URLs:
https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?wsdl
https://clientcenter.api.bingads.microsoft.com/Api/CustomerManagement/v13/CustomerManagementService.svc?xsd=xsd1
It looks like the only difference is that wsdl in the correct URL is being replaced by xsd=xsd1.
Also, I know very little about SOAP APIs so I'm just trying to figure out what is happening.
Why is the URL being altered?

Getting INVALID_REQUEST_BODY error on accessing create_template_view api

I am trying to access the api TemplateViews : createEdit using python docusign_esign api as below
api_client = ApiClient(header_name="Authorization", header_value=f"Bearer {access_token}",
host="https://demo.docusign.net/restapi/")
TemplatesApi(api_client).create_edit_view(account_id=account_id, template_id=template_id)
while accessing the create_edit_view I am getting the error as
"errorCode":"INVALID_REQUEST_BODY","message":"The request body is missing or improperly formatted."
when checked in the API explorer, I am able to get the response URL correctly. I found only the accountId and templateId is mandatory for accessing the api, am I missing something else here?
https://developers.docusign.com/docs/esign-rest-api/sdk-tools/python/reference/docusign_esign/apis/templates_api.html#docusign_esign.apis.templates_api.TemplatesApi.create_edit_view
You need to provide a return_url, it's a URL that your embedded sender will be redirected back to when they finished editing/creating the template.
This is a POST and this URL is provided in the body as JSON, not in the URL as a parameter.
https://developers.docusign.com/docs/esign-rest-api/reference/templates/templateviews/createedit/

PRIVACY Card API Authorization

I have recently been working with API's but I am stuck on one thing and it's been holding me back for a few days.
I am trying to work with Privacy's API and I do not understand the Authentication/Authorization process. When I enter the url in a browser I get the error "message": "Please provide API key in Authorization header", even when I use the correct format of Authorization. I also get an error when I make a request in Python. The format I'm using for the url is https://api.privacy.com/v1/card "Authorization: api-key:".
If someone could explain how to work this or simply give an example of how I would make a request through Python3. The API information is in the link below.
Thank you in advance.
https://developer.privacy.com/docs
This is the code I am using in Python. After I run this I receive a 401 status code.
import requests
headers={'Authorization': 'api-key:200e6036-6894-xxxx-xxxx-xxxx'}
url = 'https://api.privacy.com/v1/card'
r = requests.get(url)
print("Status code:", r.status_code)
You need to add the authentication header to the get call. It isn't enough to include it in a header variable. You need to provide those headers to requests
import requests
response = requests.get('https://api.privacy.com/v1/card', headers={'Authorization': 'api-key 65a9566c-XXXXXXXXXXXX'})
print(response.json())

Resources