Knowledgebase API
GraphQL endpoints
| Environment | Deployment status | Endpoints |
|---|---|---|
| PROD Oslo | General Availability Q1 2025 | GraphQL: https://kbapi.puzzel.com/knowledgebase-api/graphql (Please note: introspection is disabled in the production endpoint) Playground (test live queries): https://devkbapi.puzzel.com/knowledgebase-api/ui/playground |
PROD AZURE | Deprecated | GraphQL: https://knowledgebaseapi.puzzel.io/graphql Playground (test live queries): https://devdatahub.puzzel.io/ui/playground |
Authorization in Azure (deprecated)
To be able to do queries or mutations towards the GraphQL server, a authorzation token must be added in the header in playground.
You can either use an access token from SolutionAdmin (Access Keys on solution level) or a Puzzel API token.
In the HTTP header section in playground add the authorization token as shown below:
{ "Authorization": "Bearer {token}"} |
Authorization in Prod Oslo /UK1
A Puzzel ID access token with these claims are needed:
urn:puzzel:cid
urn:puzzel:cc:slid
A scope prefixed with knowledge-base is also needed
Using Puzzel ID OIDC Client
Create an OIDC Client in Puzzel ID - Organisation Settings with a grant type of Client Credentials

Add the following Allowed Scopes: "knowledge-base" & "usage-metrics.register". Set the Access Token Lifetime as needed.
Securely store the secret and client Id, these are required to obtain a Puzzel ID token.
Ensure the client has been given product access to a relevant PCC Solution:
When adding product access, choose your Contact Centre Solution and assign user to 'None'
Generate a 'secret' for your client:
Add a shared secret with a description and expiration time, both of which are required.
⚠️Once a secret is created it cannot be modified or viewed again. But you may delete an existing secret or add a new secret if needed.

Request a token as follows: Send a POST request to Prod Oslo: https://app.puzzel.com/id/connect/token OR Prod UK1: https://uk.puzzel.com/id/connect/token

Header:
Content-Type: application/x-www-form-urlencoded
Request body:
client_id: your OIDC client Id
client_secret: your OIDC client secret
grant_type: client_credentials
scope: knowledge-base:[PCC SolutionId] usage-metrics.register:[PCC SolutionId] (see screenshot above)
GraphQL Playground (Env. Prod Oslo example)
Navigate to Playground (test live queries): https://devkbapi.puzzel.com/knowledgebase-api/ui/playground

