APIs

Statistics API

intro we have created a separate service for statistics about your kindly chatbots this service is named sage and lives at sage kindly ai the statistics you can view in the kindly platform are provided by sage you can collect statistics for your own purposes from the same api that the platform uses sage has its own database which contains only non personal data when end users chat with chatbots their messages are stored and processed in kindly's database, and these can be manually or automatically deleted after some time to protect the end user's privacy the data in sage's database will not be deleted, but this data doesn't contain the user's message or any personal metadata, only an indication that someone messaged the bot at a specific time this way we can keep aggregated statistics such as the number of chats per day, while also allowing the end user to have their privacy protected how to query authentication if you have the required permissions, you can create a permanent api key in the platform this long lived key can be used by a programmatic service you create to obtain short lived jwts which can then be used for statistics requests send api key to api kindly ai to receive jwt curl request get \\ \ url 'https //api kindly ai/api/v2/bot/\<bot id>/sage/auth' \\ \ header 'authorization bearer \<api key>' send a request to sage kindly ai to test your new token curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/sessions/messages?from=2019 01 01\&to=2019 02 01' \\ \ header 'authorization bearer \<jwt>' timezone list of tz database time zones https //en wikipedia org/wiki/list of tz database time zones all time values in the database are stored as utc https //en wikipedia org/wiki/coordinated universal time if you want results in your local timezone, which takes into consideration daylight saving time and other irregularities, you can provide a tz argument to your api request with the tzdb name of the timezone you want it would look like this for oslo get https //sage kindly ai/api/ \&tz=europe/oslo the timezone parameter is important to consider if you are making a request where the data is aggregated by day if someone messages the bot at 9 p m (summertime) on monday in california, this is stored in the database as occurring at 4 a m on tuesday to get the api results scoped for california time, you would send a request with tz=america/los angeles in other words you must consider the location's timezone and adjust for it granularity some aggregations can use a granularity parameter, for example, the aggregation that counts the number of messages per hour, day, or week you can specify this with granularity=hour , etc these default to granularity=day if not otherwise specified note that hour granularity is only allowed if the time between from and to is one week or less source and language the events that are aggregated by sage are labeled by which source and language the user and bot were chatting with your api requests can be filtered by these values not adding any filters to your request will include all data in the results, unfiltered source source is the location where your bot may be deployed for example test is source value for conversations by bot builders within the kindly platform web is the source value for kindly chat deployed on websites, excluding the kindly platform app is the source value for chats via the application api docid\ cgad bxmm1 wvggzsmd1k if you do not filter by sources, all data will be included in the results, including test data to select only specific sources, you can send one or more filters like this get https //sage kindly ai/api/ \&sources\[]=web\&sources\[]=app you can also select sources to exclude , by prefixing with a minus sign this means that the api will return data from every source except the ones listed get https //sage kindly ai/api/ \&sources\[]= test language the language used for chat between the user and the bot is represented by a two letter language code if your bot does not use multiple languages, you can safely ignore this parameter if you have multiple languages in your bot and you want to filter by language, you can send one or more filters like this get https //sage kindly ai/api/ \&language code\[]=en\&language code\[]=nb api reference most of the apis can be filtered by time, language, and source to see what your options are for these filters, you can send a request to the /meta/options api curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/meta/options' \\ \ header 'authorization bearer \<jwt>'{ "data" { "first" "2019 04 28t07 22 52 825000", "last" "2019 09 04t06 48 41 100000", "language codes" \["en", "nb"], "sources" \["app", "test", "web"], "granularities" \["hour", "day", "week"] } } chat sessions number of sessions where users engaged with the bot curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/sessions/chats?from=2019 07 01\&to=2019 07 07' \\ \ header 'authorization bearer \<jwt>'{ "data" \[ { "count" 485, "date" "2019 07 01t00 00 00 000000" }, { "count" 434, "date" "2019 07 02t00 00 00 000000" }, { "count" 459, "date" "2019 07 03t00 00 00 000000" }, { "count" 446, "date" "2019 07 04t00 00 00 000000" }, { "count" 355, "date" "2019 07 05t00 00 00 000000" }, { "count" 283, "date" "2019 07 06t00 00 00 000000" } ] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc ) granularity (default day ) sources\[] language codes\[] user messages number of messages from users curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/sessions/messages?from=2019 07 01\&to=2019 07 07' \\ \ header 'authorization bearer \<jwt>'{ "data" \[ { "count" 1661, "date" "2019 07 01t00 00 00 000000" }, { "count" 1507, "date" "2019 07 02t00 00 00 000000" }, { "count" 1563, "date" "2019 07 03t00 00 00 000000" }, { "count" 1572, "date" "2019 07 04t00 00 00 000000" }, { "count" 1227, "date" "2019 07 05t00 00 00 000000" }, { "count" 964, "date" "2019 07 06t00 00 00 000000" } ] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) granularity (default day) sources\[] language codes\[] fallback rate time series number of and fraction of bot replies that are fallbacks, as an aggregated time series count represents the number of fallback messages in the given time interval, rate represents which fraction of the total number of bot replies in the time interval are fallbacks curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/fallbacks/series?from=2019 07 01\&to=2019 07 07' \\ \ header 'authorization bearer \<jwt>'{ "data" \[ { "count" 177, "date" "2019 07 01t00 00 00 000000", "rate" 0 12132805028009291 }, { "count" 161, "date" "2019 07 02t00 00 00 000000", "rate" 0 1207012308839985 }, { "count" 138, "date" "2019 07 03t00 00 00 000000", "rate" 0 09981955972573078 }, { "count" 149, "date" "2019 07 04t00 00 00 000000", "rate" 0 10669992872416251 }, { "count" 114, "date" "2019 07 05t00 00 00 000000", "rate" 0 10400945540503682 }, { "count" 94, "date" "2019 07 06t00 00 00 000000", "rate" 0 10891544117647059 } ] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) granularity (default day) sources\[] language codes\[] fallback rate total number of and fraction of bot replies that are fallbacks, as a total aggregate for the selected time interval count represents the number of fallback messages in the given time interval, rate represents which fraction of the total number of bot replies in the time interval are fallbacks curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/fallbacks/total?from=2019 07 01\&to=2019 07 07' \\ \ header 'authorization bearer \<jwt>'{ "data" { "count" 836, "rate" 0 11061601724160727 } } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[] greeting engagement rate shows the rate at which users engage with the bot (messaging or button clicking) after being shown a greeting message missed shows the number of sessions where the bot greeted but the user didn't interact rate is the ratio of engaged chats out of total chats curl request get \\ \ url 'https //sage kindly ai/api/v2/stats/bot/\<bot id>/sessions/engagement?from=2025 01 01\&to=2025 01 07' \\ \ header 'authorization bearer \<jwt>'{ &#x9;"data" \[ &#x9; { &#x9; "date" "2025 01 01t00 00 00 000000", &#x9; "missed" 199, &#x9; "rate" 0 8224799286351472 &#x9; }, &#x9; { &#x9; "date" "2025 01 02t00 00 00 000000", &#x9; "missed" 163, &#x9; "rate" 0 8560070671378092 &#x9; }, &#x9; { &#x9; "date" "2025 01 03t00 00 00 000000", &#x9; "missed" 216, &#x9; "rate" 0 8210439105219552 &#x9; }, &#x9; { &#x9; "date" "2025 01 04t00 00 00 000000", &#x9; "missed" 163, &#x9; "rate" 0 8454976303317535 &#x9; }, &#x9; { &#x9; "date" "2025 01 05t00 00 00 000000", &#x9; "missed" 138, &#x9; "rate" 0 8411967779056386 &#x9; }, &#x9; { &#x9; "date" "2025 01 06t00 00 00 000000", &#x9; "missed" 212, &#x9; "rate" 0 8302642113690952 &#x9; } &#x9;] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) granularity (default day) sources\[] language codes\[] engagement rate total shows the rate at which users engage with the bot (messaging or button clicking) after being shown a greeting message curl request get \\ \ url 'https //sage kindly ai/api/v2/stats/bot/\<bot id>/sessions/engagement/total?from=2025 01 01\&to=2025 01 07' \\ \ header 'authorization bearer \<jwt>'{ &#x9;"data" { &#x9; "missed" 1091, &#x9; "rate" 0 8355193728328056 &#x9;} } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[] web client / kindly chat pages lists most frequent web pages where interactions with the bot have happened returns top 3 pages by default, use the limit parameter to request more results curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/chatbubble/pages?from=2019 07 01\&to=2019 07 07' \\ \ header 'authorization bearer \<jwt>'{ "data" \[ { "messages" 1615, "sessions" 465, "web host" "www example com", "web path" "/" }, { "messages" 1512, "sessions" 428, "web host" "www example no", "web path" "/" }, { "messages" 784, "sessions" 264, "web host" "www example com", "web path" "/page" } ] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[] limit (default 3) number of handovers time series the number of handover requests (while open), requests while closed, started handovers, and ended handovers in the requested time period, as a time series curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/takeovers/series?from=2019 09 16\&to=2019 09 23' \\ \ header 'authorization bearer \<jwt>'{ "data" \[ { "date" "2019 09 16t00 00 00 000000", "ended" 40, "requests" 58, "requests while closed" 0, "started" 44 }, { "date" "2019 09 17t00 00 00 000000", "ended" 27, "requests" 40, "requests while closed" 0, "started" 28 }, { "date" "2019 09 18t00 00 00 000000", "ended" 35, "requests" 44, "requests while closed" 0, "started" 35 }, { "date" "2019 09 19t00 00 00 000000", "ended" 55, "requests" 88, "requests while closed" 0, "started" 55 }, { "date" "2019 09 20t00 00 00 000000", "ended" 64, "requests" 86, "requests while closed" 0, "started" 65 }, { "date" "2019 09 21t00 00 00 000000", "ended" 0, "requests" 0, "requests while closed" 2, "started" 0 }, { "date" "2019 09 22t00 00 00 000000", "ended" 0, "requests" 0, "requests while closed" 1, "started" 0 } ] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) granularity (default day) sources\[] language codes\[] number of handovers total the total number of handover requests (while open), requests while closed, started handovers, and ended handovers in the requested time period curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/takeovers/totals?from=2019 09 16\&to=2019 09 23' \\ \ header 'authorization bearer \<jwt>'{ "data" { "ended" 44, "requests" 79, "requests while closed" 3, "started" 47 } } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[] button clicks an ordered list of the most clicked buttons in the chatbot, and the dialogues the buttons belong to has both a count of the number of occurrences and a ratio of the total amount of button clicks for the period returns top 5 results by default use the limit parameter to request more data curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/buttons/most clicked?from=2019 09 16\&to=2019 09 23' \\ \ header 'authorization bearer \<jwt>'{ "data" \[ { "button id" "9d09d898 90d5 4ba9 879c 7faa0f3ec629", "button type" "quick reply", "count" 46, "dialogue id" "6a6de8f8 724d 4dc3 adcb 0b30373cfb3b", "ratio" 0 12234042553191489 }, { "button id" "6b0c5cc7 d612 4f1e bfd9 6057130146f3", "button type" "dialogue trigger", "count" 26, "dialogue id" "6a6de8f8 724d 4dc3 adcb 0b30373cfb3b", "ratio" 0 06914893617021277 }, { "button id" "a75a41b7 0132 4c0c 9cf7 82cb500c8af9", "button type" "dialogue trigger", "count" 23, "dialogue id" "6a6de8f8 724d 4dc3 adcb 0b30373cfb3b", "ratio" 0 061170212765957445 }, { "button id" "17b666ac 0276 478b a626 8659a90a1a25", "button type" "quick reply", "count" 20, "dialogue id" "c4aaf069 a0b0 4eb1 ba65 81f46f8c8ecc", "ratio" 0 05319148936170213 }, { "button id" "4f85b25b b793 4d20 9479 3c2c5b224ebf", "button type" "dialogue trigger", "count" 17, "dialogue id" "72f96a8f 4aaf 4ac2 bb73 1cbec8f2aa57", "ratio" 0 04521276595744681 } ] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[] limit (default 5) labels the most frequent labels added to chats returns top 5 labels by default use the limit parameter to request more data curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/chatlabels/added?from=2019 09 16\&to=2019 09 23' \\ \ header 'authorization bearer \<jwt>'{ "data" \[ { "count" 5, "label id" "35bf04c0 392d 46a0 a741 4d660134d461", "label text" "some label" }, { "count" 2, "label id" "50e57dca 9045 46bf 93d4 55de77795444", "label text" "another label" }, { "count" 2, "label id" "2e08978f 24f0 4207 97c0 8945e19b751e", "label text" "label 3" } ] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[] limit (default 5) customer feedback shows the number of feedbacks in each category ( /bot or /handover ) for the given time period count shows the number of times a particular rating has been given index is a representation of the ordering of the feedback options shown to the user 0 is the leftmost option, etc most rating systems order the values left to right from worst to best, but this is customizable rating is the text description of the given feedback rating system is the type of feedback shown ratio is the number of feedbacks given of this rating out of the total number of feedbacks given \# for bot feedbacks curl request get \\ \ url 'https //sage kindly ai/api/v2/stats/bot/\<bot id>/feedback/bot?from=2025 01 01\&to=2025 01 07' \\ \ header 'authorization basic \<jwt>' \# for handover feedbacks curl request get \\ \ url 'https //sage kindly ai/api/v2/stats/bot/\<bot id>/feedback/handover?from=2025 01 01\&to=2025 01 07' \\ \ header 'authorization basic \<jwt>'{ &#x9;"data" \[ &#x9; { &#x9; "count" 5, &#x9; "index" 0, &#x9; "rating" "bad", &#x9; "rating system" 5, &#x9; "ratio" 0 45454545454545453 &#x9; }, &#x9; { &#x9; "count" 4, &#x9; "index" 2, &#x9; "rating" "okay", &#x9; "rating system" 5, &#x9; "ratio" 0 36363636363636365 &#x9; }, &#x9; { &#x9; "count" 2, &#x9; "index" 4, &#x9; "rating" "great", &#x9; "rating system" 5, &#x9; "ratio" 0 18181818181818182 &#x9; } &#x9;] } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[] example this example requires python 3 6 or higher (uses f strings https //www python org/dev/peps/pep 0498/ ) and the package requests https //pypi org/project/requests/ you will need to provide two values yourself, the relevant bot id and an api key with "read statistics" permissions that you have created at https //app kindly ai/bot/bot id/connect/api keys the code exchanges the api key for a jwt, uses the jwt to get data about the number of messages per day for the bot's lifetime, then renders the data as a unicode box character bar chart from time import sleep from urllib parse import urljoin import requests bot id int = replace me kindly statistics api key str = replace me # get this from https //app kindly ai/workspace/bot id/connect/api keys sage api root = 'https //sage kindly ai/api/v1/' jwt = none def get new jwt() url = f'https //api kindly ai/api/v2/bot/{bot id}/sage/auth' response = requests get(url, headers={'authorization' f'bearer {kindly statistics api key}'}) response raise for status() return response json()\['jwt'] def sage request(endpoint, params=none) global jwt url = urljoin(sage api root, f"stats/bot/{bot id}/{endpoint lstrip('/')}") while true if jwt is none jwt = get new jwt() try response = requests get(url, params, headers={'authorization' f'bearer {jwt}'}) response raise for status() except requests httperror as e if e response status code == 401 print('401 fetching new jwt before retrying') jwt = none continue if e response status code == 429 wait time = e response headers get('retry after', 10) print(f'429 rate limited waiting {wait time}s before retrying') sleep(wait time) continue raise return response json()\['data'] \# first, fetch some metadata about the bot options = sage request('/meta/options') first = options\['first'] last = options\['last'] granularities = options\['granularities'] language codes = options\['language codes'] sources = options\['sources'] \# display the metadata print( f""" the earliest date with data is {first} the latest date with data is {last} granularity options are {granularities} language options are {language codes} source options are {sources} """ ) \# then, fetch data about the number of messages in the time period messages = sage request('/sessions/messages', {'from' first, 'to' last}) highest = max(x\['count'] for x in messages) if highest == 0 raise exception('no data found') \# display the data about the number of messages in the terminal def bar chart(label, n, scale=1) """ make a "sideways bar chart" with unicode box characters """ width = n // scale if n == 0 bar = '' elif width == 0 bar = '▍' else bar = '█' width return f"{label} {bar} {n}" line width = 80 c = highest // line width print(f'number of messages between {first} and {last}') print( (bar chart(x\['date'] split('t', 2)\[0], x\['count'], scale=c) for x in messages), sep='\n') legacy apis these apis are for deprecated features that may be removed in the future, but as long as they remain compatible we keep documentation here chat bubble feedback if you have enabled the feedback feature in kindly chat you can get a summary of the ratings given by users in the period the api considers the ratings as numbers, with 1 being the lowest rating both the count of the number of ratings and the ratio of the total number of ratings is given this api only returns aggregated data if you want to analyze the feedback texts users have given you can get these from an inbox backup see also inbox backup to gcs bucket docid\ rt 9y4ir9pe18m9lvmuwr curl request get \\ \ url 'https //sage kindly ai/api/v1/stats/bot/\<bot id>/feedback/summary?from=2019 09 16\&to=2019 09 23' \\ \ header 'authorization bearer \<jwt>'{ "data" { "binary" \[ { "count" 50, "rating" 1, "ratio" 0 5 }, { "count" 50, "rating" 2, "ratio" 0 5 } ], "emojis" \[ { "count" 0, "rating" 1, "ratio" 0 0 }, { "count" 0, "rating" 2, "ratio" 0 0 }, { "count" 0, "rating" 3, "ratio" 0 0 } ] } } required parameters from (yyyy mm dd) to (yyyy mm dd) optional parameters tz (default utc) sources\[] language codes\[]