I want to call an API from Qualtrics in R using httr2 package. However, even though I think I have the right setup I'm always getting an error.
Here's a simple endpoint I want to call: And here's how Qualtrics wants me to setup my oauth credentials:
I can confirm taht I have correctly setup my credentials (Qualtrics support confirmed) and the Qualtrics support was able to get the API running through python with my credentials. So it's really a question on how to get the right R code.
Here's what I did:
library(httr2)
get_user <- request(";) |>
req_oauth_auth_code(client = oauth_client(id = "my client id",
secret = "my client secret",
token_url = ";),
scope = "manage:all",
token_params = list("grant_type" = "client_credentials"),
auth_url = ";) |>
req_perform()
This code is supposed to open a browser window where I could enter my Qualtrics login details. However, instead the following error page opens:
Any idea on what I did wrong?
BTW, I also tried to translate from curl to httr2 here: / But it didn't work
BTW2: here's the python code the support used and that did run successfully for them:
# List Users with OAuth 2.0 Authentication
import requests
import json
import logging from datetime
import datetime import base64
# Setting up logging
logging.basicConfig( filename='api_response.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' )
# OAuth 2.0 Configuration
client_id = "my client id"
client_secret = "my client secret"
dataCenter = 'fra1'
token_url = f"https://{dataCenter}.qualtrics/oauth2/token"
api_base_url = f"https://{dataCenter}.qualtrics/API/v3/users"
# Step 1: Get access token using client credentials flow
client_credentials = f"{client_id}:{client_secret}"
encoded_credentials = base64.b64encode(client_credentials.encode()).decode()
token_headers = {
"Authorization": f"Basic {encoded_credentials}",
"Content-Type": "application/x-www-form-urlencoded" }
token_data = { "grant_type": "client_credentials", "scope": "manage:all"
# Adjust scopes as needed for your application
}
logging.info("Requesting OAuth 2.0 access token...")
token_response = requests.post(token_url, headers=token_headers, data=token_data)
logging.info(f"Token request status code: {token_response.status_code}")
try: token_info = token_response.json()
access_token = token_info["access_token"] logging.info("Access token obtained successfully")
except Exception as e: logging.error(f"Failed to obtain access token: {e}") logging.info(f"Token response: {token_response.text}")
print("Failed to obtain access token. Check the log for details.") exit(1)
# Step 2: Use the access token to call the API
headers = { "Authorization": f"Bearer {access_token}" }
logging.info("Making API request to fetch users...")
response = requests.get(api_base_url, headers=headers)
# Log the response
logging.info(f"API request status code: {response.status_code}")
try: json_response = json.dumps(response.json(), indent=4)
logging.info(f"Response: {json_response}") print(json.loads(json_response))
# Print formatted JSON to console except Exception as e: logging.error(f"Failed to parse response as JSON: {e}")
logging.info(f"Raw response: {response.text}") print(f"Error: {e}") print(f"Raw response: {response.text}")
EDIT: I got it running with the following code. However, I have no idea why it works, because it looks like I'm dumping all parameters into the body whereas I thought that httr2 has specific functions for authorization and token. In addition, there wasn't even a browser window that opened where I had to enter my username/pw.
get_token <- request(";) |>
req_method("POST") |>
req_body_multipart(grant_type = "client_credentials",
client_id = "my client id",
client_secret = "my client secret",
scope = "manage:all",
encode = "form") |>
req_perform()
bearer <- resp_body_json(get_token)$access_token
get_users <- request(";) |>
req_method("GET") |>
req_auth_bearer_token(bearer) |>
req_perform()