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
curl "https://demo.discolink.site/api/threads?serverId=123456789&status=resolved" \ -H "Accept: application/json"const response = await fetch( 'https://demo.discolink.site/api/threads?serverId=123456789&status=resolved');const data = await response.json();
console.log(`Found ${data.threads.length} resolved threads`);data.threads.forEach(thread => { console.log(`- ${thread.title} (${thread.messageCount} messages)`);});interface Thread { id: string; title: string; status: 'open' | 'resolved' | 'archived'; messageCount: number; author: { id: string; username: string }; createdAt: string;}
interface ThreadsResponse { threads: Thread[]; total: number; page: number;}
async function getResolvedThreads(serverId: string): Promise<Thread[]> { const res = await fetch( `https://demo.discolink.site/api/threads?serverId=${serverId}&status=resolved` ); const data: ThreadsResponse = await res.json(); return data.threads;}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
Full-Text Search
curl "https://demo.discolink.site/api/search?serverId=123456789&q=authentication+oauth" \ -H "Accept: application/json"async function searchContent(serverId, query) { const params = new URLSearchParams({ serverId, q: query, limit: '10' });
const response = await fetch( `https://demo.discolink.site/api/search?${params}` ); return response.json();}
// Usageconst results = await searchContent('123456789', 'authentication oauth');console.log(`Found ${results.total} results`);interface SearchResult { type: 'thread' | 'message'; id: string; title?: string; content: string; highlight: string; score: number; thread?: { id: string; title: string };}
interface SearchResponse { results: SearchResult[]; total: number; query: string;}
async function search( serverId: string, query: string, options?: { limit?: number; type?: 'thread' | 'message' }): Promise<SearchResponse> { const params = new URLSearchParams({ serverId, q: query, ...(options?.limit && { limit: String(options.limit) }), ...(options?.type && { type: options.type }) });
const res = await fetch(`https://demo.discolink.site/api/search?${params}`); return res.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
curl "https://demo.discolink.site/api/threads/111222333/messages" \ -H "Accept: application/json"async function getThreadMessages(threadId) { const response = await fetch( `https://demo.discolink.site/api/threads/${threadId}/messages` ); const data = await response.json();
// Messages are returned in chronological order return data.messages;}
// Usageconst messages = await getThreadMessages('111222333');messages.forEach(msg => { console.log(`${msg.author.username}: ${msg.content}`);});interface Message { id: string; content: string; author: { id: string; username: string; avatar?: string; }; createdAt: string; reactions: Array<{ emoji: string; count: number; }>;}
async function getThreadMessages(threadId: string): Promise<Message[]> { const res = await fetch( `https://demo.discolink.site/api/threads/${threadId}/messages` ); const data = await res.json(); return data.messages;}Leaderboard
Get Top Contributors
curl "https://demo.discolink.site/api/leaderboard?serverId=123456789&limit=10" \ -H "Accept: application/json"async function getLeaderboard(serverId, limit = 10) { const response = await fetch( `https://demo.discolink.site/api/leaderboard?serverId=${serverId}&limit=${limit}` ); return response.json();}
// Display top contributorsconst { users } = await getLeaderboard('123456789', 10);users.forEach((user, i) => { console.log(`${i + 1}. ${user.username} - ${user.stats.threadsResolved} resolved`);});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 pageinterface 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;}React Hook for DiscoLink
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 componentfunction 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
- API Overview - Learn about all available endpoints
- Authentication - Set up API authentication
- Error Handling - Handle API errors gracefully