Skip to main content

Asking Questions

Query your Chat Aid knowledge base and receive AI-generated answers with source citations.

Endpoint

POST https://api.chataid.com/chat/completions/custom

Authentication

Authorization: YOUR_API_KEY
Content-Type: application/json
No Bearer Prefix

Do not include "Bearer " before your API key.

How It Works

The API uses polling for asynchronous processing:

  1. Submit question → receive promptId and pollEndpoint
  2. Poll endpoint at recommended timeInterval
  3. Stop when canPoll is false
  4. Retrieve answer and sources

This ensures high-quality answers for complex queries.

Request Parameters

Submit Question

POST /chat/completions/custom

ParameterTypeRequiredDescription
promptstringYesThe question to answer
parentTsstringNoUnix timestamp for conversation threading
messageTsstringNoUnix timestamp of current message
wikiFiltersobjectNoFilter search scope (see Wiki Filters)

Example

curl -X POST https://api.chataid.com/chat/completions/custom \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "What is our refund policy?"}'
{
"prompt": "What is our refund policy?"
}

Response

Initial Response

Status: 200 OK

{
"ok": true,
"promptId": "65e1c08202791119fbe1d476",
"pollEndpoint": "https://api.chataid.com/chat/completions/custom/65e1c08202791119fbe1d476",
"timeInterval": 5000,
"votingEndpoint": "https://api.chataid.com/chat/completions/feedback/65e1c08202791119fbe1d476"
}
FieldDescription
promptIdUnique question identifier
pollEndpointURL to poll for answer
timeIntervalRecommended poll interval (milliseconds)
votingEndpointURL for feedback submission

Poll Response (Processing)

GET {pollEndpoint}

{
"ok": true,
"data": {
"canPoll": true,
"response": "Loading completions..."
}
}

Poll Response (Complete)

{
"ok": true,
"data": {
"canPoll": false,
"response": "Our refund policy allows customers to return products within 30 days...",
"sources": {
"formatted": "**Sources:**\n- [Refund Policy](https://...) (Confluence)",
"raw": [
{
"name": "Refund Policy",
"provider": "confluence",
"url": "https://docs.example.com/policies/refunds"
}
]
}
}
}
FieldDescription
data.canPollfalse when answer is ready
data.responseAnswer text or loading message
data.sourcesSource citations (when ready)
data.sources.formattedMarkdown-formatted sources
data.sources.rawArray of source objects

Error Response

Status: 400 or 401

{
"ok": false,
"message": "promptId is invalid"
}

See Getting Started - Error Handling.

Polling Best Practices

  1. Respect timeInterval - Use the returned interval
  2. Check canPoll - Stop when false
  3. Set timeout - Limit to 60 seconds total (~12 attempts)
  4. Handle errors - Catch network failures gracefully
  5. Cache results - Store answers for repeated questions

Wiki Filters

Restrict search scope by filtering teams.

{
"prompt": "What is the deployment process?",
"wikiFilters": {
"teams": ["team-id-1", "team-id-2"]
}
}
FieldDescription
wikiFilters.teamsArray of team IDs to search within
API Key Configuration

Teams must be accessible by your API key (configured in Settings → Custom APIs). The wikiFilters further restricts within those teams.

Conversation Threading

Maintain context across multiple questions using parentTs.

Example Flow

Question 1:

{
"prompt": "What is our refund policy?",
"parentTs": "1640995200"
}

Question 2 (follow-up):

{
"prompt": "What about international orders?",
"parentTs": "1640995200",
"messageTs": "1640995260"
}

Chat Aid understands "international orders" refers to refunds due to conversation context.

Best Practices

  • Use unique parentTs per conversation
  • Increment messageTs for follow-ups
  • Start new conversations for unrelated topics
  • Conversations retained for 90 days

Code Examples

Complete JavaScript Implementation
const axios = require('axios');

class ChatAidClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseURL = 'https://api.chataid.com';
}

async query(prompt, options = {}) {
// Submit question
const submitResponse = await axios.post(
`${this.baseURL}/chat/completions/custom`,
{
prompt,
parentTs: options.parentTs,
messageTs: options.messageTs,
wikiFilters: options.wikiFilters
},
{
headers: {
'Authorization': this.apiKey,
'Content-Type': 'application/json'
},
timeout: 30000
}
);

if (!submitResponse.data.ok) {
throw new Error(submitResponse.data.message);
}

const { promptId, pollEndpoint, timeInterval } = submitResponse.data;

// Poll for answer
const result = await this.pollForAnswer(pollEndpoint, timeInterval);

return {
promptId,
answer: result.response,
sources: result.sources
};
}

async pollForAnswer(pollEndpoint, interval, maxAttempts = 12) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
await new Promise(resolve => setTimeout(resolve, interval));

const response = await axios.get(pollEndpoint, {
headers: { 'Authorization': this.apiKey }
});

if (!response.data.ok) {
throw new Error(response.data.message);
}

const { canPoll, response: answer, sources } = response.data.data;

if (!canPoll) {
return { response: answer, sources };
}
}

throw new Error('Polling timeout');
}
}

// Usage
const client = new ChatAidClient(process.env.CHATAID_API_KEY);

// Simple query
const result = await client.query('What is our refund policy?');
console.log(result.answer);

// With filters
const result2 = await client.query('Find compliance docs', {
wikiFilters: { teams: ['team-123'] }
});

// Conversation
const parentTs = Date.now().toString();
const r1 = await client.query('What is our refund policy?', { parentTs });
const r2 = await client.query('What about international orders?', {
parentTs,
messageTs: (Date.now() + 1000).toString()
});