{"_id":"5aaab8cd311eea001e60e7f0","project":"55843604fd8d910d007b9502","version":{"_id":"558444ceafccfd0d00fcb2bb","forked_from":"55843604fd8d910d007b9505","project":"55843604fd8d910d007b9502","__v":65,"createdAt":"2015-06-19T16:35:26.435Z","releaseDate":"2015-06-19T16:35:26.435Z","categories":["558444cfafccfd0d00fcb2bc","558444cfafccfd0d00fcb2bd","55ad4ce733616a0d00599d2e","55ad4cef6aadf20d0015b764","55ad4cf36aadf20d0015b765","55ad4cfb24cf160d0013584f","55ad4d0024cf160d00135850","55ad4d0a24cf160d00135851","55ad4d0d24cf160d00135852","55ad4d126aadf20d0015b766","55ad4d1624cf160d00135853","55ad4d1933616a0d00599d2f","55ad4d2233616a0d00599d30","55ad4d2e24cf160d00135854","55d35b6bf77e6d0d00b1b092","55d3649a0168850d0073f14a","55d366d40168850d0073f15a","55d37fcff77e6d0d00b1b13f","55d383e50168850d0073f1e1","55d3ac26c336ec0d007c2251","55d3c51cb2330119009c31db","55d3c59bfe37111900e536f3","55d3c5a7fe37111900e536f4","55d3c5b4fe37111900e536f5","55d3c5d4fe37111900e536f6","55d3c5d6b2330119009c31df","55d3c5d71f478b170077c164","55d3c687b2330119009c31e4","55d3c6a4fe37111900e536f9","55d3c6befe37111900e536fa","55d3c6e8d2c66f0d00497f93","55d49dcfd7c16b2d007de905","55d4ca8f5082980d0009c79b","55d4cab9c95a3d2f0069ad3d","55d4d279c95a3d2f0069ad60","55d4d9355082980d0009c7e1","55d4f6b5988e130d000b3eb1","55d64dc8e60a2f0d00b88ecb","5627ca43fcbbc621004ec07d","56c64a0d8f98b50d0012c37c","56f1b8b13eb62a34003ea041","56f1b9df4476fb2200795e8c","57f6907dca5e5d1700039ae9","591dd06ca266c423002ec4ca","59234825e465c11900922518","5936f82eaa591e0027638d57","59972f54fd7078001992c136","599c6da8f180820025f14909","59b054613c3e1b0019cf27d9","59b1ceca2d6231003ad73e5f","59b1cf1857911600382e0dc4","59b1cf2730f3d60010c30ef7","59b1cf385d4b89003035441a","59b1cf5857911600382e0dc6","59bc2c4e26ac9b0010a8b753","59bc2ce20b3eb30010657b70","59f0c793ba3bc90030f413ab","59f0cd62f5ecda00325294b9","59fb55a8e8d0f600101aedc3","59fcb05c067f8d0028613f86","5a2af4a1bc5fba00283909c1","5a83673b0e56010012138c12","5a972f2e77b85a0070e4ebe2","5aa300224ed4b40012c53e1d","5acd20095efd8d000359bb3c","5ad50889c05179000306021e"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"3.0.0","version":"3"},"category":{"_id":"5627ca43fcbbc621004ec07d","project":"55843604fd8d910d007b9502","version":"558444ceafccfd0d00fcb2bb","__v":7,"pages":["5627ca593a4c6b0d00c455e9","5627ca6866c62617009d1844","5627ca823a4c6b0d00c455eb","5627ca9c22ef6a2100fb3513","56292b022c0fd9190067da82","5632ce9310b6040d0087944b","56df6582c0e74f0e00ba6ce6"],"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-10-21T17:24:19.325Z","from_sync":false,"order":0,"slug":"api","title":"API"},"user":"5919f13aff66b00f00f1948c","__v":0,"parentDoc":null,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2018-03-15T18:17:49.199Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"This guide describes how to use OAuth 2.0 with the Qualtrics APIs. You can use OAuth instead of the API token (as described in [Authentication](doc:authentication)) to access the Qualtrics APIs. For differences between OAuth and the API token see [Differences Between OAuth and the API Token](#differences-between-oauth-and-the-api-token).\n\nThis guide contains the following topics:\n\n- [Authentication with OAuth](#authentication-with-oauth)\n- [Finding Your Client ID and Client Secret](#finding-your-client-id-and-client-secret)\n- [Obtaining a Bearer Token](#obtaining-a-bearer-token)\n- [Using Your Bearer Token with the Qualtrics APIs](#using-your-bearer-token-with-the-qualtrics-apis)\n- [Expired Token Server Response](#expired-token-server-response)\n- [Differences Between OAuth and the API Token](#differences-between-oauth-and-the-api-token)\n- [Security](#security)\n\n[block:api-header]\n{\n  \"title\": \"Authentication with OAuth\"\n}\n[/block]\nThere are two steps required to use OAuth:\n\n## Request a Bearer Token\n\nPOST your client ID and client secret to the OAuth endpoint to receive a bearer token. Your token is valid for one hour, so you need to request a token each time you want to use a Qualtrics API, or you need to handle the error from an expired token and request a new one. See [Expired Token Server Response](#expired-token-server-response) for an example response when the token has expired. \n\n## Use the Token with Each API Call\n\nUse the bearer token to authorize the use of the Qualtrics APIs. Normally, the Qualtrics APIs require the use of the API token in the HTTP header **X-API-TOKEN**. OAuth uses the **Authorization** HTTP header instead, as shown below:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"Authorization: Bearer <your_bearer_token>\",\n      \"language\": \"http\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Finding Your Client ID and Client Secret\"\n}\n[/block]\nIn the Qualtrics web interface, click the user button on the far right of the screen to display the menu as shown below:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/5d91850-Dropdown_menu_fixed-_highlighted-01.png\",\n        \"Dropdown menu fixed- highlighted-01.png\",\n        1853,\n        412,\n        \"#f2f2f2\"\n      ]\n    }\n  ]\n}\n[/block]\nClick on **Account Settings...** and choose **Qualtrics IDs**. \n\nThe client ID and client secret as they appear on **Qualtrics IDs** are shown below:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/e049061-OAUTH_IDs-01.png\",\n        \"OAUTH IDs-01.png\",\n        1892,\n        594,\n        \"#d0d1d2\"\n      ]\n    }\n  ]\n}\n[/block]\nThe section **API OAuth** contains your OAuth client ID and client secret. If they are empty, you need to click on **Generate Client** to see them.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Generate Client\",\n  \"body\": \"Your client secret will only appear after you click on **Generate Client**. However, every time you click on **Generate Client** you reset the client secret for the entire brand, invalidating the current client secret. Any code that uses that client secret will fail.\\n\\nIf you leave and return to the page, the client secret will no longer appear. Be sure you save it.\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Obtaining a Bearer Token\"\n}\n[/block]\nThese examples (except for the cURL example) assume that you have saved your client ID, client secret, and data center values in the environment as **Q_CLIENT_ID**, **Q_CLIENT_SECRET**, and **Q_DATA_CENTER**.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"import requests\\nimport os\\n\\nclientId = os.environ[\\\"Q_CLIENT_ID\\\"]\\nclientSecret = os.environ[\\\"Q_CLIENT_SECRET\\\"]\\ndataCenter = os.environ[\\\"Q_DATA_CENTER\\\"]\\n\\ndef getToken():\\n  \\n\\tbaseUrl = \\\"https://{0}.qualtrics.com/oauth2/token\\\".format(dataCenter) \\n\\tdata = { \\\"grant_type\\\": \\\"client_credentials\\\" }\\n\\n\\tr = requests.post(baseUrl, auth=(clientId, clientSecret), data=data)\\n\\n\\treturn r.json()['access_token']\\n\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"# Get Token with the OAuthLib\\n#\\n# For this sample, install the dependencies with:\\n# \\n# pip install oauthlib\\n# pip install requests_oauthlib\\n\\nimport os\\nfrom oauthlib.oauth2 import BackendApplicationClient\\nfrom requests_oauthlib import OAuth2Session\\n\\nclientId = os.environ[\\\"Q_CLIENT_ID\\\"]\\nclientSecret = os.environ[\\\"Q_CLIENT_SECRET\\\"]\\ndataCenter = os.environ[\\\"Q_DATA_CENTER\\\"]\\ntoken_url = 'https://{0}.qualtrics.com/oauth2/token'.format(dataCenter)\\n\\ndef getToken():\\n  \\n\\tclient = BackendApplicationClient(client_id=clientId)\\n\\toauth = OAuth2Session(client=client)\\n\\ttoken = oauth.fetch_token(token_url=token_url, client_id=clientId, client_secret=client_secret)\\n  \\n\\treturn token['access_token']\",\n      \"language\": \"python\",\n      \"name\": \"Python with OAuthLib\"\n    },\n    {\n      \"code\": \"# Java command-line tool to get a bearer token\\n\\npublic static void main(String[] args) {\\n\\n   String client_id = System.getenv(\\\"Q_CLIENT_ID\\\");\\n   String client_secret = System.getenv(\\\"Q_CLIENT_SECRET\\\");;\\n   String data_center = System.getenv(\\\"Q_DATA_CENTER\\\");\\n\\n   String m = client_id + \\\":\\\" + client_secret;\\n   byte[] message =  m.getBytes(StandardCharsets.UTF_8);\\n   String encoded = Base64.getEncoder().encodeToString(message);\\n   String authString = \\\"Basic \\\" + encoded;\\n   System.out.println(authString);\\n\\n   try {\\n       String data = URLEncoder.encode(\\\"grant_type\\\", \\\"UTF-8\\\")\\n               + \\\"=\\\" + URLEncoder.encode(\\\"client_credentials\\\", \\\"UTF-8\\\");\\n\\tSystem.out.println(excutePost(String.format(\\\"https://%s.qualtrics.com/oauth2/token\\\", data_center), data, authString));\\n   }\\n   catch (Exception ex)\\n   {\\n\\n   }\\n}\\n\\npublic static String excutePost(String targetURL, String data, String authString)\\n{\\n   URL url;\\n   HttpURLConnection connection = null;\\n   try {\\n       //Create connection\\n       url = new URL(targetURL);\\n       connection = (HttpURLConnection)url.openConnection();\\n       connection.setRequestMethod(\\\"POST\\\");\\n       connection.setRequestProperty(\\\"Content-Type\\\",\\n               \\\"application/x-www-form-urlencoded\\\");\\n       connection.setRequestProperty(\\\"Authorization\\\",\\n               authString);\\n\\n       connection.setUseCaches (false);\\n       connection.setDoInput(true);\\n       connection.setDoOutput(true);\\n\\n       //Send request\\n       OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream());\\n\\n       outputStreamWriter.write(data);\\n       outputStreamWriter.flush ();\\n       outputStreamWriter.close ();\\n\\n       //Get Response\\n       InputStream is = connection.getInputStream();\\n       BufferedReader rd = new BufferedReader(new InputStreamReader(is));\\n       String line;\\n       StringBuffer response = new StringBuffer();\\n       while((line = rd.readLine()) != null) {\\n           response.append(line);\\n           response.append('\\\\r');\\n       }\\n       rd.close();\\n       return response.toString();\\n\\n   } catch (Exception e) {\\n\\n       e.printStackTrace();\\n       return null;\\n\\n   } finally {\\n\\n       if(connection != null) {\\n           connection.disconnect();\\n       }\\n   }\\n}\\n\",\n      \"language\": \"java\"\n    },\n    {\n      \"code\": \"curl -X POST -d \\\"grant_type=client_credentials\\\" -u \\\"<client_id>:<client_secret>\\\" https://<yourdatacenter>.qualtrics.com/oauth2/token\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\nAn example response object is as follows:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{  \\n   \\\"access_token\\\": \\\"your access token\\\",\\n   \\\"expires_in\\\": 3599,\\n   \\\"scope\\\": \\\"\\\",\\n   \\\"token_type\\\": \\\"bearer\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nThe **expires_in** field indicates the number of seconds until the token expires.\n\nThe token returned from the Python OAuth library is slightly different:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n 'access_token': 'your access token', \\n 'expires_in': 3599, \\n 'scope': [''], \\n 'token_type': 'bearer', \\n 'expires_at': 1521498141.7638242\\n}\",\n      \"language\": \"python\",\n      \"name\": \"Python with OAuthLib\"\n    }\n  ]\n}\n[/block]\nIt contains an **expires_at** field that gives the timestamp for the expiration date.\n\nFor more information about the Python **oauthlib** library, see [OAuthLib Documentation](https://oauthlib.readthedocs.io/en/latest/). For more information about **requests_oauthlib**, see [Requests-OAuthlib Documentation](https://requests-oauthlib.readthedocs.io/en/latest/)\n[block:api-header]\n{\n  \"title\": \"Using Your Bearer Token with the Qualtrics APIs\"\n}\n[/block]\nThe following example shows how to use the token with the List Surveys API. \n\nThe Python example calls the **getToken()** function defined in the previous section, and the cURL example uses the token on the command line.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# List Surveys\\n\\nimport os\\nimport requests\\n\\n# Setting user Parameters\\ndataCenter = os.environ[\\\"Q_DATA_CENTER\\\"]\\n\\nbearerToken = getToken() # call the function defined in the previous code example\\nbaseUrl = \\\"https://{0}.qualtrics.com/API/v3/surveys\\\".format(dataCenter)\\nheaders = {\\n    \\\"authorization\\\": \\\"bearer \\\" + bearerToken,\\n    }\\n\\nresponse = requests.request(\\\"GET\\\", baseUrl, headers=headers)\\nprint(response.text)\\n\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"curl -H 'Authorization:bearer <your-bearer-token>'\\n'https://yourdatacenterid.qualtrics.com/API/v3/surveys'\",\n      \"language\": \"curl\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Expired Token Server Response\"\n}\n[/block]\nIf your OAuth token has expired, you will receive a response to API calls as shown below:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"meta\\\": {\\n        \\\"error\\\": {\\n            \\\"errorCode\\\": \\\"AUTH_6.0\\\",\\n            \\\"errorMessage\\\": \\\"invalid_client\\\"\\n        },\\n        \\\"httpStatus\\\": \\\"401 - Unauthorized\\\",\\n        \\\"requestId\\\": \\\"bed93eee-a684-44b7-8cdc-128251874a45\\\"\\n    }\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Differences Between OAuth and the API Token\"\n}\n[/block]\nThis section discusses the practical differences between the API token as discussed in [Authentication](doc:authentication) and the OAuth bearer token.\n\n### Duration\n\nThe API token is valid until you regenerate a new token in the web interface. The OAuth bearer token is only valid for one hour. Because you need to frequently regenerate your bearer token, you need to request a token every time you want to use a Qualtrics API or you need to handle token expiration errors by requesting a new token.\n\nPrevious tokens are not invalidated when you request a new token and can be used up to their expiration \n\n### HTTP Header\n\nThe API token is sent to the server with the **X-API-TOKEN** header as shown below:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"X-API-TOKEN: <your api token>\",\n      \"language\": \"http\"\n    }\n  ]\n}\n[/block]\nThe OAuth bearer token appears instead in the **Authorization** header:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"Authorization: Bearer <your OAuth bearer token>\",\n      \"language\": \"http\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"title\": \"Security\"\n}\n[/block]\nThe examples in this guide show the client ID and client secret stored in environment variables, which is better than hardcoding them in the source code, but all code (including malicious code) running with that same environment has access to the environment and thus your client ID and client secret. A better approach is to store the values in an encrypted password vault (such as Keychain or 1Password).\n\nThe client ID and client secret should never be stored in apps distributed to users (such as mobile or desktop apps). Both values could be extracted from the client binaries and used to generate tokens to access the Qualtrics APIs using your credentials and thus have access to all of your survey responses, surveys, contact lists, and other confidential information. Treat your client ID and client secret as if they were a username and password.","excerpt":"Describes how to use OAuth 2.0 instead of the API token to access the Qualtrics APIs","slug":"using-oauth","type":"basic","title":"Using OAuth with the Qualtrics APIs"}

Using OAuth with the Qualtrics APIs

Describes how to use OAuth 2.0 instead of the API token to access the Qualtrics APIs

This guide describes how to use OAuth 2.0 with the Qualtrics APIs. You can use OAuth instead of the API token (as described in [Authentication](doc:authentication)) to access the Qualtrics APIs. For differences between OAuth and the API token see [Differences Between OAuth and the API Token](#differences-between-oauth-and-the-api-token). This guide contains the following topics: - [Authentication with OAuth](#authentication-with-oauth) - [Finding Your Client ID and Client Secret](#finding-your-client-id-and-client-secret) - [Obtaining a Bearer Token](#obtaining-a-bearer-token) - [Using Your Bearer Token with the Qualtrics APIs](#using-your-bearer-token-with-the-qualtrics-apis) - [Expired Token Server Response](#expired-token-server-response) - [Differences Between OAuth and the API Token](#differences-between-oauth-and-the-api-token) - [Security](#security) [block:api-header] { "title": "Authentication with OAuth" } [/block] There are two steps required to use OAuth: ## Request a Bearer Token POST your client ID and client secret to the OAuth endpoint to receive a bearer token. Your token is valid for one hour, so you need to request a token each time you want to use a Qualtrics API, or you need to handle the error from an expired token and request a new one. See [Expired Token Server Response](#expired-token-server-response) for an example response when the token has expired. ## Use the Token with Each API Call Use the bearer token to authorize the use of the Qualtrics APIs. Normally, the Qualtrics APIs require the use of the API token in the HTTP header **X-API-TOKEN**. OAuth uses the **Authorization** HTTP header instead, as shown below: [block:code] { "codes": [ { "code": "Authorization: Bearer <your_bearer_token>", "language": "http" } ] } [/block] [block:api-header] { "title": "Finding Your Client ID and Client Secret" } [/block] In the Qualtrics web interface, click the user button on the far right of the screen to display the menu as shown below: [block:image] { "images": [ { "image": [ "https://files.readme.io/5d91850-Dropdown_menu_fixed-_highlighted-01.png", "Dropdown menu fixed- highlighted-01.png", 1853, 412, "#f2f2f2" ] } ] } [/block] Click on **Account Settings...** and choose **Qualtrics IDs**. The client ID and client secret as they appear on **Qualtrics IDs** are shown below: [block:image] { "images": [ { "image": [ "https://files.readme.io/e049061-OAUTH_IDs-01.png", "OAUTH IDs-01.png", 1892, 594, "#d0d1d2" ] } ] } [/block] The section **API OAuth** contains your OAuth client ID and client secret. If they are empty, you need to click on **Generate Client** to see them. [block:callout] { "type": "warning", "title": "Generate Client", "body": "Your client secret will only appear after you click on **Generate Client**. However, every time you click on **Generate Client** you reset the client secret for the entire brand, invalidating the current client secret. Any code that uses that client secret will fail.\n\nIf you leave and return to the page, the client secret will no longer appear. Be sure you save it." } [/block] [block:api-header] { "title": "Obtaining a Bearer Token" } [/block] These examples (except for the cURL example) assume that you have saved your client ID, client secret, and data center values in the environment as **Q_CLIENT_ID**, **Q_CLIENT_SECRET**, and **Q_DATA_CENTER**. [block:code] { "codes": [ { "code": "import requests\nimport os\n\nclientId = os.environ[\"Q_CLIENT_ID\"]\nclientSecret = os.environ[\"Q_CLIENT_SECRET\"]\ndataCenter = os.environ[\"Q_DATA_CENTER\"]\n\ndef getToken():\n \n\tbaseUrl = \"https://{0}.qualtrics.com/oauth2/token\".format(dataCenter) \n\tdata = { \"grant_type\": \"client_credentials\" }\n\n\tr = requests.post(baseUrl, auth=(clientId, clientSecret), data=data)\n\n\treturn r.json()['access_token']\n", "language": "python" }, { "code": "# Get Token with the OAuthLib\n#\n# For this sample, install the dependencies with:\n# \n# pip install oauthlib\n# pip install requests_oauthlib\n\nimport os\nfrom oauthlib.oauth2 import BackendApplicationClient\nfrom requests_oauthlib import OAuth2Session\n\nclientId = os.environ[\"Q_CLIENT_ID\"]\nclientSecret = os.environ[\"Q_CLIENT_SECRET\"]\ndataCenter = os.environ[\"Q_DATA_CENTER\"]\ntoken_url = 'https://{0}.qualtrics.com/oauth2/token'.format(dataCenter)\n\ndef getToken():\n \n\tclient = BackendApplicationClient(client_id=clientId)\n\toauth = OAuth2Session(client=client)\n\ttoken = oauth.fetch_token(token_url=token_url, client_id=clientId, client_secret=client_secret)\n \n\treturn token['access_token']", "language": "python", "name": "Python with OAuthLib" }, { "code": "# Java command-line tool to get a bearer token\n\npublic static void main(String[] args) {\n\n String client_id = System.getenv(\"Q_CLIENT_ID\");\n String client_secret = System.getenv(\"Q_CLIENT_SECRET\");;\n String data_center = System.getenv(\"Q_DATA_CENTER\");\n\n String m = client_id + \":\" + client_secret;\n byte[] message = m.getBytes(StandardCharsets.UTF_8);\n String encoded = Base64.getEncoder().encodeToString(message);\n String authString = \"Basic \" + encoded;\n System.out.println(authString);\n\n try {\n String data = URLEncoder.encode(\"grant_type\", \"UTF-8\")\n + \"=\" + URLEncoder.encode(\"client_credentials\", \"UTF-8\");\n\tSystem.out.println(excutePost(String.format(\"https://%s.qualtrics.com/oauth2/token\", data_center), data, authString));\n }\n catch (Exception ex)\n {\n\n }\n}\n\npublic static String excutePost(String targetURL, String data, String authString)\n{\n URL url;\n HttpURLConnection connection = null;\n try {\n //Create connection\n url = new URL(targetURL);\n connection = (HttpURLConnection)url.openConnection();\n connection.setRequestMethod(\"POST\");\n connection.setRequestProperty(\"Content-Type\",\n \"application/x-www-form-urlencoded\");\n connection.setRequestProperty(\"Authorization\",\n authString);\n\n connection.setUseCaches (false);\n connection.setDoInput(true);\n connection.setDoOutput(true);\n\n //Send request\n OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream());\n\n outputStreamWriter.write(data);\n outputStreamWriter.flush ();\n outputStreamWriter.close ();\n\n //Get Response\n InputStream is = connection.getInputStream();\n BufferedReader rd = new BufferedReader(new InputStreamReader(is));\n String line;\n StringBuffer response = new StringBuffer();\n while((line = rd.readLine()) != null) {\n response.append(line);\n response.append('\\r');\n }\n rd.close();\n return response.toString();\n\n } catch (Exception e) {\n\n e.printStackTrace();\n return null;\n\n } finally {\n\n if(connection != null) {\n connection.disconnect();\n }\n }\n}\n", "language": "java" }, { "code": "curl -X POST -d \"grant_type=client_credentials\" -u \"<client_id>:<client_secret>\" https://<yourdatacenter>.qualtrics.com/oauth2/token", "language": "curl" } ] } [/block] An example response object is as follows: [block:code] { "codes": [ { "code": "{ \n \"access_token\": \"your access token\",\n \"expires_in\": 3599,\n \"scope\": \"\",\n \"token_type\": \"bearer\"\n}", "language": "json" } ] } [/block] The **expires_in** field indicates the number of seconds until the token expires. The token returned from the Python OAuth library is slightly different: [block:code] { "codes": [ { "code": "{\n 'access_token': 'your access token', \n 'expires_in': 3599, \n 'scope': [''], \n 'token_type': 'bearer', \n 'expires_at': 1521498141.7638242\n}", "language": "python", "name": "Python with OAuthLib" } ] } [/block] It contains an **expires_at** field that gives the timestamp for the expiration date. For more information about the Python **oauthlib** library, see [OAuthLib Documentation](https://oauthlib.readthedocs.io/en/latest/). For more information about **requests_oauthlib**, see [Requests-OAuthlib Documentation](https://requests-oauthlib.readthedocs.io/en/latest/) [block:api-header] { "title": "Using Your Bearer Token with the Qualtrics APIs" } [/block] The following example shows how to use the token with the List Surveys API. The Python example calls the **getToken()** function defined in the previous section, and the cURL example uses the token on the command line. [block:code] { "codes": [ { "code": "# List Surveys\n\nimport os\nimport requests\n\n# Setting user Parameters\ndataCenter = os.environ[\"Q_DATA_CENTER\"]\n\nbearerToken = getToken() # call the function defined in the previous code example\nbaseUrl = \"https://{0}.qualtrics.com/API/v3/surveys\".format(dataCenter)\nheaders = {\n \"authorization\": \"bearer \" + bearerToken,\n }\n\nresponse = requests.request(\"GET\", baseUrl, headers=headers)\nprint(response.text)\n", "language": "python" }, { "code": "curl -H 'Authorization:bearer <your-bearer-token>'\n'https://yourdatacenterid.qualtrics.com/API/v3/surveys'", "language": "curl" } ] } [/block] [block:api-header] { "title": "Expired Token Server Response" } [/block] If your OAuth token has expired, you will receive a response to API calls as shown below: [block:code] { "codes": [ { "code": "{\n \"meta\": {\n \"error\": {\n \"errorCode\": \"AUTH_6.0\",\n \"errorMessage\": \"invalid_client\"\n },\n \"httpStatus\": \"401 - Unauthorized\",\n \"requestId\": \"bed93eee-a684-44b7-8cdc-128251874a45\"\n }\n}", "language": "json" } ] } [/block] [block:api-header] { "title": "Differences Between OAuth and the API Token" } [/block] This section discusses the practical differences between the API token as discussed in [Authentication](doc:authentication) and the OAuth bearer token. ### Duration The API token is valid until you regenerate a new token in the web interface. The OAuth bearer token is only valid for one hour. Because you need to frequently regenerate your bearer token, you need to request a token every time you want to use a Qualtrics API or you need to handle token expiration errors by requesting a new token. Previous tokens are not invalidated when you request a new token and can be used up to their expiration ### HTTP Header The API token is sent to the server with the **X-API-TOKEN** header as shown below: [block:code] { "codes": [ { "code": "X-API-TOKEN: <your api token>", "language": "http" } ] } [/block] The OAuth bearer token appears instead in the **Authorization** header: [block:code] { "codes": [ { "code": "Authorization: Bearer <your OAuth bearer token>", "language": "http" } ] } [/block] [block:api-header] { "title": "Security" } [/block] The examples in this guide show the client ID and client secret stored in environment variables, which is better than hardcoding them in the source code, but all code (including malicious code) running with that same environment has access to the environment and thus your client ID and client secret. A better approach is to store the values in an encrypted password vault (such as Keychain or 1Password). The client ID and client secret should never be stored in apps distributed to users (such as mobile or desktop apps). Both values could be extracted from the client binaries and used to generate tokens to access the Qualtrics APIs using your credentials and thus have access to all of your survey responses, surveys, contact lists, and other confidential information. Treat your client ID and client secret as if they were a username and password.