Make chatbot queries by API

The queries endpoint lets you integrate AI Hub chatbots into any workflow. You can send asynchronous queries, track their status, and retrieve replies.

This guide explains how to interact with the queries endpoint by making direct API calls. Step-by-step code snippets and a complete script provide a reference for writing your own scripts to interact with chatbots.

This page focuses on using the API to interact with the queries endpoint. See the Make chatbot queries by SDK guide to learn how to use the Python SDK to do the same.

Three types of code appear on this page.

  • Snippets - a sequence of code snippets to demonstrate API usage, omitting error handling for simplicity. Each snippet is presented and discussed in numbered steps below.

  • Complete script - all snippets are combined into a complete script for reference.

  • Enhanced script - an improved version of the complete script adds error handling and Python type annotations, resulting in near-production-quality code.

Any chatbot that you can access through the AI Hub user interface can also be accessed with the API.

API chatbot queries are visible in your query history when accessing the chatbot from the AI Hub user interface.

Before you begin

Learn about the API and SDK and install the SDK.

1

Import modules

Start your Python script by importing required modules. The third-party requests module makes it easier to send HTTP requests to the API.

1import json
2import time
3
4import requests # third-party module for making HTTP requests

If you don’t already have the requests module installed on your system, run pip install requests. There’s no harm in running the install command even if the module is already installed.

2

Define URLs

Because you use the queries endpoint for all interactions with chatbots, you must specify where to find that endpoint.

1# define URLs
2api_base_url = <API-BASE-URL>
3queries_endpoint_url = f'{api_base_url}/v2/queries'

Your API_BASE_URL depends on how you access AI Hub.

  • If you use SaaS AI Hub, set it to https://aihub.instabase.com/api.

  • If you run AI Hub on a custom domain, set it to that domain plus /api, such as https://www.acme-widgets.com/aihub/api.

3

Define authentication credentials

Every request to the AI Hub API must include authentication credential headers.

1# include authentication credentials as request headers
2api_token = <API-TOKEN>
3ib_context = <IB-CONTEXT>
4
5api_headers = {
6 'Authorization': f'Bearer {api_token}',
7 'IB-Context': ib_context
8}

To find values for api_token and ib_context, see the Code section of the Using the API & SDK page.

4

Provide the chatbot ID

Identify the chatbot to query by storing its ID in a Python dictionary.

1# provide the chatbot ID
2source_app = {'type': 'CHATBOT',
3 'id': <CHATBOT-ID>}

The value for <CHATBOT-ID> is in the chatbot URL. The chatbot ID is the 36-character string at the end of the URL, excluding the slash at the beginning of the string.

To find the chatbot’s URL, navigate to Hub and run the chatbot you want to send queries to.

The chatbot ID embedded in the chatbot's URL

Chatbot ID embedded in the URL
A chatbot’s ID changes with every version update. For convenience, queries are automatically redirected to the latest version of the chatbot.
5

Create the request payload

Querying a chatbot by API is an asynchronous operation.

  1. Send a request to the chatbot, with your query as its payload.

  2. Check whether the chatbot has finished processing the query by sending another request.

  3. If the chatbot is still processing, wait a few seconds and check its status again by sending another request.

  4. Repeat the previous step as many times as needed until the chatbot is done processing your query. The first response that includes COMPLETE status also includes the chatbot’s reply to your query.

The next snippet stores the query and key data about the chatbot. Include the data in your first request to the chatbot.

1# create payload for POST to 'queries' endpoint
2data = {'query': <QUERY>,
3 'model_name': <MODEL-NAME>,
4 'include_source_info': <INCLUDE-SOURCE-INFO>,
5 'source_app': source_app}

Parameter reference

ParameterTypeRequiredDescription
querystrYesThe question to submit to the chatbot. This can be any query you would submit through the graphical user interface, excluding requests for graphs.
model_namestrNoModel for the chatbot to use when answering your query.

multistep-lite for basic queries
multistep for complicated queries (default)

The multistep model takes more processing time and uses more consumption units, but can give better answers to difficult questions.
include_source_infoboolNoWhether the reply includes information about which documents it was compiled from. Defaults to False.
When model_name is set to multistep-lite, source info includes document names only. When model_name is set to multistep, source info includes document names and page numbers.
source_appdict[str, str]YesSee the Provide the chatbot ID section above.
6

Submit the query and capture the query_id

You’re ready to submit a query to the chatbot as an HTTP request. The HTTP response to the request contains a query ID that you must include in future requests to check the chatbot’s processing status.