Graphql endpoints: https://kbapi.puzzel.com/knowledgebase-api/graphql for Prod Oslo, Or https://uk.puzzel.com/knowledgebase-api/graphql for UK1 platform area.
ℹ️Please note that introspection is disabled in the production endpoints, as such you will not be able to access the docs and schema panels shown above. To see the docs and schema panel, use the dev endpoint: https://devkbapi.puzzel.com/knowledgebase-api/graphql
When using the dev endpoint to access the documentation for the queries and mutations, you will not be able to perform live queries, consider using an alternative client to perform operations such as Postman.
For the production environment: Set the Puzzel ID token in HTTP HEADERS as "Authorization": "Bearer <Puzzel Id Token>"
ℹ️Note that where a user or OIDC Client has been assigned "Access Levels/Permission Schemes", then the respective limitations will be enforced in the API provided that you have also enabled "Activate content access management" in Knowledgebase Admin - Settings - Access panel.
Authorization handling in KnowledgeBase API
All Puzzel ID users with "KnowledgeBaseAdmin" role will have full access. If the user does not have the "KnowledgeBaseAdmin" role, the different permissions are handled by our defined content access control system which consists of schemes which are assigned to users or groups in Puzzel Id for different KnowledgeBase entities.
A Content Permission Scheme defines what actions (read, add, edit, delete, assign permissions) an access level can do. We have defined 3 global access levels which are called kb:manager, kb:author and kb:agent with pre-assigned permissions. Custom access levels can be added for your solution.
You then grant access by specifying an access level, a KnowledgeBase entity (category, section or article) and a group or user for which it applies to.
Examples of Content Access assignments:
- Assign kb:author access level to Support category for Red group
- Assign kb:author access level to SMS Support article for user John
Embedding content from other articles
The system supports embedding content from other articles with use of custom HTML tags on this format:
<article-content articleId="123" language="en" type="CONTENT">The embedded content</article-content>
When retrieving the content, you must account for this when rendering the content. By default most browsers will render custom tags as a <span> element.
Other points to consider on embedded content:
- Embedded content only works when content type is HTML
- When retrieving the linked content, the system will use the language of the parent article, so make sure the linked content exist on the same language
- When retrieving the linked content, other attributes are disregarded, so take care not to link to hidden articles, etc
- The embedded content is not searchable (that is only the the embedded article itself will show up on searches, not articles linking to it)
Category types
A category can be any of these types:
| name | systemCategory |
|---|---|
| Default | no |
| Suggestions | no |
| Imports | yes |
| News | no |
| Announcements | no |
System categories are created by the system, and only 1 exist pr solution. For non system categories (Default, Suggestions, News and Announcements), you can create as many as you'd like. It is not possible to change type of a category once it has been created.
Queries
Get all categories
Query all categories with belonging sections and sub sections (as many levels as you need). You can optionally specify which categoryTypes you want to query - by default only DEFAULT category type is returned.
You can also set the optional parameter returnOrphanedSections: true if you want to receive the orphaned sections in this call. If set to true, they will be returned in a special category with id = -1.
NB not possible to retrieve articles through this call
{ categories(categoryType: [DEFAULT, NEWS, ANNOUNCEMENTS, SUGGESTIONS]) { id name type articleCount sections { id name articleCount subSections { id name articleCount subSections { id name subSections { id name subSections { id name } } } } } }}Get category
Query a specific category with all fields.
You can optionally specify which statuses the returned articles should have. If not specified, only published articles are returned.
NB Article details such as Attachments, Feedback and RelatedArticles are not available through this call
{ category(id: 2, status: [DRAFT, REVIEW, PUBLISHED]) { id name articles { id status attributes usageCount content { language question answer snippet contentType publishDate expiryDate attributes tags { id name type } ignoredTags alternativeViews { viewName question answer snippet contentType } } } sections { id name articles { id status attributes usageCount content { language question answer snippet contentType publishDate expiryDate attributes tags { id name type } ignoredTags alternativeViews { viewName question answer snippet contentType } } } } }}Get section
Query a specific section with all fields.
You can optionally specify which statuses the returned articles should have. If not specified, only published articles are returned.
NB Article details such as Attachments, Feedback and RelatedArticles are not available through this call
{ section(id: 13, status: [DRAFT, REVIEW, PUBLISHED]) { id name articles { id status attributes usageCount content { language question answer snippet contentType publishDate expiryDate attributes tags { id name type } ignoredTags alternativeViews { viewName question answer snippet contentType } } } }}Get sections
Gets all sections for a customer (articles are not returned) including sub sections for as many sub levels as you need.
query sections{ sections { id name articleCount subSections { id name articleCount subSections { id name subSections { id name subSections { id name } } } } }}Get articles
Queries all articles matching input parameters.
Input parameters are optional, so setting none will return complete list of all articles.
You can optionally specify which statuses the returned articles should have. If not specified, only published articles are returned.
Note that if isPopular is set to true and number of articles marked as popular is lower than a global threshold (10), the method will add the mostly used articles to the list (regardless of attributes).
{ articles(language: "en", status: [DRAFT, REVIEW, PUBLISHED], isVisible:true, isPublished:true, hasFeedback:true, isPopular:true, hasExpired: false) { id type status attributes usageCount viewsContextCount { viewContext count } searchFrequency lastUseDate lastViewDate relatedArticles { id type question } feedback { id text agent createdTime } content { language question answer snippet decisionTree { ... } contentType publishDate expiryDate attributes tags { id name type } ignoredTags attachments { fileId fileName mediaType } alternativeViews { viewName question answer snippet contentType } } }}Get article
Query a specific article with all fields. Language, status, viewContext, view and versionId parameters are optional.
You can optionally specify which statuses the returned articles should have. If not specified, only published articles are returned.
It is highly encouraged to use viewContext to specify under which context the article is viewed from which will enhance the quality of the dashboard data.
By default the optional parameter ignoreVisibilityFlags is set to false, and content with either Hidden, Unpublished or HasExpired attributes will not be returned.
{ article(id: 287, language: "en", status: [DRAFT, REVIEW, PUBLISHED], viewContext:FROM_NAVIGATION, view: "mobile", versionId: 1, ignoreVisibilityFlags: false) { id type status comment attributes usageCount viewsContextCount { viewContext count } searchFrequency lastUseDate lastViewDate categories{ id name } sections{ id name } relatedArticles { id type question } feedback { id text agent createdTime } content { language question answer snippet decisionTree { questions { id text answers { id order answer nextQuestionId articleId articleContent { question answer contentType attributes alternativeViews { viewId viewName question answer contentType } } } } } contentType publishDate expiryDate attributes tags { id name type } ignoredTags attachments { fileId fileName mediaType } alternativeViews { viewName question answer snippet contentType } } }}Get latest news and announcements
Returns X latest news and X latest announcements for the desired languages. maxRecords is optional and if omitted, will return the default value from solution settings.
This method also accounts for when a user has last read announcements (call to storeUserActivity being made).
query { newsAndAnnouncements(languages: ["en", "no"], news: true, announcements: true, maxRecords: 10) { news { id categories { id } availableLanguages content { language question } } announcements { id categories { id } availableLanguages content { language question answer snippet } } }}Get articles with my feedback
Returns a list of articles that user either has provided feedback for or suggested as new articles. Only user's own feedback with replies are returned (ie not feedback on the same articles provided by someone else).
{ articlesWithMyFeedback(languages: ["en", "no"]) { id type status content { language question answer snippet attributes createdDate publishDate author lastModifiedBy lastModifiedDate } feedback{ text response respondent createdTime responseTime deleted } }}Get audit logs
Returns a maximum of 1000 audit logs based on optional filters. Note that all input fields are optional and can be skipped.
query { auditLogs(userId:"00000000-0000-0000-0000-000000000000", resourceId: 123, resourceType: ARTICLE, fromTime: "2024-07-01T06:30:00", toTime: "2024-07-01T10:30:00") { id timestamp userId name resourceId resourceType operation logText }}Search articles
Performance a semantic search towards Puzzel's cloud agnostic search service.
You can optionally specify which statuses the returned articles should have. If not specified, only published articles are returned.
Languages (minimum one) is mandatory, and the following codes are supported: bg, da, de, en, es, fi, fr, it, no, nl, pl, sv
You can optionally specify one alternative view to filter on.
{ searchArticles( query: "Can you help me reset my password?" languages: ["en", "no"] status: [DRAFT, REVIEW, PUBLISHED] limit: 10 view: "mobile") { id searchScore type status attributes usageCount searchFrequency lastUseDate lastViewDate availableLanguages categories{ id name } sections{ id name } content{ language question answer snippet decisionTree { ... } contentType attributes author lastModifiedBy lastModifiedDate publishDate createdDate expiryDate alternativeViews { viewName question answer snippet contentType } } }}Get key metrics for articles
Returns various key metrics for articles.
{ articlesKeyMetrics { key count }}// Response example "data": { "articlesKeyMetrics": [ { "key": "HasExpired", "count": 3 }, { "key": "NoExpiry", "count": 302 }, { "key": "WillExpire", "count": 2 }, { "key": "HasFeedback", "count": 16 }, { "key": "ReviewStatus", "count": 7 } ]}Get alternative content views
Returns list of alternative views defined for a given customer
{ customerViews { id name useInlineStyling }}Get dashboard data
Returns key metrics to be used in the dashboard.
All input parameters are optional, however only users with kb:admin role can drop categoryIds/sectionIds.
Note that searchHits are global (not tied to a category/section).
Note that the metrics returned relates to articles mapped directly to the categoryId or sectionId in the input (meaning if you just specify categoryId 1, the metrics will not contain data for articles beloning to a section under that category. Such a sectionId must inputted specifically).
{ dashboardMetrics( language:"en" categoryIds: [1, 2] sectionIds: [1, 2] fromTime: "2024-02-01T00:00:00" toTime: "2024-02-08T23:59:59" ) { articleTotalCount articleDraftCount articleReviewCount articlePublishedCount articleExpiringCount articleExpiredCount searchHits { hits count } viewsDataPoints { year month day hour count } articleViewCount { articleId question count } viewsContextCount { viewContext count } }}Get word cloud data
Returns key words with frequencies to be used in generating a word cloud.
Note that the words are global (not tied to a category/section).
wordData( language: "en" maxWords: 10 wordCloudType: HITS fromTime: "2024-01-01T00:00:00" toTime: "2024-01-31T23:59:59") { word frequency}Get bookmarked articles
Returns a list of articles that a user has bookmarked. Note that it's only a sub set of attributes available in the response (those listed below).
{ getBookmarks { id type content { language question answer snippet contentType } }}Get user properties
Returns properties for a user
Request:{ userProperties { preferredLanguage allowedLanguages }}Response:{ "data": { "userProperties": { "preferredLanguage": "en", "allowedLanguages": [ "bg", "en", "no" ] } }}REST API [DRAFT]
Endpoints
NOTE: Only supports attachment handling and registering usage metrics
| Environment | Deployment Status | Endpoints |
|---|---|---|
| PROD OSLO | General Availability Q1 2025 | |
| PROD AZURE | Deprecated |