Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
NPrinting has a library of APIs that can be used to customize many native NPrinting functions outside the NPrinting Web Console.
An example of two of the more common capabilities available via NPrinting APIs are as follows
These and many other public NPrinting APIs can be found here: Qlik NPrinting API
In the Qlik Sense data load editor of your Qlik Sense app, two REST connections are required (These two REST Connectors must also be configured in the QlikView Desktop application>load where the API's are used. See Nprinting Rest API Connection through QlikView desktop)
Requirements of REST user account:
Creating REST "GET" connections
Note: Replace QlikServer3.domain.local with the name and port of your NPrinting Server
NOTE: replace domain\administrator with the domain and user name of your NPrinting service user account
Creating REST "POST" connections
Note: Replace QlikServer3.domain.local with the name and port of your NPrinting Server
NOTE: replace domain\administrator with the domain and user name of your NPrinting service user account
Ensure to enter the 'Name' Origin and 'Value' of the Qlik Sense (or QlikView) server address in your POST REST connection only.
Replace https://qlikserver1.domain.local with your Qlik sense (or QlikView) server address.
Ensure that the 'Origin' Qlik Sense or QlikView server is added as a 'Trusted Origin' on the NPrinting Server computer
NOTE: The information in this article is provided as-is and to be used at own discretion. NPrinting API usage requires developer expertise and usage therein is significant customization outside the turnkey NPrinting Web Console functionality. Depending on tool(s) used, customization(s), and/or other factors ongoing, support on the solution below may not be provided by Qlik Support.
Ever wanted to brand or customize the default Qlik Sense Login page?
The functionality exists, and it's really as simple as just designing your HTML page and 'POSTing' it into your environment.
We've all seen the standard Qlik Sense Login page, this article is all about customizing this page.
This customization is provided as is. Qlik Support cannot provide continued support of the solution. For assistance, reach out to our Professional Services or engage in our active Integrations forum.
To customize the page:
{
"id": "8817d7ab-e9b2-4816-8332-f8cb869b27c2",
"createdDate": "2020-03-23T15:39:33.540Z",
"modifiedDate": "2020-05-20T18:46:13.995Z",
"modifiedByUserName": "INTERNAL\\sa_api",
"customProperties": [],
"settings": {
"id": "8817d7ab-e9b2-4816-8332-f8cb869b27c2",
"createdDate": "2020-03-23T15:39:33.540Z",
"modifiedDate": "2020-05-20T18:46:13.995Z",
"modifiedByUserName": "INTERNAL\\sa_api",
"listenPort": 443,
"allowHttp": true,
"unencryptedListenPort": 80,
"authenticationListenPort": 4244,
"kerberosAuthentication": false,
"unencryptedAuthenticationListenPort": 4248,
"sslBrowserCertificateThumbprint": "e6ee6df78f9afb22db8252cbeb8ad1646fa14142",
"keepAliveTimeoutSeconds": 10,
"maxHeaderSizeBytes": 16384,
"maxHeaderLines": 100,
"logVerbosity": {
"id": "8817d7ab-e9b2-4816-8332-f8cb869b27c2",
"createdDate": "2020-03-23T15:39:33.540Z",
"modifiedDate": "2020-05-20T18:46:13.995Z",
"modifiedByUserName": "INTERNAL\\sa_api",
"logVerbosityAuditActivity": 4,
"logVerbosityAuditSecurity": 4,
"logVerbosityService": 4,
"logVerbosityAudit": 4,
"logVerbosityPerformance": 4,
"logVerbositySecurity": 4,
"logVerbositySystem": 4,
"schemaPath": "ProxyService.Settings.LogVerbosity"
},
"useWsTrace": false,
"performanceLoggingInterval": 5,
"restListenPort": 4243,
"virtualProxies": [
{
"id": "58d03102-656f-4075-a436-056d81144c1f",
"prefix": "",
"description": "Central Proxy (Default)",
"authenticationModuleRedirectUri": "",
"sessionModuleBaseUri": "",
"loadBalancingModuleBaseUri": "",
"useStickyLoadBalancing": false,
"loadBalancingServerNodes": [
{
"id": "f1d26a45-b0dd-4be1-91d0-34c698e18047",
"name": "Central",
"hostName": "qlikdemo",
"temporaryfilepath": "C:\\Users\\qservice\\AppData\\Local\\Temp\\",
"roles": [
{
"id": "2a6a0d52-9bb4-4e74-b2b2-b597fa4e4470",
"definition": 0,
"privileges": null
},
{
"id": "d2c56b7b-43fd-44ad-a12f-59e778ce575a",
"definition": 1,
"privileges": null
},
{
"id": "37244424-96ae-4fe5-9522-088a0e9679e3",
"definition": 2,
"privileges": null
},
{
"id": "b770516e-fe8a-43a8-a7a4-318984ee4bd6",
"definition": 3,
"privileges": null
},
{
"id": "998b7df8-195f-4382-af18-4e0c023e7f1c",
"definition": 4,
"privileges": null
},
{
"id": "2a5325f4-649b-4147-b0b1-f568be1988aa",
"definition": 5,
"privileges": null
}
],
"serviceCluster": {
"id": "b07fc5f2-f09e-4676-9de6-7d73f637b962",
"name": "ServiceCluster",
"privileges": null
},
"privileges": null
}
],
"authenticationMethod": 0,
"headerAuthenticationMode": 0,
"headerAuthenticationHeaderName": "",
"headerAuthenticationStaticUserDirectory": "",
"headerAuthenticationDynamicUserDirectory": "",
"anonymousAccessMode": 0,
"windowsAuthenticationEnabledDevicePattern": "Windows",
"sessionCookieHeaderName": "X-Qlik-Session",
"sessionCookieDomain": "",
"additionalResponseHeaders": "",
"sessionInactivityTimeout": 30,
"extendedSecurityEnvironment": false,
"websocketCrossOriginWhiteList": [
"qlikdemo",
"qlikdemo.local",
"qlikdemo.paris.lan"
],
"defaultVirtualProxy": true,
"tags": [],
"samlMetadataIdP": "",
"samlHostUri": "",
"samlEntityId": "",
"samlAttributeUserId": "",
"samlAttributeUserDirectory": "",
"samlAttributeSigningAlgorithm": 0,
"samlAttributeMap": [],
"jwtAttributeUserId": "",
"jwtAttributeUserDirectory": "",
"jwtAudience": "",
"jwtPublicKeyCertificate": "",
"jwtAttributeMap": [],
"magicLinkHostUri": "",
"magicLinkFriendlyName": "",
"samlSlo": false,
"privileges": null
},
{
"id": "a8b561ec-f4dc-48a1-8bf1-94772d9aa6cc",
"prefix": "header",
"description": "header",
"authenticationModuleRedirectUri": "",
"sessionModuleBaseUri": "",
"loadBalancingModuleBaseUri": "",
"useStickyLoadBalancing": false,
"loadBalancingServerNodes": [
{
"id": "f1d26a45-b0dd-4be1-91d0-34c698e18047",
"name": "Central",
"hostName": "qlikdemo",
"temporaryfilepath": "C:\\Users\\qservice\\AppData\\Local\\Temp\\",
"roles": [
{
"id": "2a6a0d52-9bb4-4e74-b2b2-b597fa4e4470",
"definition": 0,
"privileges": null
},
{
"id": "d2c56b7b-43fd-44ad-a12f-59e778ce575a",
"definition": 1,
"privileges": null
},
{
"id": "37244424-96ae-4fe5-9522-088a0e9679e3",
"definition": 2,
"privileges": null
},
{
"id": "b770516e-fe8a-43a8-a7a4-318984ee4bd6",
"definition": 3,
"privileges": null
},
{
"id": "998b7df8-195f-4382-af18-4e0c023e7f1c",
"definition": 4,
"privileges": null
},
{
"id": "2a5325f4-649b-4147-b0b1-f568be1988aa",
"definition": 5,
"privileges": null
}
],
"serviceCluster": {
"id": "b07fc5f2-f09e-4676-9de6-7d73f637b962",
"name": "ServiceCluster",
"privileges": null
},
"privileges": null
}
],
"authenticationMethod": 1,
"headerAuthenticationMode": 1,
"headerAuthenticationHeaderName": "userid",
"headerAuthenticationStaticUserDirectory": "QLIKDEMO",
"headerAuthenticationDynamicUserDirectory": "",
"anonymousAccessMode": 0,
"windowsAuthenticationEnabledDevicePattern": "Windows",
"sessionCookieHeaderName": "X-Qlik-Session-Header",
"sessionCookieDomain": "",
"additionalResponseHeaders": "",
"sessionInactivityTimeout": 30,
"extendedSecurityEnvironment": false,
"websocketCrossOriginWhiteList": [
"qlikdemo",
"qlikdemo.local"
],
"defaultVirtualProxy": false,
"tags": [],
"samlMetadataIdP": "",
"samlHostUri": "",
"samlEntityId": "",
"samlAttributeUserId": "",
"samlAttributeUserDirectory": "",
"samlAttributeSigningAlgorithm": 0,
"samlAttributeMap": [],
"jwtAttributeUserId": "",
"jwtAttributeUserDirectory": "",
"jwtAudience": "",
"jwtPublicKeyCertificate": "",
"jwtAttributeMap": [],
"magicLinkHostUri": "",
"magicLinkFriendlyName": "",
"samlSlo": false,
"privileges": null
}
],
"formAuthenticationPageTemplate": "",
"loggedOutPageTemplate": "",
"errorPageTemplate": "",
"schemaPath": "ProxyService.Settings"
},
"serverNodeConfiguration": {
"id": "f1d26a45-b0dd-4be1-91d0-34c698e18047",
"name": "Central",
"hostName": "qlikdemo",
"temporaryfilepath": "C:\\Users\\qservice\\AppData\\Local\\Temp\\",
"roles": [
{
"id": "2a6a0d52-9bb4-4e74-b2b2-b597fa4e4470",
"definition": 0,
"privileges": null
},
{
"id": "d2c56b7b-43fd-44ad-a12f-59e778ce575a",
"definition": 1,
"privileges": null
},
{
"id": "37244424-96ae-4fe5-9522-088a0e9679e3",
"definition": 2,
"privileges": null
},
{
"id": "b770516e-fe8a-43a8-a7a4-318984ee4bd6",
"definition": 3,
"privileges": null
},
{
"id": "998b7df8-195f-4382-af18-4e0c023e7f1c",
"definition": 4,
"privileges": null
},
{
"id": "2a5325f4-649b-4147-b0b1-f568be1988aa",
"definition": 5,
"privileges": null
}
],
"serviceCluster": {
"id": "b07fc5f2-f09e-4676-9de6-7d73f637b962",
"name": "ServiceCluster",
"privileges": null
},
"privileges": null
},
"tags": [],
"privileges": null,
"schemaPath": "ProxyService"
}
If your login page does not work and you need to revert back to the default, simply do a GET call on your proxy service, and set formAuthenticationPageTemplate back to an empty string:
formAuthenticationPageTemplate": ""
The following article describes how to use Postman to make GET and PUT requests and verify the JSON output.
The information in this article is provided as-is and to be used at own discretion. Depending on tool(s) used, customization(s), and/or other factors ongoing support on the solution below may not be provided by Qlik Support.
Steps
Copy the Certificates to the server/computer where Postman is used.
Open Postman and go to menu "Settings" , In the General tab set "SSL certificate verification" to Off, In the Certificates Tab select "add Certificate" and set the path to the exported certs. The CRT file path will correspond to the path where the client.pem certificate resides, the Key file to the cleint_key.pem
Now Postman is ready to be used, this article describes how to make a GET and PUT request to add a tag to a sheet.
It is suggested to visit our Help site to verify the documentation about the API, in this case we will use
get /app/object/{id}
put /app/object/{id}
The URL would be
https://qlikserver1.domain.local:4242/qrs/app/object/aa73b22a-c933-4c26-aa2b-1e0947d708ab?xrfkey=12345678qwertyui
[Server] + [API end point] + [xrfkey]
The necessary headers would be :
X-Qlik-xrfkey = 12345678qwertyui
(this value needs to be the same provided in the URL xrfkey), for questions about xrfkey headers please refer to the following information: Using Xrfkey headers
X-Qlik-User = UserDirectory=DOMAIN;UserId=Administrator (this value would be the user to make the API calls)
Note that Postman will include xrfkey in the parameters section once the URL is pasted in the GET response.
Please refer to the following pictures to verify the configurations are correct.
GET
Postman Headers
Once is configured you can click the "Send" button, the Response will look like this:
PUT
In order to send the PUT method it is necessary to copy the JSON Response from the previous GET call and modify the necessary information, this need to be done carefully otherwise the request will return an error. The details can be found In our Qlik Site under "Updating an entry" section included here.
Sample (It will be necessary to include a comma if there are already tags associated to the object)
{
"id": "376e0283-3e5b-4968-bc55-2a19c4ba3b17",
"name": "Tag3",
"privileges": null
}
Please refer to the following pictures to verify that the configurations are correct
PUT Header
PUT Body
Once the information is correct, select the "Send" button, and you should get a 200 OK Status.
We can verify the chances in the Qlik Sense Management Console, now the tag shows 1 Occurrence and the sheet shows the new tag.
The event payloads emitted by the Qlik Cloud webhooks service are changing. Qlik is replacing a legacy event format with a new cloud event format.
Any legacy events (such as anything not already cloud event compliant) will be updated to a temporary hybrid event containing both legacy and cloud event payloads. This will start on or after November 3, 2025.
Please consider updating your integrations to use the new fields once added.
A formal deprecation with at least a 6-month notice will be provided via the Qlik Developer changelog. After that period, hybrid events will be replaced entirely by cloud events.
Webhook automations in Qlik Automate will not be impacted at this time.
The webhooks service in Qlik Cloud enables you to subscribe to notifications when your Qlik Cloud tenant generates specific events.
At the time of writing, the following legacy events are available:
Service | Event name | Event type | When is event generated |
API keys | API key validation failed | com.qlik.v1.api-key.validation.failed | The tenant tries to use an API key which is expired or revoked |
Apps (Analytics apps) | App created | com.qlik.v1.app.created | A new analytics app is created |
Apps (Analytics apps) | App deleted | com.qlik.v1.app.deleted | An analytics app is deleted |
Apps (Analytics apps) | App exported | com.qlik.v1.app.exported | An analytics app is exported |
Apps (Analytics apps) | App reload finished | com.qlik.v1.app.reload.finished | An analytics app has finished refreshing on an analytics engine (not it may not be saved yet) |
Apps (Analytics apps) | App published | com.qlik.v1.app.published | An analytics app is published from a personal or shared space to a managed space |
Apps (Analytics apps) | App data updated | com.qlik.v1.app.data.updated | An analytics app is saved to persistent storage |
Automations (Automate) | Automation created | com.qlik.v1.automation.created | A new automation is created |
Automations (Automate) | Automation deleted | com.qlik.v1.automation.deleted | An automation is deleted |
Automations (Automate) | Automation updated | com.qlik.v1.automation.updated | An automation has been updated and saved to persistent storage |
Automations (Automate) | Automation run started | com.qlik.v1.automation.run.started | An automation run began execution |
Automations (Automate) | Automation run failed | com.qlik.v1.automation.run.failed | An automation run failed |
Automations (Automate) | Automation run ended | com.qlik.v1.automation.run.ended | An automation run finished successfully |
Reloads (Analytics reloads) | Reload finished | com.qlik.v1.reload.finished | An analytics app has been refreshed and saved |
Users | User created | com.qlik.v1.user.created | A new user is created |
Users | User deleted | com.qlik.v1.user.deleted | A user is deleted |
Any events not listed above will remain as-is, as they already adhere to the cloud event format.
Each event will change to a new structure. The details included in the payloads will remain the same, but some attributes will be available in a different location.
The changes being made:
data
object.cloudEventsVersion
is replaced by specversion
. For most events this will be from cloudEventsVersion: 0.1
to specversion: 1.0+
.contentType
is replaced by datacontentype
to describe the media type of the data object.eventId
is replaced by id
.eventTime
is replaced by time
.eventTypeVersion
is not present in the future schema.eventType
is replaced by type
.extensions.actor
is replaced by authtype
and authclaims
.extensions.updates
is replaced by data._updates
extensions.meta
, and any other direct objects on extensions
are replaced by equivalents in data
where relevant.extensions
object will be moved to the root and renamed to be lowercase if needed, such astenantId
,userId
,spaceId
, etc.
This is the current legacy payload of the automation created event:
{
"cloudEventsVersion": "0.1",
"source": "com.qlik/automations",
"contentType": "application/json",
"eventId": "f4c26f04-18a4-4032-974b-6c7c39a59816",
"eventTime": "2025-09-01T09:53:17.920Z",
"eventTypeVersion": "1.0.0",
"eventType": "com.qlik.v1.automation.created",
"extensions": {
"ownerId": "637390ef6541614d3a88d6c3",
"spaceId": "685a770f2c31b9e482814a4f",
"tenantId": "BL4tTJ4S7xrHTcq0zQxQrJ5qB1_Q6cSo",
"userId": "637390ef6541614d3a88d6c3"
},
"data": {
"connectorIds": {},
"containsBillable": null,
"createdAt": "2025-09-01T09:53:17.000000Z",
"description": null,
"endpointIds": {},
"id": "cae31848-2825-4841-bc88-931be2e3d01a",
"lastRunAt": null,
"lastRunStatus": null,
"name": "hello world",
"ownerId": "637390ef6541614d3a88d6c3",
"runMode": "manual",
"schedules": {},
"snippetIds": {},
"spaceId": "685a770f2c31b9e482814a4f",
"state": "available",
"tenantId": "BL4tTJ4S7xrHTcq0zQxQrJ5qB1_Q6cSo",
"updatedAt": "2025-09-01T09:53:17.000000Z"
}
}
This will be the temporary hybrid event for automation created:
{
// cloud event fields
"id": "f4c26f04-18a4-4032-974b-6c7c39a59816",
"time": "2025-09-01T09:53:17.920Z",
"type": "com.qlik.v1.automation.created",
"userid": "637390ef6541614d3a88d6c3",
"ownerid": "637390ef6541614d3a88d6c3",
"tenantid": "BL4tTJ4S7xrHTcq0zQxQrJ5qB1_Q6cSo",
"description": "hello world",
"datacontenttype": "application/json",
"specversion": "1.0.2",
// legacy event fields
"eventId": "f4c26f04-18a4-4032-974b-6c7c39a59816",
"eventTime": "2025-09-01T09:53:17.920Z",
"eventType": "com.qlik.v1.automation.created",
"extensions": {
"userId": "637390ef6541614d3a88d6c3",
"spaceId": "685a770f2c31b9e482814a4f",
"ownerId": "637390ef6541614d3a88d6c3",
"tenantId": "BL4tTJ4S7xrHTcq0zQxQrJ5qB1_Q6cSo",
},
"contentType": "application/json",
"eventTypeVersion": "1.0.0",
"cloudEventsVersion": "0.1",
// unchanged event fields
"data": {
"connectorIds": {},
"containsBillable": null,
"createdAt": "2025-09-01T09:53:17.000000Z",
"description": null,
"endpointIds": {},
"id": "cae31848-2825-4841-bc88-931be2e3d01a",
"lastRunAt": null,
"lastRunStatus": null,
"name": "hello world",
"ownerId": "637390ef6541614d3a88d6c3",
"runMode": "manual",
"schedules": {},
"snippetIds": {},
"spaceId": "685a770f2c31b9e482814a4f",
"state": "available",
"tenantId": "BL4tTJ4S7xrHTcq0zQxQrJ5qB1_Q6cSo",
"updatedAt": "2025-09-01T09:53:17.000000Z"
},
"source": "com.qlik/automations"
}
Beginning with Qlik Sense Enterprise on Windows 2024, Qlik has extended CSRF protection to WebSockets. For reference, see the Release Notes.
In the case of mashups, extensions,and or other cross-site domain setups, the following two steps are necessary:
Content
The three additional response headers are:
Access-Control-Allow-Origin: https://localhost:8080
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: qlik-csrf-token
Localhost and port 8080 are examples. Replace them with the appropriate hostname. Defining the port is optional.
If you have multiple origins, seperate them by comma.
Example:
For more information about adding response headers to the Qlik Sense Virtual proxy, see Creating a virtual proxy. Expand the Advanced section to access Additional response headers.
In certain scenarios, the additional headers on the virtual proxy will not be enough and a code change is required. In these cases, you need to request the CSRF token and then send it forward when opening the session on the WebSocket. See Workflow for a visualisation of the process.
An example written in Enigma.js is available here:
The information and example in this article are provided as-is and are not directly supported by Qlik Support. More assistance can be found on the Qlik Integration forum. Professional Services are available to help where needed.
Workflow
To verify if the header information is correctly passed on, capture the web traffic in your browser's debug tool.
Environment
A Mixed Content error and CORS errors are displayed in a Qlik Sense Enterprise on Windows Environment running HTTPS and a Webserver hosting a mashup on HTTP.
Qlik Sense Mashups may fail to render when deployed to a web server.
Example setup:
Example error messages:
Access to XMLHttpRequest at [] from origin '[]' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value '[]' that is not equal to the supplied origin.
Origin null not found in Access-Control-Allow-Origin header.
XMLHttpRequest cannot load. No 'Access-Control-Allow-Origin' header is present on the requested resource.
Avoid mixed content (HTTP and HTTPS)
First, verify that the host is included in the WebSocket origin allow list. For details on how this is configured, see How to configure the WebSocket origin allow list and best practices.
Example: A mashup is hosted on http://localhost:8080, and Qlik Sense is hosted on https://my-sense-server. Including "localhost" in the allow list is not sufficient; include explicitly both the protocol and port in this case (* will not include the port):
Then configure Qlik Sense (November 2018 and up) specifically to address the CORS error
Note: Wildcard (*) is not supported. Always define the actual origin.
Example:
Assuming that QlikServer1 is the Qlik Sense server running on HTTPS and localhost is the web server running on HTTP.
The additional response headers would be:
Access-Control-Allow-Origin:https://qlikserver1.domain.local, http://localhost
This issue originates from the browsers parsing and handling of the web content. As a security measure browser do not allow content from multiple domains unless the main page has been configured to allow the cross-domain content. The symptom of not allowed cross-domain content is that the embedded parts fail to render and the browser throws a Cross-Origin Resource Sharing (CORS) error.
The main page must have a HTTP header that allows content from the Qlik Sense host, in order for the embedded object to be allowed by the browser. The general advice on (Access-Control-Allow-Origin) HTTP header requirements are as described in below link from Mozilla Developer Network.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
https://www.w3schools.com/tags/att_iframe_sandbox.asp
If the allow list has been configured correctly in Qlik Sense, then the issue may lie in the web portal or web page hosting Qlik Sense content. Please contact the web service provider or web server administrator for further troubleshooting and configuration.
A user's last login timestamp can be retrieved using the Qlik Audit API and filtering by the event type: com.qlik.user-session.begin
For more information, see: Audits.
The login timestamps can also be obtained from the Qlik Cloud Entitlement Analyzer app.
By default, the touch screen function cannot be disabled in Qlik Sense Enterprise on Windows. It is enabled whenever the client recognizes a touch-enabled device, such as a mobile phone or tablet.
It can be disabled manually by the user, but not globally on the server.
To disable Touch Screen mode manually:
An idea has been created to gather demand on allowing this feature to be disabled on server/administration level. See Option to Disable Touch Screen or toggle Touch Screen off on server side.
Qlik Sense Enterprise on Windows
It is possible to disable touch screen options entirely in, for example, mashups.
A mashup can send information to the client that sends a fixed device type, which modifies the UI accordingly.
The information in this article is provided as-is and to be used at own discretion. Depending on tool(s) used, customization(s), and/or other factors ongoing support on the solution below may not be provided by Qlik Support.
Example:
// Sets device type, which modifies the UI accordingly.
// The device type is automatically detected if it is not manually set.
@function
// String describing the device type.
@param {'auto'|'touch'|'desktop'} deviceType
@example
qlik.setDeviceType('desktop');
More information could be found on the help site: setDeviceType method
After upgrading Qlik Sense Enterprise on Windows to February 2024 or any later versions, the following errors may be thrown in mashups:
Unable to connect to the Qlik Sense Engine
Connection Lost.
Ensure that your mashup script is properly configured to handle authentication and include the session cookie in all subsequent requests after login.
Some APIs are now restricted, and the session cookie is required in every request to validate and process your request successfully.
This article documents how to configure a Qlik tenant to send emails using MS365.
An account with an active Office365 license is required for this setup.
First, we configure the MS365 tenant to support the configuration.
Once you have an account set up on the MS365 side, let's go to the Microsoft Tenant settings:
Setting Application permissions to Mail.Send grants the application to use any email address from your organization.
The information in this article is provided as-is and will be used at your discretion. Depending on the tool(s) used, customization(s), and/or other factors, ongoing support on the solution below may not be provided by Qlik Support.
Sometimes we need to store column's before-image data in the target table. This is useful if we want to store both of the before-image and after-image of the columns values in the target table for downstream apps usage.
Under Apply Changes mode (Store changes mode is turn off), in the table setting by adding a new column in transformation (name it as "prevenient_salary" in this sample), the variable expression is like $BI__<columnName> where $BI__ is a mandatory prefix (which instructs Replicate to capture the before-image data) and <columnName> is the original table column. For example if the original table column name is SALARY then $BI__SALARY is the column before-image data:
If the column SALARY value is updated from 22 to 33 in source side, then before the UPDATE the target table row looks like:
after the UPDATE is applied to target table the row looks like:
In this sample the before-image value is 22, the after-image value is 33.
before-image data can be used in filer also, see sample here .
This video will demonstrate how to install and configure Qlik-CLI for SaaS editions of Qlik Sense.
Content:
get-command qlik
choco install qlik-cli
if ( -not (Test-Path $PROFILE) ) {
echo "" > $PROFILE
}
qlik completion ps > "./qlik_completion.ps1" # Create a file containing the powershell completion.
. ./qlik_completion.ps1 # Source the completion.
Advanced and additional instructions as seen in the video can be found at Qlik-CLI on Qlik.Dev. Begin with Get Started.
Deploying an app with Qlik CLI from Git (with app unbuild and app build ) fails when using the --bookmark parameter.
qlik app build --bookmark --app --git-repo
When a user authenticates with SAML/JWT/Ticket, security rules based on the attributes from the SSO provider do not work and the attributes are not visible in the QMC under the User record.
Environments:
When a user authenticates with SAML, a list of attributes will be given to Qlik Sense based on what is set up in the virtual proxy. The attributes depend on the implementation.
However, these User attribute(s) returned from the SSO provider are only kept for the user session and are not stored/persisted in the Qlik Sense Repository Database. Therefore, they do not appear in the QMC like attributes synchronized via a UDC connection (data which is persisted to the database).
This article documents how to successfully implement an Oracle Wallet into a POST call, which is a necessary step when setting up a Qlik Oracle ODBC connection using the Wallet authentication method via the Qlik QRS API (post /dataconnection).
You can use the following approach to achieve this.
The first three steps will show you what information you need for the POST call.
get /dataconnection/{id}For details, review get /dataconnection/{id}
# Ignore SSL validation errors
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
# Force TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Headers and cert
$hdrs = @{
"X-Qlik-xrfkey" = "12345678qwertyui"
"X-Qlik-User" = "UserDirectory=internal;UserId=sa_repository"
}
$cert = Get-ChildItem -Path "Cert:\CurrentUser\My" | Where-Object { $_.Subject -like '*QlikClient*' }
if (-not $cert) {
Write-Error "Qlik client certificate not found!"
exit
}
# API URL
$url = "https://localhost:4242/qrs/dataconnection/67069b0e-ef40-4873-91a8-8a9c56d61ebd?xrfkey=12345678qwertyui"
# Make request
try {
$resp = Invoke-RestMethod -Uri $url -Method Get -Headers $hdrs -Certificate $cert
$resp | ConvertTo-Json -Depth 10
} catch {
Write-Error "API call failed: $_"
}
{
"id": "67069b0e-ef40-4873-91a8-8a9c56d61ebd",
"createdDate": "2024-07-08T10:15:25.144Z",
"modifiedDate": "2025-04-25T09:34:56.948Z",
"modifiedByUserName": "DOMAIN\\administrator",
"customProperties": [],
"owner": {
"id": "0e756718-ddfa-457a-a219-256211c8dcb4",
"userId": "administrator",
"userDirectory": "DOMAIN",
"userDirectoryConnectorName": "DOMAIN",
"name": "Administrator",
"privileges": null
},
"name": "Oracle_TEST (domain_administrator)",
"connectionstring": "CUSTOM CONNECT TO \"provider=QvOdbcConnectorPackage.exe;driver=oracle;ConnectionType=wallet;port=1521;USETNS=false;TnsName=zx0ka5pcjb3oxzut_high;EnableNcharSupport=1;allowNonSelectQueries=false;QueryTimeout=30;useBulkReader=true;maxStringLength=4096;logSQLStatements=false;\"",
"type": "QvOdbcConnectorPackage.exe",
"engineObjectId": "c4a089ad-b853-4841-b96c-79d259fba388",
"username": "ADMIN",
"password": "Wallet%2wallet.zip%%2UEsDBF...", // truncated for readability
"logOn": 0,
"architecture": 0,
"tags": [],
"privileges": null,
"schemaPath": "DataConnection"
}
Note "ConnectionType=wallet" in the connection string and "password": "Wallet%2wallet.zip%%2UEsDBF..." This contains the encoded information from the Oracle Wallet.
Now apply all information from steps two and three on the template for the post /dataconnection request. See post /dataconnection for details. This allows you to create the Oracle ODBC connection via an API call (using the same Oracle Wallet).
The JSON could look something like this:
{
"name": "Oracle_TEST123",
"connectionstring": "CUSTOM CONNECT TO \"provider=QvOdbcConnectorPackage.exe;driver=oracle;ConnectionType=wallet;port=1521;USETNS=false;TnsName=zx0ka5pcjb3oxzut_high;EnableNcharSupport=1;allowNonSelectQueries=false;QueryTimeout=30;useBulkReader=true;maxStringLength=4096;logSQLStatements=false;\"",
"type": "QvOdbcConnectorPackage.exe",
"username": "ADMIN",
"password": "Wallet%2wallet.zip%%2UEsDBF...", // truncated for readability
"logOn": 0,
"architecture": 0,
"schemaPath": "DataConnection",
"tags": [],
"customProperties": [],
"owner": {
"id": "0e756718-ddfa-457a-a219-256211c8dcb4",
"userId": "administrator",
"userDirectory": "DOMAIN",
"userDirectoryConnectorName": "DOMAIN",
"name": "Administrator"
}
}
PowerShell script example:
$hdrs = @{
"X-Qlik-xrfkey" = "12345678qwertyui"
"X-Qlik-User" = "UserDirectory=internal;UserId=sa_repository"
"Content-Type" = "application/json"
}
$cert = Get-ChildItem -Path "Cert:\CurrentUser\My" | Where-Object { $_.Subject -like '*QlikClient*' }
$body = @{
name = "Oracle_TEST123"
connectionstring = 'CUSTOM CONNECT TO "provider=QvOdbcConnectorPackage.exe;driver=oracle;ConnectionType=wallet;port=1521;USETNS=false;TnsName=zx0ka5pcjb3oxzut_high;EnableNcharSupport=1;allowNonSelectQueries=false;QueryTimeout=30;useBulkReader=true;maxStringLength=4096;logSQLStatements=false;"'
type = "QvOdbcConnectorPackage.exe"
username = "ADMIN"
password = "Wallet%2wallet.zip%%2UEsDBF..." # truncated
logOn = 0
architecture = 0
schemaPath = "DataConnection"
tags = @()
customProperties = @()
owner = @{
id = "0e756718-ddfa-457a-a219-256211c8dcb4"
userId = "administrator"
userDirectory = "DOMAIN"
userDirectoryConnectorName = "DOMAIN"
name = "Administrator"
}
}
$jsonBody = $body | ConvertTo-Json -Depth 10
$url = "https://localhost:4242/qrs/dataconnection?xrfkey=12345678qwertyui"
try {
$response = Invoke-RestMethod -Uri $url -Method Post -Headers $hdrs -Certificate $cert -Body $jsonBody
$response | ConvertTo-Json -Depth 10
} catch {
Write-Error "POST failed: $_"
}
You now have everything you need to create a new Oracle connection (Oracle_TEST123 as named in our example) using the post /dataconnection QRS REST API call.
This article is provided as is. For additional assistance, post your query in our Integration and API forum or contact Services for customized solution assistance.
After distributing the Consumption Report app from Qlik Cloud Administration > Settings, scheduled reloads of the app fail with the following error:
Error: $(MUST_INCLUDE= [lib://snowflake_external_share:DataFiles/Capacity_Usage_Script_PROD.txt] cannot access the local file system in current script mode. Try including with LIB path.
The Consumption Report app isn't meant to be reloaded. The app should be distributed from Qlik Cloud Administration > Settings each day. Refer to Distributing detailed consumption reports for details:
Redistribute the app to obtain the most recent data. Apps stored on your tenant exist as separate instances and are not replaced by newer ones.
On the Talend side, refer to Distributing Data Capacity Reporting App for Talend Management Console for details on how to set up capacity reporting.
The Report Consumption app is meant to be distributed from Qlik Cloud Administration > Settings and not updated by a scheduled reload of the app.
This article explains how the session API works and the workflow.
Postman is used to perform the API call to add the session in Qlik Sense.
In the browser, developer tools or an extension can be used to set the cookie.
1. User authenticate to an external session module (This module must be built by the customer)
2. The module adds the session to the Proxy using the session API
3. The module sets the cookie for the end user
4. The end user is recognized as authenticated and can access the hub and apps.
It does not matter which authentication method is set on the virtual proxy as we are creating directly a session when using this method. However, the following information: Session Cookie header name, Authentication module redirect URI and Session Cookie domain are important to remember when you use the Session API.
You will need to have the QlikClient certificate installed for the user performing this API call. More information is available in following articles:
QRS API using Xrfkey header in Postman
Export client certificate and root certificate to make API calls with Postman
In order to add a session to the virtual proxy, you need to provide the following information:
UserDirectory
UserId
Attributes (optional, these are for example groups to which the user belongs to)
Cookie value (In Qlik Sense by default, a 36 characters string such as aa051074-13a1-4f2a-842b-a64aa4d21001 is used, however this can be any value, but it must be long enough and randomized to ensure there is not 2 session cookies with the same value that are added to the virtual proxy)
Example of API call:
https://qlikserver1.domain.local:4243/qps/{virtual proxy prefix}/session?xrfkey=0123456789abcdef
Headers:
X-Qlik-xrfkey | 0123456789abcdef |
Content-Type | application/json |
Body:
{
"UserDirectory": "DOMAIN",
"UserId": "User1",
"Attributes":
[],
"SessionId": "aa051074-13a1-4f2a-842b-a64aa4d21001"
}
Postman:
PowerShell:
$body = '{ "UserDirectory": "DOMAIN", "UserId": "User1", "Attributes": [], "SessionId": "aa051074-13a1-4f2a-842b-a64aa4d21001" }' $hdrs = @{} $hdrs.Add("X-Qlik-xrfkey","iX83QmNlvu87yyAB") $url = "https://qlikserver1.domain.local:4243/qps/session?xrfkey=iX83QmNlvu87yyAB" $cert = Get-ChildItem -Path "Cert:\CurrentUser\My" | Where {$_.Subject -like '*QlikClient*'} Invoke-RestMethod -Uri $url -Method Post -Body $body -ContentType 'application/json' -Headers $hdrs -Certificate $cert
In Chrome, an extension such as "EditThisCookie" can be used to test that the session API works.
Open the hub and add a cookie with the following information:
Name: X-Qlik-Session-sessionvp
Value: aa051074-13a1-4f2a-842b-a64aa4d21001
Domain: domain.local
Expiration: 0001-01-01 00:00:00
HttpOnly:True
Secure:True
Save the cookie and refresh the page, make sure the address is https://qlikserver1.domain.local/{virtual proxy prefix}/hub/ when you refresh.
Now you should be logged in as the user requested in the previous API call and able to access the hub/your apps.
Content
Qlik Cloud is designed to support a single interactive Identity Provider (IdP) per tenant.
As my friend @DaveChannon explains in Why Qlik doesn't support multiple interactive identity providers on a Qlik Cloud tenant, only one interactive identity provider can be enabled at any one time for Qlik Cloud (Which includes Qlik Cloud Analytics and Qlik Talend Cloud Data Integration). Without restating the points Dave made, the short answer is we do not plan to change this as we don't consider this good practice.
So, if your organisation needs to support multiple IDPs, what can you do? There are many use-cases that require this, such as:
These are just a few examples but this is a very common use case for most large organisations. So what do you have to do? Well, you could solve this with multiple tenants, but that's often a high-maintenance solution and isn't ideal. That's why, as Dave mentioned, we recommend that customers use Identity federation to address this.
Identity federation is a mechanism that links a user's identity across multiple identity management systems, allowing them to access different applications and resources without needing separate logins or credentials. Almost all major providers support this. For example, these IDPs all support federation:
While this is not a 'how-to' article, at a high level, what I've set up is:
This may not always be what you want to do. You may wish to use the groups coming from Auth0 also, and that is possible, but not needed for my use case.
Finally, here are my users set up in Auth0:
So what happens when I log in?
First, let's look at jane@qmi.com. Jane is set up in KeyCloak. After opening the URL for our Qlik Cloud tenant, I am redirected to the keycloak login screen:
I can log in directly here or choose to sign in with Auth0. Jane logs into KeyCloak directly and is then sent back to the Qlik Tenant:
To understand what information Qlik Clouid has been provided, we can append "/api/v1/diagnose-claims" to the end of our tenant URL. This will show us the metadata Qlik has received about Jane, such as:
We are most concerned about Jane's groups, as that is how we will control access. Jane is in the Finance and Human Resources groups.
In our tenant, we have the following spaces and access rules:
Space Name | Space Type | Groups with Access |
External | Managed | External: Read Only |
External_development | Shared | Finance: full access Sales: full access Human Resources: full access |
Finance | Shared | Finance: Read Only |
Sales | Shared | Sales: Read Only |
Human Resources | Shared | Human Resources: Read Only |
So Jane sees the Finance, Human Resources, and External_development spaces:
As this user has never logged in before, KeyCloak asks for some details:
After logging in, we can look at the "/api/v1/diagnose-claims" endpoint to see the user's metadata. We see the External group, which we hard-coded for Auth0 users in KeyCloak:
And when looking at the user's space access, we can only see the External space as expected:
This is a simple example I put together in a couple of hours. I selected KeyCloak and Auth0 simply because I have some experience with them - most IDPs could do this (and also, I could have chosen to reverse the order and have Auth0 as the primary IDP).
Neither Qlik nor I make any specific recommendations as to what identity providers customers should use.
While we haven't looked at it here, it's also possible to use social services (such as LinkedIn, GitHub, Facebook, etc.) as external Identity providers, which may well be a better solution for some use-cases. And you can support many of these at the same time as your needs require.
If you require assistance in this, your friendly neighbourhood Qlik Services team can assist, as can our partners.
After renaming a group used in the Identity Provider (IdP) set up with Qlik Cloud Analytics, the old group name continues to be listed in Qlik Cloud.
Users can log in without issues using the updated information.
Use Qlik-CLI to remove the old group name.
Example command:
qlik group rm <groupId>
See Delete group by ID for details.
Qlik Cloud retrieves all its information on groups from the IdP (Identity Provider), but does not delete old groups. Old groups can be removed using the API.
Renaming a group will be perceived by Qlik Cloud as a new group having been created.
This article explains the steps to configure Kerberos with Qlik Sense. However, it's important to note that the actual setup, implementation, and configuration of Kerberos for Qlik is the responsibility of the customer.
For another set of instructions, see Seamless Single SignOn (SSSO) into Qlik Sense
Note: The following will require appropriate permissions in Active Directory to add Service Principal Names on the account running Qlik Sense services.
A Service Principal Name may be registered using the following command:
setspn -A http/HOST serviceaccount
where
Steps:
1. Open a command prompt with administrative privileges and type :
setspn -U -S http/QlikServer1 COMPANYX\serviceAccount setspn -U -S http/QlikServer1.companyx.local COMPANYX\serviceAccount
2. Go to the QMC > Proxy > Edit
Check the 'Enable Kerberos' checkbox.
NOTE: An SPN must be set for both the short hostname and FQDN for the target Qlik Sense server for Kerberos to work correctly. This is not related to URLs configured in the Web Client allowlist under the Virtual Proxy configuration.
For more information about Service Principal Names see: http://technet.microsoft.com/en-us/library/cc961723.aspx
Seamless Single SignOn (SSSO) into Qlik Sense
Qlik Sense Mobile and Kerberos