The word response can mean different things. This documentation uses response to mean the HTTP response to an HTTP request, and reply to mean the chatbot’s answer to your query.
1# send the query to the chatbot and capture the 'query_id'
2response = requests.post(url=queries_endpoint_url,
3 headers=api_headers,
4 data=json.dumps(data))
5resp_data = response.json()
6query_id = resp_data.get('query_id')

Parameter reference

ParameterTypeRequiredDescription
headersdictYesSee the Define authentication credentials section for details.

The response is a JSON object containing the query ID. For example:

1{ "query_id": "f2ef9702-b018-4a45-9b2e-d1fb575b42ed" }
7

Get the query processing status and query reply

After sending your query, you must send a separate request to retrieve the chatbot’s reply. Keep calling the get chatbot query status API operation until the status returned in the response changes from RUNNING to COMPLETE. When the status is COMPLETE, the chatbot reply to your query is included in the response.

1# get the status of the query
2while True:
3 response = requests.get(url=f'{queries_endpoint_url}/{query_id}',
4 headers=api_headers)
5 response_json = response.json()
6 status = response_json.get('status')
7 if status == 'COMPLETE':
8 break
9 time.sleep(5)

Parameter reference

ParameterTypeRequiredDescription
query_idstrYesThe ID of the query. Retrieved from the response to the request made in the Submit the query and capture the query_id section above.

The response body is a JSON object containing the query ID and status. If the query status is COMPLETE, the query response is also returned. If the query status is FAILED, an error message is returned instead.

Sample JSON object in response

1{
2 "query_id": "f2ef9702-b018-4a45-9b2e-d1fb575b42ed",
3 "status": "COMPLETE",
4 "results": [
5 {
6 "response":" "<REPLY>",
7 "source_documents": [
8 {
9 "name": "file1.pdf",
10 "pages": [
11 {
12 "bboxes": [],
13 "page_number": 9.0
14 }
15 ]
16 },
17 {
18 "name": "file2.pdf",
19 "pages": [
20 {
21 "bboxes": [],
22 "page_number": 2.0
23 }
24 ]
25 }
26 ]
27 }
28 ]
29}

JSON schema

Because the snippet above converts the JSON object into a Python dictionary, the types listed in this schema are Python types, not JSON types.

KeyPython typeDescription
query_idstrID of the query.
statusstrStatus of the query.
Possible values are RUNNING, COMPLETE, or FAILED.
resultslist[dict]Container for query replies and data sources. Returned if the status field is COMPLETE.
results.responsestrChatbot’s reply to your query.
results.source_documentslist[dict]Container for information about the documents the chatbot used when composing its reply to your query.
Returned if include_source_info was set to true in the data dictionary submitted as the payload of the original query request.
results.source_documents[i].namestrName of a source document that contributed to the chatbot’s reply.
results.source_documents[i].pageslist[dict]List of objects with information about the specific pages referenced in the source document.
Page-level source information is supported only when using the multistep model.
results.source_documents[i].pages[j].page_numberfloatPage from the source document that contributed to the query’s reply.
results.source_documents[i].pages[j].bboxeslistBounding boxes from the source document, for the text that contributed to the query’s reply. Not always applicable.
errorobjectPresent only if the status is FAILED. Contains a message with information about the source of the execution error.
8

Parse the Python dictionary to extract the reply to your query and any data sources the chatbot used.

1# print the query's reply and its sources
2results = response_json['results']
3for result in results:
4 reply = result['response']
5 print(f"REPLY\n{reply}\n")
6
7 sources = result['source_documents']
8 print("SOURCE DOCUMENTS")
9 for source in sources:
10 print(f"{source['name']}")
11 pages = source['pages']
12 for page in pages:
13 page = int(page['page_number']) # convert from float
14 print(f" page {page}")

Complete script

This script combines all the snippets from above and contains all the steps needed to call the queries endpoint and interact with a chatbot. The code is deliberately minimal, to aid readability.

The script performs the following tasks:

  1. Call the send chatbot query operation, sending an asynchronous request to query a specified chatbot. A query ID is returned.

  2. Poll the get chatbot query status endpoint repeatedly, until the chatbot’s processing status changes from RUNNING to COMPLETE.

  3. Extract and print the reply and sources from the last response.

