Skip to content

API Examples

This page provides ready-to-use code examples for common DiscoLink API operations. All examples can be tested against the demo API at https://demo.discolink.site/api.

Fetching Threads

Get All Resolved FAQ Threads

Terminal window
curl "https://demo.discolink.site/api/threads?serverId=123456789&status=resolved" \
-H "Accept: application/json"

Response:

{
"threads": [
{
"id": "111222333444555666",
"title": "How do I implement OAuth2 authentication?",
"status": "resolved",
"messageCount": 12,
"author": {
"id": "987654321",
"username": "curious_developer"
},
"channel": {
"id": "444555666",
"name": "help-forum"
},
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:22:00Z"
}
],
"total": 47,
"page": 1,
"limit": 20
}

Search Content

Terminal window
curl "https://demo.discolink.site/api/search?serverId=123456789&q=authentication+oauth" \
-H "Accept: application/json"

Response:

{
"results": [
{
"type": "thread",
"id": "111222333",
"title": "How do I implement OAuth2 authentication?",
"highlight": "...implementing <mark>OAuth</mark> <mark>authentication</mark> with Discord...",
"score": 0.95
},
{
"type": "message",
"id": "444555666",
"content": "You can use the passport-discord strategy for OAuth...",
"highlight": "...passport-discord strategy for <mark>OAuth</mark>...",
"score": 0.82,
"thread": {
"id": "111222333",
"title": "How do I implement OAuth2 authentication?"
}
}
],
"total": 15,
"query": "authentication oauth"
}

Get Thread Messages

Fetch All Messages in a Thread

Terminal window
curl "https://demo.discolink.site/api/threads/111222333/messages" \
-H "Accept: application/json"

Leaderboard

Get Top Contributors

Terminal window
curl "https://demo.discolink.site/api/leaderboard?serverId=123456789&limit=10" \
-H "Accept: application/json"

Response:

{
"users": [
{
"id": "123456789",
"username": "helpful_member",
"avatar": "abc123",
"stats": {
"messagesCount": 342,
"threadsCreated": 12,
"threadsResolved": 28,
"reactionsReceived": 156
},
"rank": 1
}
],
"total": 150,
"period": "all-time"
}

Common Patterns

Building a FAQ Page

// Complete example: Building a FAQ page
interface FAQItem {
question: string;
answer: string;
author: string;
resolvedAt: string;
}
async function buildFAQ(serverId: string): Promise<FAQItem[]> {
// Get all resolved threads
const threadsRes = await fetch(
`https://demo.discolink.site/api/threads?serverId=${serverId}&status=resolved&limit=100`
);
const { threads } = await threadsRes.json();
// Get messages for each thread
const faqItems = await Promise.all(
threads.map(async (thread) => {
const messagesRes = await fetch(
`https://demo.discolink.site/api/threads/${thread.id}/messages`
);
const { messages } = await messagesRes.json();
// First message is the question, last is usually the answer
const question = thread.title;
const answer = messages[messages.length - 1]?.content || '';
return {
question,
answer,
author: thread.author.username,
resolvedAt: thread.updatedAt
};
})
);
return faqItems;
}
hooks/useDiscoLink.ts
import { useState, useEffect } from 'react';
interface UseDiscoLinkOptions {
serverId: string;
endpoint: string;
params?: Record<string, string>;
}
export function useDiscoLink<T>({ serverId, endpoint, params = {} }: UseDiscoLinkOptions) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const searchParams = new URLSearchParams({ serverId, ...params });
const res = await fetch(
`${process.env.DISCOLINK_API_URL}/${endpoint}?${searchParams}`
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const json = await res.json();
setData(json);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
};
fetchData();
}, [serverId, endpoint, JSON.stringify(params)]);
return { data, loading, error };
}
// Usage in a component
function FAQList({ serverId }) {
const { data, loading, error } = useDiscoLink({
serverId,
endpoint: 'threads',
params: { status: 'resolved' }
});
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.threads.map(thread => (
<li key={thread.id}>{thread.title}</li>
))}
</ul>
);
}

Error Handling

async function safeApiCall<T>(url: string): Promise<T> {
const response = await fetch(url);
if (!response.ok) {
const error = await response.json().catch(() => ({}));
switch (response.status) {
case 400:
throw new Error(`Bad Request: ${error.message || 'Invalid parameters'}`);
case 401:
throw new Error('Unauthorized: Check your API key');
case 404:
throw new Error('Not Found: Resource does not exist');
case 429:
throw new Error('Rate Limited: Too many requests');
default:
throw new Error(`API Error: ${response.status}`);
}
}
return response.json();
}

Next Steps