1import json
2import time
3
4import requests # third-party module for making HTTP requests
5
6# define URLs
7api_base_url = <API-BASE-URL>
8queries_endpoint_url = f'{api_base_url}/v2/queries'
9
10# include authentication credentials as request headers
11api_token = <API-TOKEN>
12ib_context = <IB-CONTEXT>
13
14api_headers = {
15 'Authorization': f'Bearer {api_token}',
16 'IB-Context': ib_context
17}
18
19# provide the chatbot ID
20source_app = {'type': 'CHATBOT',
21 'id': <CHATBOT-ID>}
22
23# create payload for POST to 'queries' endpoint
24data = {'query': <QUERY>,
25 'model_name': <MODEL-NAME>,
26 'include_source_info': <INCLUDE-SOURCE-INFO>,
27 'source_app': source_app}
28
29# send the query to the chatbot and capture the 'query_id'
30response = requests.post(url=queries_endpoint_url,
31 headers=api_headers,
32 data=json.dumps(data))
33resp_data = response.json()
34query_id = resp_data.get('query_id')
35
36# get the status of the query
37while True:
38 response = requests.get(url=f'{queries_endpoint_url}/{query_id}',
39 headers=api_headers)
40 response_json = response.json()
41 status = response_json.get('status')
42 if status == 'COMPLETE':
43 break
44 time.sleep(5)
45
46# print the query's reply and its sources
47results = response_json['results']
48for result in results:
49 reply = result['response']
50 print(f"REPLY\n{reply}\n")
51
52 sources = result['source_documents']
53 print("SOURCE DOCUMENTS")
54 for source in sources:
55 print(f"{source['name']}")
56 pages = source['pages']
57 for page in pages:
58 page = int(page['page_number']) # convert from float
59 print(f" page {page}")

Parameter reference for complete script

ParameterTypeRequiredDescription
api_rootstrNoThe root URL of your AI Hub API.

For community accounts
• Omit setting api_root.

For organization accounts
• If your organization has a custom AI Hub domain, use your organization’s root API URL, such as https://my-org.instabase.com/api.
• If your organization doesn’t have a custom AI Hub domain, omit setting api_root.
api_keystrYesYour API token.
ib_contextstrNo, but recommendedThe value for the IB-Context header that the SDK includes with all API requests.

For community accounts
• Omit setting ib_context.

For commercial accounts
• To use your personal account, set to your user ID.
• To use your organization account, set to your organization ID.
If ib_context isn’t explicitly set, requests use consumption units from your community account.
querystrYesThe question to submit to the chatbot. This can be any query you would submit through the graphical user interface, excluding requests for graphs.
model_namestrNoModel for the chatbot to use when answering your query.

multistep-lite for basic queries
multistep for complicated queries (default)

The multistep model takes more processing time and uses more consumption units, but can give better answers to difficult questions.
include_source_infoboolNoWhether the reply includes information about which documents it was compiled from. Defaults to False.
When model_name is set to multistep-lite, source info includes document names only. When model_name is set to multistep, source info includes document names and page numbers.
source_appdict[str, str]YesSee the Provide the chatbot ID section above.

Enhanced script

This script is functionally identical to the complete script above but adds error handling and Python type annotation, bringing it closer to production-grade code. Keep these guidelines and best practices in mind as you review or use this script:

  • The included error handling shows what can go wrong, but the recovery code is unrealistically basic. Before running this code in a production environment, replace sys.exit() calls with error handling appropriate to your workflow.

  • The SDK supports Python 3.7+, but this script uses improved type annotations introduced in later versions. You can safely remove the type annotations if they cause problems with your version of Python.

  • This script is presented as a single block of code to aid readability, but refactoring it into smaller functions would improve testability.

1import json
2import sys
3import time
4from typing import Any, Final, Literal, Optional
5
6import requests # third-party module for making HTTP requests
7from requests import Response
8
9# define URLs
10API_BASE_URL: Final[str] = <API-BASE-URL>
11QUERIES_ENDPOINT_URL: Final[str] = f'{API_BASE_URL}/v2/queries'
12
13# how long to wait for the Chatbot to process the query
14# and generate a reply
15PROCESSING_TIMEOUT_SECS: Final[int] = <PROCESSING-TIMEOUT-SECS>
16
17# how long to wait for an HTTP response to each HTTP request
18RESPONSE_TIMEOUT_SECS: Final[int] = <RESPONSE-TIMEOUT-SECS>
19
20# how long to wait between query processing status checks
21STATUS_POLLING_INTERVAL_SECS: Final[int] = <STATUS-POLLING-INTERVAL-SECS>
22
23# put authentication credentials in a header for API calls
24API_TOKEN: Final[str] = <API-TOKEN>
25IB_CONTEXT: Final[str] = <IB-CONTEXT>
26API_HEADERS: Final[dict[str, str]] = {
27 'Authorization': f'Bearer {API_TOKEN}',
28 'IB-Context': IB_CONTEXT
29}
30
31# provide the chatbot ID
32SOURCE_APP: Final[dict[str, str]] = {'type': 'CHATBOT',
33 'id': <CHATBOT-ID>}
34
35# create payload for POST to 'queries' endpoint
36data: dict[str, Any] = {'query': <QUERY>,
37'model_name': <MODEL-NAME>,
38'include_source_info': <INCLUDE-SOURCE-INFO>,
39'source_app': SOURCE_APP}
40
41# send the query to the chatbot and capture the 'query_id'
42try:
43 response: Response = requests.post(url=QUERIES_ENDPOINT_URL,
44 headers=API_HEADERS,
45 data=json.dumps(data),
46 timeout=RESPONSE_TIMEOUT_SECS)
47except requests.exceptions.ConnectionError as conn_err:
48 sys.exit(f"Error: Couldn't submit request to API: {conn_err}")
49except requests.exceptions.Timeout as timeout_err:
50 sys.exit(f"Error: Request to API timed out: {timeout_err}")
51
52if not response.ok:
53 sys.exit("Error: Bad response from API. "
54 f"Response status code: {response.status_code}. "
55 f"Response content: {response.text}")
56
57response_json: dict[str, Any] = response.json()
58query_id: Optional[str] = response_json.get('query_id')
59
60if not query_id:
61 sys.exit("Error: Chatbot didn't return a query_id")
62
63# get the query status and check for chatbot processing timeout
64elapsed_time_secs: int = 0
65while elapsed_time_secs < PROCESSING_TIMEOUT_SECS:
66 try:
67 response = requests.get(url=f'{QUERIES_ENDPOINT_URL}/{query_id}',
68 headers=API_HEADERS)
69 except requests.exceptions.ConnectionError as conn_err:
70 sys.exit(f"Error: Couldn't submit request to API: {conn_err}")
71 except requests.exceptions.Timeout as timeout_err:
72 sys.exit(f"Error: Request to API timed out: {timeout_err}")
73 except Exception as err:
74 sys.exit(f"Error: Request to API failed: {err}")
75
76 # check if we got back an expected status code
77 if response.ok:
78 response_json = response.json()
79 else:
80 sys.exit("Error: Bad response from API. "
81 f"Response status code: {response.status_code}. "
82 f"Response content: {response.text}")
83
84 # stop polling once the processing status is 'COMPLETE'
85 status: Optional[Literal['COMPLETE', 'FAILED', 'RUNNING']] = response_json.get('status')
86 if status == 'COMPLETE':
87 break
88 time.sleep(STATUS_POLLING_INTERVAL_SECS)
89 elapsed_time_secs += STATUS_POLLING_INTERVAL_SECS
90
91# handle processing timeout
92if elapsed_time_secs >= PROCESSING_TIMEOUT_SECS:
93 sys.exit(f"Error: Chatbot didn't finish processing the query "
94 f"within {PROCESSING_TIMEOUT_SECS} seconds")
95
96# Print the reply and its sources. Assume the API returns a well-
97# formed reply, so no need for error handling when parsing the reply
98results: list[dict] = response_json['results']
99result: dict[str, Any]
100for result in results:
101 reply: str = result['response']
102 print(f"REPLY\n{reply}\n")
103 sources: list[dict[str, Any]] = result['source_documents']
104 if sources:
105 print("SOURCE DOCUMENTS")
106 source: dict[str, Any]
107 for source in sources:
108 print(f"{source['name']}")
109 pages: list[dict] = source['pages']
110 page: dict[str, str | float]
111 for page in pages:
112 page_num: int = int(page['page_number'])
113 print(f" page {page_num}")

Parameter reference

Most of the variables or parameters in this script are described in the Parameter reference for complete script section above, but these three constants appear only in the enhanced script.

ConstantTypeRequiredDescription
API_BASE_URLstrYesThe root URL of your AI Hub API.

For community accounts, set to https://aihub.instabase.com/api.

For organization accounts
• If your organization has a custom AI Hub domain, use your organization’s root API URL, such as https://my-org.instabase.com/api.
• If your organization doesn’t have a custom AI Hub domain, use https://aihub.instabase.com/api.
PROCESSING_TIMEOUT_SECSintYesSeconds to wait for the chatbot to compose a reply to your query. Recommended value: 45
RESPONSE_TIMEOUT_SECSintYesSeconds to wait for an HTTP response to each HTTP request. Recommended value: 3
STATUS_POLLING_INTERVAL_SECSintYesSeconds to wait between checking the processing status of a query. Recommended value: 5
Was this page helpful?