diff options
-rw-r--r-- | static/api-docs-script.js | 449 | ||||
-rw-r--r-- | static/api-docs-styles.css | 1073 | ||||
-rw-r--r-- | static/api-docs.html | 937 |
3 files changed, 2459 insertions, 0 deletions
diff --git a/static/api-docs-script.js b/static/api-docs-script.js new file mode 100644 index 0000000..436067d --- /dev/null +++ b/static/api-docs-script.js @@ -0,0 +1,449 @@ +// DOM Elements +const elements = { + sidebar: document.getElementById('sidebar'), + apiTester: document.getElementById('apiTester'), + closeTester: document.getElementById('closeTester'), + getApiKeyBtn: document.getElementById('getApiKeyBtn'), + tryApiBtn: document.getElementById('tryApiBtn'), + toast: document.getElementById('toast') +}; + +// Navigation and scrolling +const setupNavigation = () => { + // Smooth scrolling for navigation links + document.querySelectorAll('.nav-item').forEach(link => { + link.addEventListener('click', (e) => { + e.preventDefault(); + const targetId = link.getAttribute('href').substring(1); + const targetElement = document.getElementById(targetId); + + if (targetElement) { + targetElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + + // Update active nav item + document.querySelectorAll('.nav-item').forEach(item => { + item.classList.remove('active'); + }); + link.classList.add('active'); + } + }); + }); + + // Update active nav item on scroll + const observerOptions = { + rootMargin: '-100px 0px -50% 0px', + threshold: 0 + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const id = entry.target.id; + const navLink = document.querySelector(`[href="#${id}"]`); + + if (navLink) { + document.querySelectorAll('.nav-item').forEach(item => { + item.classList.remove('active'); + }); + navLink.classList.add('active'); + } + } + }); + }, observerOptions); + + // Observe all sections + document.querySelectorAll('.doc-section').forEach(section => { + observer.observe(section); + }); +}; + +// Code tabs functionality +const setupCodeTabs = () => { + document.querySelectorAll('.code-tabs').forEach(tabGroup => { + const tabs = tabGroup.querySelectorAll('.tab-btn'); + const codeExample = tabGroup.closest('.code-example'); + const contents = codeExample.querySelectorAll('.tab-content'); + + tabs.forEach(tab => { + tab.addEventListener('click', () => { + const targetTab = tab.dataset.tab; + + // Update active tab + tabs.forEach(t => t.classList.remove('active')); + tab.classList.add('active'); + + // Update active content + contents.forEach(content => { + content.classList.remove('active'); + if (content.id === targetTab) { + content.classList.add('active'); + } + }); + }); + }); + }); +}; + +// Copy to clipboard functionality +const setupCopyButtons = () => { + document.querySelectorAll('.copy-btn').forEach(button => { + button.addEventListener('click', async () => { + const copyTarget = button.dataset.copy; + const targetElement = document.getElementById(copyTarget); + + if (targetElement) { + try { + await navigator.clipboard.writeText(targetElement.textContent); + showToast('Copied to clipboard!', 'success'); + + // Visual feedback + const originalText = button.textContent; + button.textContent = 'Copied!'; + setTimeout(() => { + button.textContent = originalText; + }, 2000); + } catch (err) { + console.error('Failed to copy:', err); + showToast('Failed to copy to clipboard', 'error'); + } + } + }); + }); +}; + +// API Tester functionality +const setupApiTester = () => { + const tester = elements.apiTester; + const closeTester = elements.closeTester; + const tryApiBtn = elements.tryApiBtn; + const sendRequestBtn = document.getElementById('sendRequest'); + + // Show API tester + tryApiBtn.addEventListener('click', () => { + tester.classList.add('show'); + document.body.style.overflow = 'hidden'; + }); + + // Close API tester + const closeTesterModal = () => { + tester.classList.remove('show'); + document.body.style.overflow = 'auto'; + }; + + closeTester.addEventListener('click', closeTesterModal); + + // Close on outside click + tester.addEventListener('click', (e) => { + if (e.target === tester) { + closeTesterModal(); + } + }); + + // Close on escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && tester.classList.contains('show')) { + closeTesterModal(); + } + }); + + // Try It buttons for specific endpoints + document.querySelectorAll('.try-it-btn').forEach(button => { + button.addEventListener('click', () => { + const endpoint = button.dataset.endpoint; + populateApiTester(endpoint); + tester.classList.add('show'); + document.body.style.overflow = 'hidden'; + }); + }); + + // Send API request + sendRequestBtn.addEventListener('click', async () => { + await sendApiRequest(); + }); +}; + +// Populate API tester with endpoint data +const populateApiTester = (endpoint) => { + const methodSelect = document.getElementById('testMethod'); + const endpointInput = document.getElementById('testEndpoint'); + const headersTextarea = document.getElementById('testHeaders'); + const bodyTextarea = document.getElementById('testBody'); + + const endpointConfigs = { + projects: { + method: 'GET', + endpoint: '/projects', + headers: `Authorization: Bearer your_api_key_here +Content-Type: application/json`, + body: '' + } + }; + + const config = endpointConfigs[endpoint]; + if (config) { + methodSelect.value = config.method; + endpointInput.value = config.endpoint; + headersTextarea.value = config.headers; + bodyTextarea.value = config.body; + } +}; + +// Send API request (mock implementation) +const sendApiRequest = async () => { + const method = document.getElementById('testMethod').value; + const endpoint = document.getElementById('testEndpoint').value; + const headers = document.getElementById('testHeaders').value; + const body = document.getElementById('testBody').value; + const responseStatus = document.getElementById('responseStatus'); + const responseBody = document.getElementById('responseBody'); + + // Show loading state + responseStatus.textContent = 'Sending request...'; + responseStatus.className = 'response-status'; + responseBody.textContent = ''; + + try { + // Parse headers + const headerLines = headers.split('\n').filter(line => line.trim()); + const headerObj = {}; + headerLines.forEach(line => { + const [key, ...valueParts] = line.split(':'); + if (key && valueParts.length > 0) { + headerObj[key.trim()] = valueParts.join(':').trim(); + } + }); + + // Mock API response based on endpoint + const mockResponse = generateMockResponse(method, endpoint); + + // Simulate network delay + await new Promise(resolve => setTimeout(resolve, 1000)); + + // Display response + responseStatus.textContent = `${mockResponse.status} ${mockResponse.statusText}`; + responseStatus.className = `response-status ${mockResponse.status < 400 ? 'success' : 'error'}`; + responseBody.textContent = JSON.stringify(mockResponse.data, null, 2); + + showToast('Request completed', 'success'); + + } catch (error) { + responseStatus.textContent = '500 Internal Server Error'; + responseStatus.className = 'response-status error'; + responseBody.textContent = JSON.stringify({ + error: { + code: 'request_failed', + message: error.message || 'Failed to send request' + } + }, null, 2); + + showToast('Request failed', 'error'); + } +}; + +// Generate mock API responses +const generateMockResponse = (method, endpoint) => { + const responses = { + 'GET /projects': { + status: 200, + statusText: 'OK', + data: { + data: [ + { + id: 'proj_1234567890', + name: 'Website Redesign', + description: 'Complete overhaul of company website', + status: 'active', + created_at: '2025-01-15T10:30:00Z', + updated_at: '2025-01-20T14:22:00Z', + owner: { + id: 'user_0987654321', + name: 'John Doe', + email: 'john@company.com' + }, + team_id: 'team_1122334455', + task_count: 24, + completed_tasks: 12, + progress: 50.0, + due_date: '2025-03-01T00:00:00Z', + tags: ['design', 'frontend', 'priority-high'] + } + ], + pagination: { + limit: 20, + offset: 0, + total: 1, + has_more: false + } + } + }, + 'POST /projects': { + status: 201, + statusText: 'Created', + data: { + id: 'proj_9876543210', + name: 'Mobile App Development', + description: 'Build iOS and Android mobile applications', + status: 'active', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + owner: { + id: 'user_0987654321', + name: 'John Doe', + email: 'john@company.com' + }, + team_id: 'team_1122334455', + task_count: 0, + completed_tasks: 0, + progress: 0.0, + due_date: '2025-06-01T00:00:00Z', + tags: ['mobile', 'ios', 'android'] + } + } + }; + + const key = `${method} ${endpoint}`; + return responses[key] || { + status: 404, + statusText: 'Not Found', + data: { + error: { + code: 'endpoint_not_found', + message: 'The requested endpoint was not found' + } + } + }; +}; + +// Toast notifications +const showToast = (message, type = 'success') => { + const toast = elements.toast; + const toastMessage = toast.querySelector('.toast-message'); + const toastIcon = toast.querySelector('.toast-icon'); + + toastMessage.textContent = message; + + if (type === 'success') { + toast.style.background = 'var(--success)'; + toastIcon.textContent = '✓'; + } else { + toast.style.background = 'var(--error)'; + toastIcon.textContent = '✕'; + } + + toast.classList.add('show'); + + setTimeout(() => { + toast.classList.remove('show'); + }, 4000); +}; + +// Get API Key functionality +const setupGetApiKey = () => { + elements.getApiKeyBtn.addEventListener('click', () => { + showToast('Redirecting to API key management...', 'success'); + setTimeout(() => { + // In a real app, this would redirect to the API key management page + window.location.href = 'login.html'; + }, 2000); + }); +}; + +// Navbar background on scroll +const setupNavbarScroll = () => { + window.addEventListener('scroll', () => { + const navbar = document.querySelector('.navbar'); + if (window.scrollY > 50) { + navbar.style.background = 'rgba(255, 255, 255, 0.98)'; + } else { + navbar.style.background = 'rgba(255, 255, 255, 0.95)'; + } + }); +}; + +// Button click handlers +const setupButtonHandlers = () => { + document.querySelectorAll('.btn').forEach(btn => { + btn.addEventListener('click', (e) => { + const buttonText = btn.textContent.toLowerCase(); + + if (buttonText.includes('trial') || buttonText.includes('start')) { + if (!btn.closest('.api-tester') && !btn.id) { + e.preventDefault(); + showToast('Starting your free trial! Redirecting...', 'success'); + setTimeout(() => { + window.location.href = 'signup.html'; + }, 2000); + } + } + }); + }); +}; + +// Syntax highlighting for code blocks (simple implementation) +const setupSyntaxHighlighting = () => { + document.querySelectorAll('pre code').forEach(block => { + const text = block.textContent; + + // Simple JSON highlighting + if (text.trim().startsWith('{') || text.trim().startsWith('[')) { + try { + const parsed = JSON.parse(text); + const highlighted = JSON.stringify(parsed, null, 2) + .replace(/"([^"]+)":/g, '<span style="color: #8b5cf6;">"$1":</span>') + .replace(/: "([^"]+)"/g, ': <span style="color: #10b981;">"$1"</span>') + .replace(/: (\d+)/g, ': <span style="color: #f59e0b;">$1</span>') + .replace(/: (true|false|null)/g, ': <span style="color: #ef4444;">$1</span>'); + + block.innerHTML = highlighted; + } catch (e) { + // If JSON parsing fails, leave as is + } + } + + // Simple curl command highlighting + if (text.includes('curl')) { + const highlighted = text + .replace(/curl/g, '<span style="color: #8b5cf6;">curl</span>') + .replace(/-X (GET|POST|PUT|DELETE)/g, '<span style="color: #f59e0b;">-X</span> <span style="color: #10b981;">$1</span>') + .replace(/-H/g, '<span style="color: #f59e0b;">-H</span>') + .replace(/-d/g, '<span style="color: #f59e0b;">-d</span>'); + + block.innerHTML = highlighted; + } + }); +}; + +// Initialize everything +const init = () => { + setupNavigation(); + setupCodeTabs(); + setupCopyButtons(); + setupApiTester(); + setupGetApiKey(); + setupNavbarScroll(); + setupButtonHandlers(); + setupSyntaxHighlighting(); + + // Set first nav item as active initially + const firstNavItem = document.querySelector('.nav-item'); + if (firstNavItem) { + firstNavItem.classList.add('active'); + } +}; + +// Initialize when DOM is loaded +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); +} else { + init(); +} + +// Export for potential external use +window.TaskFlowAPIDocs = { + showToast, + populateApiTester, + sendApiRequest +}; diff --git a/static/api-docs-styles.css b/static/api-docs-styles.css new file mode 100644 index 0000000..a97e15e --- /dev/null +++ b/static/api-docs-styles.css @@ -0,0 +1,1073 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + --primary-color: #6366f1; + --primary-dark: #4f46e5; + --secondary-color: #f1f5f9; + --text-primary: #1e293b; + --text-secondary: #64748b; + --background: #ffffff; + --surface: #f8fafc; + --border: #e2e8f0; + --success: #10b981; + --warning: #f59e0b; + --error: #ef4444; + --code-bg: #1e293b; + --code-text: #e2e8f0; + --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1); + --gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); +} + +body { + font-family: 'Inter', sans-serif; + line-height: 1.6; + color: var(--text-primary); + background: var(--background); +} + +/* Navigation */ +.navbar { + position: fixed; + top: 0; + width: 100%; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + z-index: 1000; + border-bottom: 1px solid var(--border); +} + +.nav-container { + max-width: 1200px; + margin: 0 auto; + padding: 1rem 2rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.nav-logo { + font-size: 1.5rem; + font-weight: 700; + background: var(--gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-decoration: none; +} + +.nav-menu { + display: flex; + list-style: none; + gap: 2rem; +} + +.nav-link { + text-decoration: none; + color: var(--text-primary); + font-weight: 500; + transition: color 0.3s ease; +} + +.nav-link:hover { + color: var(--primary-color); +} + +.nav-actions { + display: flex; + align-items: center; + gap: 1rem; +} + +/* Buttons */ +.btn { + padding: 0.75rem 1.5rem; + border: none; + border-radius: 0.5rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + text-decoration: none; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + font-size: 0.875rem; +} + +.btn-primary { + background: var(--gradient); + color: white; + box-shadow: var(--shadow); +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-lg); +} + +.btn-secondary { + background: white; + color: var(--text-primary); + border: 2px solid var(--border); +} + +.btn-secondary:hover { + border-color: var(--primary-color); + color: var(--primary-color); +} + +.btn-ghost { + background: transparent; + color: var(--text-primary); + border: none; +} + +.btn-ghost:hover { + background: var(--surface); +} + +/* Layout */ +.docs-layout { + display: flex; + margin-top: 80px; + min-height: calc(100vh - 80px); +} + +.sidebar { + width: 300px; + background: var(--surface); + border-right: 1px solid var(--border); + padding: 2rem; + position: sticky; + top: 80px; + height: calc(100vh - 80px); + overflow-y: auto; +} + +.sidebar-header { + margin-bottom: 2rem; +} + +.sidebar-header h3 { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.api-version { + background: var(--primary-color); + color: white; + padding: 0.25rem 0.75rem; + border-radius: 1rem; + font-size: 0.75rem; + font-weight: 600; + display: inline-block; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.nav-section h4 { + font-size: 0.875rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 1rem; +} + +.nav-section ul { + list-style: none; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.nav-item { + color: var(--text-primary); + text-decoration: none; + padding: 0.5rem 0.75rem; + border-radius: 0.375rem; + transition: all 0.3s ease; + font-size: 0.875rem; +} + +.nav-item:hover, +.nav-item.active { + background: var(--primary-color); + color: white; +} + +.main-content { + flex: 1; + padding: 2rem 3rem; + max-width: calc(100vw - 300px); +} + +/* Content Header */ +.content-header { + margin-bottom: 3rem; + padding-bottom: 2rem; + border-bottom: 1px solid var(--border); +} + +.content-header h1 { + font-size: 3rem; + font-weight: 700; + margin-bottom: 1rem; +} + +.content-header p { + font-size: 1.25rem; + color: var(--text-secondary); + margin-bottom: 2rem; +} + +.quick-actions { + display: flex; + align-items: center; + gap: 1rem; + flex-wrap: wrap; +} + +.api-status { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; + color: var(--text-secondary); +} + +.status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--success); +} + +.status-dot.operational { + background: var(--success); +} + +/* Documentation Sections */ +.doc-section { + margin-bottom: 4rem; + scroll-margin-top: 100px; +} + +.doc-section h2 { + font-size: 2rem; + font-weight: 700; + margin-bottom: 1rem; + color: var(--text-primary); +} + +.doc-section h3 { + font-size: 1.5rem; + font-weight: 600; + margin: 2rem 0 1rem 0; + color: var(--text-primary); +} + +.doc-section h4 { + font-size: 1.125rem; + font-weight: 600; + margin: 1.5rem 0 1rem 0; + color: var(--text-primary); +} + +.doc-section p { + margin-bottom: 1.5rem; + color: var(--text-secondary); + line-height: 1.7; +} + +.feature-list { + list-style: none; + margin: 1.5rem 0; +} + +.feature-list li { + padding: 0.5rem 0; + padding-left: 1.5rem; + position: relative; + color: var(--text-secondary); +} + +.feature-list li::before { + content: '✓'; + position: absolute; + left: 0; + color: var(--success); + font-weight: bold; +} + +/* Info Boxes */ +.info-box { + background: var(--surface); + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 1.5rem; + margin: 2rem 0; + display: flex; + align-items: flex-start; + gap: 1rem; +} + +.info-icon { + font-size: 1.5rem; + margin-top: 0.25rem; +} + +.info-content h4 { + margin: 0 0 0.5rem 0; + font-size: 1rem; +} + +.info-content code { + background: var(--code-bg); + color: var(--code-text); + padding: 0.5rem 1rem; + border-radius: 0.375rem; + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; +} + +/* Authentication Methods */ +.auth-methods { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; + margin: 2rem 0; +} + +.auth-method { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 2rem; +} + +.auth-method h3 { + margin-top: 0; + margin-bottom: 1rem; +} + +/* Rate Limits */ +.rate-limits { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1.5rem; + margin: 2rem 0; +} + +.rate-limit-tier { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 1.5rem; + text-align: center; +} + +.rate-limit-tier h4 { + margin: 0 0 1rem 0; + color: var(--primary-color); +} + +.limit-value { + font-size: 1.5rem; + font-weight: 700; + color: var(--text-primary); + margin-bottom: 0.5rem; +} + +.limit-burst { + font-size: 0.875rem; + color: var(--text-secondary); +} + +/* Error Codes */ +.error-codes { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 1rem; + margin: 2rem 0; +} + +.error-code { + background: white; + border: 1px solid var(--border); + border-radius: 0.5rem; + padding: 1rem; + display: flex; + align-items: center; + gap: 1rem; +} + +.code-number { + font-size: 1.25rem; + font-weight: 700; + color: var(--primary-color); + font-family: 'JetBrains Mono', monospace; + min-width: 3rem; +} + +.code-description h4 { + margin: 0 0 0.25rem 0; + font-size: 1rem; +} + +.code-description p { + margin: 0; + font-size: 0.875rem; + color: var(--text-secondary); +} + +/* Code Examples */ +.code-example { + margin: 2rem 0; + border-radius: 0.75rem; + overflow: hidden; + border: 1px solid var(--border); +} + +.code-header { + background: var(--surface); + padding: 1rem 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid var(--border); +} + +.code-title { + font-weight: 600; + color: var(--text-primary); +} + +.code-tabs { + display: flex; + gap: 0.5rem; +} + +.tab-btn { + padding: 0.5rem 1rem; + border: none; + background: transparent; + color: var(--text-secondary); + cursor: pointer; + border-radius: 0.375rem; + font-size: 0.875rem; + transition: all 0.3s ease; +} + +.tab-btn.active, +.tab-btn:hover { + background: white; + color: var(--primary-color); +} + +.copy-btn { + padding: 0.5rem 1rem; + border: 1px solid var(--border); + background: white; + color: var(--text-secondary); + border-radius: 0.375rem; + cursor: pointer; + font-size: 0.875rem; + transition: all 0.3s ease; +} + +.copy-btn:hover { + color: var(--primary-color); + border-color: var(--primary-color); +} + +.code-content { + position: relative; +} + +.tab-content { + display: none; +} + +.tab-content.active { + display: block; +} + +.code-example pre { + background: var(--code-bg); + color: var(--code-text); + padding: 1.5rem; + margin: 0; + overflow-x: auto; + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; + line-height: 1.6; +} + +.code-example code { + background: transparent; + color: inherit; + padding: 0; +} + +/* Endpoints */ +.endpoint-group { + margin: 2rem 0; +} + +.endpoint { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + margin-bottom: 2rem; + overflow: hidden; +} + +.endpoint-header { + background: var(--surface); + padding: 1.5rem 2rem; + display: flex; + align-items: center; + gap: 1rem; + border-bottom: 1px solid var(--border); +} + +.method { + padding: 0.5rem 1rem; + border-radius: 0.375rem; + font-weight: 700; + font-size: 0.875rem; + font-family: 'JetBrains Mono', monospace; + min-width: 4rem; + text-align: center; +} + +.method.get { + background: rgba(16, 185, 129, 0.1); + color: var(--success); +} + +.method.post { + background: rgba(99, 102, 241, 0.1); + color: var(--primary-color); +} + +.method.put { + background: rgba(245, 158, 11, 0.1); + color: var(--warning); +} + +.method.delete { + background: rgba(239, 68, 68, 0.1); + color: var(--error); +} + +.endpoint-path { + font-family: 'JetBrains Mono', monospace; + font-weight: 600; + color: var(--text-primary); + flex: 1; +} + +.endpoint-title { + font-weight: 600; + color: var(--text-primary); +} + +.endpoint-content { + padding: 2rem; +} + +.endpoint-content p { + margin-bottom: 2rem; +} + +/* Parameters */ +.parameters { + margin: 1.5rem 0; +} + +.parameter { + display: grid; + grid-template-columns: 1fr 1fr 2fr; + gap: 1rem; + padding: 1rem; + border-bottom: 1px solid var(--border); + align-items: start; +} + +.parameter:last-child { + border-bottom: none; +} + +.parameter.required .param-name::after { + content: ' *'; + color: var(--error); +} + +.param-name { + font-family: 'JetBrains Mono', monospace; + font-weight: 600; + color: var(--text-primary); +} + +.param-type { + font-family: 'JetBrains Mono', monospace; + color: var(--primary-color); + font-size: 0.875rem; +} + +.param-description { + color: var(--text-secondary); + font-size: 0.875rem; + line-height: 1.5; +} + +/* Try It Section */ +.try-it-section { + margin-top: 2rem; + padding-top: 2rem; + border-top: 1px solid var(--border); +} + +.try-it-btn { + background: var(--success); + color: white; +} + +.try-it-btn:hover { + background: #059669; +} + +/* Webhook Events */ +.webhook-events { + margin: 2rem 0; +} + +.event-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 1rem; + margin: 1.5rem 0; +} + +.event-item { + background: white; + border: 1px solid var(--border); + border-radius: 0.5rem; + padding: 1rem; +} + +.event-name { + font-family: 'JetBrains Mono', monospace; + font-weight: 600; + color: var(--primary-color); + margin-bottom: 0.5rem; +} + +.event-description { + color: var(--text-secondary); + font-size: 0.875rem; +} + +/* SDKs */ +.sdk-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 2rem; + margin: 2rem 0; +} + +.sdk-card { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 2rem; + text-align: center; + transition: transform 0.3s ease; +} + +.sdk-card:hover { + transform: translateY(-5px); +} + +.sdk-icon { + font-size: 3rem; + margin-bottom: 1rem; +} + +.sdk-card h3 { + margin: 0 0 1rem 0; + color: var(--text-primary); +} + +.sdk-card p { + margin-bottom: 1.5rem; + color: var(--text-secondary); +} + +.sdk-install { + background: var(--code-bg); + color: var(--code-text); + padding: 1rem; + border-radius: 0.375rem; + margin-bottom: 1.5rem; + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; +} + +.sdk-links { + display: flex; + justify-content: center; + gap: 1rem; +} + +.sdk-link { + color: var(--primary-color); + text-decoration: none; + font-weight: 500; + font-size: 0.875rem; +} + +.sdk-link:hover { + text-decoration: underline; +} + +/* Changelog */ +.changelog { + margin: 2rem 0; +} + +.changelog-entry { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 2rem; + margin-bottom: 2rem; +} + +.changelog-date { + color: var(--text-secondary); + font-size: 0.875rem; + margin-bottom: 0.5rem; +} + +.changelog-version { + font-family: 'JetBrains Mono', monospace; + font-weight: 600; + color: var(--primary-color); + margin-bottom: 1rem; +} + +.changelog-content h4 { + margin: 1.5rem 0 1rem 0; + color: var(--text-primary); +} + +.changelog-content ul { + margin-bottom: 1.5rem; +} + +.changelog-content li { + color: var(--text-secondary); + margin-bottom: 0.5rem; +} + +/* Support Options */ +.support-options { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; + margin: 2rem 0; +} + +.support-option { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 2rem; + text-align: center; + transition: transform 0.3s ease; +} + +.support-option:hover { + transform: translateY(-5px); +} + +.support-icon { + font-size: 3rem; + margin-bottom: 1rem; +} + +.support-option h3 { + margin: 0 0 1rem 0; +} + +.support-option p { + margin-bottom: 1.5rem; + color: var(--text-secondary); +} + +.support-link { + color: var(--primary-color); + text-decoration: none; + font-weight: 600; +} + +.support-link:hover { + text-decoration: underline; +} + +/* API Tester */ +.api-tester { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 90%; + max-width: 800px; + max-height: 80vh; + background: white; + border-radius: 1rem; + box-shadow: var(--shadow-lg); + z-index: 2000; + display: none; + overflow: hidden; +} + +.api-tester.show { + display: block; +} + +.tester-header { + background: var(--surface); + padding: 1.5rem 2rem; + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid var(--border); +} + +.tester-header h3 { + margin: 0; + font-size: 1.25rem; +} + +.close-btn { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + color: var(--text-secondary); + padding: 0.5rem; + border-radius: 0.375rem; + transition: all 0.3s ease; +} + +.close-btn:hover { + background: var(--border); + color: var(--text-primary); +} + +.tester-content { + padding: 2rem; + max-height: calc(80vh - 100px); + overflow-y: auto; +} + +.tester-form { + margin-bottom: 2rem; +} + +.form-group { + margin-bottom: 1.5rem; +} + +.form-group label { + display: block; + font-weight: 600; + margin-bottom: 0.5rem; + color: var(--text-primary); +} + +.form-group input, +.form-group select, +.form-group textarea { + width: 100%; + padding: 0.75rem 1rem; + border: 1px solid var(--border); + border-radius: 0.5rem; + font-size: 1rem; + font-family: inherit; + transition: border-color 0.3s ease; +} + +.form-group input:focus, +.form-group select:focus, +.form-group textarea:focus { + outline: none; + border-color: var(--primary-color); +} + +.form-group textarea { + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; + resize: vertical; +} + +.tester-response h4 { + margin: 0 0 1rem 0; + color: var(--text-primary); +} + +.response-status { + padding: 0.5rem 1rem; + border-radius: 0.375rem; + font-family: 'JetBrains Mono', monospace; + font-weight: 600; + margin-bottom: 1rem; +} + +.response-status.success { + background: rgba(16, 185, 129, 0.1); + color: var(--success); +} + +.response-status.error { + background: rgba(239, 68, 68, 0.1); + color: var(--error); +} + +#responseBody { + background: var(--code-bg); + color: var(--code-text); + padding: 1.5rem; + border-radius: 0.5rem; + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; + line-height: 1.6; + overflow-x: auto; + white-space: pre-wrap; +} + +/* Toast */ +.toast { + position: fixed; + top: 2rem; + right: 2rem; + background: var(--success); + color: white; + padding: 1rem 1.5rem; + border-radius: 0.5rem; + box-shadow: var(--shadow-lg); + transform: translateX(100%); + transition: transform 0.3s ease; + z-index: 1000; +} + +.toast.show { + transform: translateX(0); +} + +.toast-content { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.toast-icon { + font-size: 1.25rem; +} + +/* Responsive Design */ +@media (max-width: 1024px) { + .docs-layout { + flex-direction: column; + } + + .sidebar { + width: 100%; + position: static; + height: auto; + border-right: none; + border-bottom: 1px solid var(--border); + } + + .main-content { + max-width: 100%; + padding: 2rem; + } + + .nav-menu { + display: none; + } +} + +@media (max-width: 768px) { + .content-header h1 { + font-size: 2rem; + } + + .auth-methods { + grid-template-columns: 1fr; + } + + .rate-limits { + grid-template-columns: 1fr; + } + + .parameter { + grid-template-columns: 1fr; + gap: 0.5rem; + } + + .endpoint-header { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .api-tester { + width: 95%; + max-height: 90vh; + } + + .tester-content { + padding: 1rem; + } +} + +@media (max-width: 480px) { + .main-content { + padding: 1rem; + } + + .sidebar { + padding: 1rem; + } + + .content-header { + margin-bottom: 2rem; + } + + .quick-actions { + flex-direction: column; + align-items: stretch; + } + + .toast { + top: 1rem; + right: 1rem; + left: 1rem; + } +} diff --git a/static/api-docs.html b/static/api-docs.html new file mode 100644 index 0000000..a133375 --- /dev/null +++ b/static/api-docs.html @@ -0,0 +1,937 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>API Documentation - TaskFlow</title> + <link rel="stylesheet" href="api-docs-styles.css"> + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet"> +</head> +<body> + <nav class="navbar"> + <div class="nav-container"> + <a href="landing.html" class="nav-logo">TaskFlow</a> + <ul class="nav-menu"> + <li><a href="landing.html#features" class="nav-link">Features</a></li> + <li><a href="landing.html#pricing" class="nav-link">Pricing</a></li> + <li><a href="about.html" class="nav-link">About</a></li> + <li><a href="blog.html" class="nav-link">Blog</a></li> + <li><a href="contact.html" class="nav-link">Contact</a></li> + </ul> + <div class="nav-actions"> + <a href="login.html" class="btn btn-ghost">Sign In</a> + <button class="btn btn-primary">Start Free Trial</button> + </div> + </div> + </nav> + + <div class="docs-layout"> + <aside class="sidebar" id="sidebar"> + <div class="sidebar-header"> + <h3>API Documentation</h3> + <div class="api-version">v2.1</div> + </div> + + <nav class="sidebar-nav"> + <div class="nav-section"> + <h4>Getting Started</h4> + <ul> + <li><a href="#introduction" class="nav-item">Introduction</a></li> + <li><a href="#authentication" class="nav-item">Authentication</a></li> + <li><a href="#rate-limiting" class="nav-item">Rate Limiting</a></li> + <li><a href="#errors" class="nav-item">Error Handling</a></li> + </ul> + </div> + + <div class="nav-section"> + <h4>Core Resources</h4> + <ul> + <li><a href="#projects" class="nav-item">Projects</a></li> + <li><a href="#tasks" class="nav-item">Tasks</a></li> + <li><a href="#users" class="nav-item">Users</a></li> + <li><a href="#teams" class="nav-item">Teams</a></li> + </ul> + </div> + + <div class="nav-section"> + <h4>Advanced</h4> + <ul> + <li><a href="#webhooks" class="nav-item">Webhooks</a></li> + <li><a href="#search" class="nav-item">Search</a></li> + <li><a href="#analytics" class="nav-item">Analytics</a></li> + <li><a href="#integrations" class="nav-item">Integrations</a></li> + </ul> + </div> + + <div class="nav-section"> + <h4>Resources</h4> + <ul> + <li><a href="#sdks" class="nav-item">SDKs</a></li> + <li><a href="#changelog" class="nav-item">Changelog</a></li> + <li><a href="#support" class="nav-item">Support</a></li> + </ul> + </div> + </nav> + </aside> + + <main class="main-content"> + <div class="content-header"> + <h1>TaskFlow API Documentation</h1> + <p>Build powerful integrations with TaskFlow's RESTful API. Access projects, tasks, users, and more programmatically.</p> + + <div class="quick-actions"> + <button class="btn btn-primary" id="getApiKeyBtn">Get API Key</button> + <button class="btn btn-secondary" id="tryApiBtn">Try API</button> + <div class="api-status"> + <div class="status-dot operational"></div> + <span>API Status: Operational</span> + </div> + </div> + </div> + + <section id="introduction" class="doc-section"> + <h2>Introduction</h2> + <p>The TaskFlow API is a RESTful API that allows you to integrate TaskFlow's project management capabilities into your applications. Our API follows standard HTTP conventions and returns JSON responses.</p> + + <div class="info-box"> + <div class="info-icon">ℹ️</div> + <div class="info-content"> + <h4>Base URL</h4> + <code>https://api.taskflow.com/v2</code> + </div> + </div> + + <h3>Key Features</h3> + <ul class="feature-list"> + <li>RESTful architecture with predictable URLs</li> + <li>JSON request and response bodies</li> + <li>Standard HTTP status codes</li> + <li>OAuth 2.0 and API key authentication</li> + <li>Rate limiting and pagination</li> + <li>Comprehensive error messages</li> + <li>Real-time webhooks</li> + <li>SDKs for popular languages</li> + </ul> + </section> + + <section id="authentication" class="doc-section"> + <h2>Authentication</h2> + <p>TaskFlow API supports two authentication methods: API Keys for server-to-server communication and OAuth 2.0 for user-facing applications.</p> + + <div class="auth-methods"> + <div class="auth-method"> + <h3>API Key Authentication</h3> + <p>Include your API key in the Authorization header:</p> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Request Headers</span> + <button class="copy-btn" data-copy="auth-header">Copy</button> + </div> + <pre><code id="auth-header">Authorization: Bearer your_api_key_here +Content-Type: application/json</code></pre> + </div> + </div> + + <div class="auth-method"> + <h3>OAuth 2.0</h3> + <p>For user-facing applications, use OAuth 2.0 with the authorization code flow:</p> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Authorization URL</span> + <button class="copy-btn" data-copy="oauth-url">Copy</button> + </div> + <pre><code id="oauth-url">https://api.taskflow.com/oauth/authorize? + client_id=your_client_id& + redirect_uri=your_redirect_uri& + response_type=code& + scope=read write</code></pre> + </div> + </div> + </div> + </section> + + <section id="rate-limiting" class="doc-section"> + <h2>Rate Limiting</h2> + <p>API requests are rate limited to ensure fair usage and system stability.</p> + + <div class="rate-limits"> + <div class="rate-limit-tier"> + <h4>Free Tier</h4> + <div class="limit-value">1,000 requests/hour</div> + <div class="limit-burst">Burst: 100 requests/minute</div> + </div> + <div class="rate-limit-tier"> + <h4>Pro Tier</h4> + <div class="limit-value">10,000 requests/hour</div> + <div class="limit-burst">Burst: 500 requests/minute</div> + </div> + <div class="rate-limit-tier"> + <h4>Enterprise</h4> + <div class="limit-value">100,000 requests/hour</div> + <div class="limit-burst">Burst: 2,000 requests/minute</div> + </div> + </div> + + <h3>Rate Limit Headers</h3> + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Response Headers</span> + </div> + <pre><code>X-RateLimit-Limit: 1000 +X-RateLimit-Remaining: 999 +X-RateLimit-Reset: 1640995200</code></pre> + </div> + </section> + + <section id="errors" class="doc-section"> + <h2>Error Handling</h2> + <p>TaskFlow API uses conventional HTTP response codes and returns detailed error information in JSON format.</p> + + <div class="error-codes"> + <div class="error-code"> + <div class="code-number">200</div> + <div class="code-description"> + <h4>OK</h4> + <p>Request succeeded</p> + </div> + </div> + <div class="error-code"> + <div class="code-number">400</div> + <div class="code-description"> + <h4>Bad Request</h4> + <p>Invalid request parameters</p> + </div> + </div> + <div class="error-code"> + <div class="code-number">401</div> + <div class="code-description"> + <h4>Unauthorized</h4> + <p>Invalid or missing authentication</p> + </div> + </div> + <div class="error-code"> + <div class="code-number">403</div> + <div class="code-description"> + <h4>Forbidden</h4> + <p>Insufficient permissions</p> + </div> + </div> + <div class="error-code"> + <div class="code-number">404</div> + <div class="code-description"> + <h4>Not Found</h4> + <p>Resource not found</p> + </div> + </div> + <div class="error-code"> + <div class="code-number">429</div> + <div class="code-description"> + <h4>Too Many Requests</h4> + <p>Rate limit exceeded</p> + </div> + </div> + </div> + + <h3>Error Response Format</h3> + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Error Response</span> + <button class="copy-btn" data-copy="error-response">Copy</button> + </div> + <pre><code id="error-response">{ + "error": { + "code": "validation_error", + "message": "The request contains invalid parameters", + "details": [ + { + "field": "name", + "message": "Name is required" + } + ], + "request_id": "req_1234567890" + } +}</code></pre> + </div> + </section> + + <section id="projects" class="doc-section"> + <h2>Projects</h2> + <p>Projects are the top-level containers for organizing tasks and team collaboration.</p> + + <div class="endpoint-group"> + <div class="endpoint"> + <div class="endpoint-header"> + <div class="method get">GET</div> + <div class="endpoint-path">/projects</div> + <div class="endpoint-title">List Projects</div> + </div> + + <div class="endpoint-content"> + <p>Retrieve a list of projects accessible to the authenticated user.</p> + + <h4>Query Parameters</h4> + <div class="parameters"> + <div class="parameter"> + <div class="param-name">limit</div> + <div class="param-type">integer</div> + <div class="param-description">Number of results to return (1-100, default: 20)</div> + </div> + <div class="parameter"> + <div class="param-name">offset</div> + <div class="param-type">integer</div> + <div class="param-description">Number of results to skip (default: 0)</div> + </div> + <div class="parameter"> + <div class="param-name">status</div> + <div class="param-type">string</div> + <div class="param-description">Filter by status: active, completed, archived</div> + </div> + </div> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Request</span> + <div class="code-tabs"> + <button class="tab-btn active" data-tab="curl">cURL</button> + <button class="tab-btn" data-tab="javascript">JavaScript</button> + <button class="tab-btn" data-tab="python">Python</button> + </div> + <button class="copy-btn" data-copy="projects-curl">Copy</button> + </div> + <div class="code-content"> + <pre class="tab-content active" id="curl"><code id="projects-curl">curl -X GET "https://api.taskflow.com/v2/projects?limit=10&status=active" \ + -H "Authorization: Bearer your_api_key_here" \ + -H "Content-Type: application/json"</code></pre> + <pre class="tab-content" id="javascript"><code>const response = await fetch('https://api.taskflow.com/v2/projects?limit=10&status=active', { + method: 'GET', + headers: { + 'Authorization': 'Bearer your_api_key_here', + 'Content-Type': 'application/json' + } +}); + +const projects = await response.json();</code></pre> + <pre class="tab-content" id="python"><code>import requests + +headers = { + 'Authorization': 'Bearer your_api_key_here', + 'Content-Type': 'application/json' +} + +response = requests.get( + 'https://api.taskflow.com/v2/projects', + headers=headers, + params={'limit': 10, 'status': 'active'} +) + +projects = response.json()</code></pre> + </div> + </div> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Response</span> + <button class="copy-btn" data-copy="projects-response">Copy</button> + </div> + <pre><code id="projects-response">{ + "data": [ + { + "id": "proj_1234567890", + "name": "Website Redesign", + "description": "Complete overhaul of company website", + "status": "active", + "created_at": "2025-01-15T10:30:00Z", + "updated_at": "2025-01-20T14:22:00Z", + "owner": { + "id": "user_0987654321", + "name": "John Doe", + "email": "john@company.com" + }, + "team_id": "team_1122334455", + "task_count": 24, + "completed_tasks": 12, + "progress": 50.0, + "due_date": "2025-03-01T00:00:00Z", + "tags": ["design", "frontend", "priority-high"] + } + ], + "pagination": { + "limit": 10, + "offset": 0, + "total": 1, + "has_more": false + } +}</code></pre> + </div> + + <div class="try-it-section"> + <button class="btn btn-primary try-it-btn" data-endpoint="projects">Try It</button> + </div> + </div> + </div> + + <div class="endpoint"> + <div class="endpoint-header"> + <div class="method post">POST</div> + <div class="endpoint-path">/projects</div> + <div class="endpoint-title">Create Project</div> + </div> + + <div class="endpoint-content"> + <p>Create a new project.</p> + + <h4>Request Body</h4> + <div class="parameters"> + <div class="parameter required"> + <div class="param-name">name</div> + <div class="param-type">string</div> + <div class="param-description">Project name (1-100 characters)</div> + </div> + <div class="parameter"> + <div class="param-name">description</div> + <div class="param-type">string</div> + <div class="param-description">Project description (max 1000 characters)</div> + </div> + <div class="parameter"> + <div class="param-name">team_id</div> + <div class="param-type">string</div> + <div class="param-description">ID of the team to assign the project to</div> + </div> + <div class="parameter"> + <div class="param-name">due_date</div> + <div class="param-type">string</div> + <div class="param-description">Due date in ISO 8601 format</div> + </div> + <div class="parameter"> + <div class="param-name">tags</div> + <div class="param-type">array</div> + <div class="param-description">Array of tag strings</div> + </div> + </div> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Request</span> + <button class="copy-btn" data-copy="create-project">Copy</button> + </div> + <pre><code id="create-project">curl -X POST "https://api.taskflow.com/v2/projects" \ + -H "Authorization: Bearer your_api_key_here" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Mobile App Development", + "description": "Build iOS and Android mobile applications", + "team_id": "team_1122334455", + "due_date": "2025-06-01T00:00:00Z", + "tags": ["mobile", "ios", "android"] + }'</code></pre> + </div> + </div> + </div> + </div> + </section> + + <section id="tasks" class="doc-section"> + <h2>Tasks</h2> + <p>Tasks represent individual work items within projects.</p> + + <div class="endpoint-group"> + <div class="endpoint"> + <div class="endpoint-header"> + <div class="method get">GET</div> + <div class="endpoint-path">/projects/{project_id}/tasks</div> + <div class="endpoint-title">List Tasks</div> + </div> + + <div class="endpoint-content"> + <p>Retrieve tasks for a specific project.</p> + + <h4>Path Parameters</h4> + <div class="parameters"> + <div class="parameter required"> + <div class="param-name">project_id</div> + <div class="param-type">string</div> + <div class="param-description">The ID of the project</div> + </div> + </div> + + <h4>Query Parameters</h4> + <div class="parameters"> + <div class="parameter"> + <div class="param-name">status</div> + <div class="param-type">string</div> + <div class="param-description">Filter by status: todo, in_progress, completed</div> + </div> + <div class="parameter"> + <div class="param-name">assignee_id</div> + <div class="param-type">string</div> + <div class="param-description">Filter by assigned user ID</div> + </div> + <div class="parameter"> + <div class="param-name">priority</div> + <div class="param-type">string</div> + <div class="param-description">Filter by priority: low, medium, high, urgent</div> + </div> + </div> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Response</span> + <button class="copy-btn" data-copy="tasks-response">Copy</button> + </div> + <pre><code id="tasks-response">{ + "data": [ + { + "id": "task_9876543210", + "title": "Design homepage mockup", + "description": "Create wireframes and visual mockups for the new homepage", + "status": "in_progress", + "priority": "high", + "created_at": "2025-01-16T09:15:00Z", + "updated_at": "2025-01-18T11:30:00Z", + "due_date": "2025-01-25T17:00:00Z", + "assignee": { + "id": "user_1357924680", + "name": "Jane Smith", + "email": "jane@company.com" + }, + "project_id": "proj_1234567890", + "tags": ["design", "homepage"], + "time_estimate": 480, + "time_spent": 240, + "subtasks": [ + { + "id": "subtask_1111111111", + "title": "Create wireframes", + "completed": true + }, + { + "id": "subtask_2222222222", + "title": "Design visual mockups", + "completed": false + } + ] + } + ], + "pagination": { + "limit": 20, + "offset": 0, + "total": 1, + "has_more": false + } +}</code></pre> + </div> + </div> + </div> + </div> + </section> + + <section id="users" class="doc-section"> + <h2>Users</h2> + <p>Manage user accounts and profiles.</p> + + <div class="endpoint-group"> + <div class="endpoint"> + <div class="endpoint-header"> + <div class="method get">GET</div> + <div class="endpoint-path">/users/me</div> + <div class="endpoint-title">Get Current User</div> + </div> + + <div class="endpoint-content"> + <p>Retrieve information about the authenticated user.</p> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Response</span> + <button class="copy-btn" data-copy="user-response">Copy</button> + </div> + <pre><code id="user-response">{ + "id": "user_0987654321", + "name": "John Doe", + "email": "john@company.com", + "avatar_url": "https://cdn.taskflow.com/avatars/user_0987654321.jpg", + "role": "admin", + "created_at": "2024-12-01T10:00:00Z", + "last_active": "2025-01-20T15:30:00Z", + "timezone": "America/New_York", + "preferences": { + "notifications": { + "email": true, + "push": true, + "desktop": false + }, + "theme": "light" + }, + "subscription": { + "plan": "pro", + "status": "active", + "expires_at": "2025-12-01T00:00:00Z" + } +}</code></pre> + </div> + </div> + </div> + </div> + </section> + + <section id="teams" class="doc-section"> + <h2>Teams</h2> + <p>Manage teams and team memberships.</p> + + <div class="endpoint-group"> + <div class="endpoint"> + <div class="endpoint-header"> + <div class="method get">GET</div> + <div class="endpoint-path">/teams</div> + <div class="endpoint-title">List Teams</div> + </div> + + <div class="endpoint-content"> + <p>Retrieve teams that the authenticated user belongs to.</p> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Response</span> + <button class="copy-btn" data-copy="teams-response">Copy</button> + </div> + <pre><code id="teams-response">{ + "data": [ + { + "id": "team_1122334455", + "name": "Design Team", + "description": "UI/UX designers and visual artists", + "created_at": "2024-11-15T08:00:00Z", + "member_count": 8, + "project_count": 12, + "owner": { + "id": "user_0987654321", + "name": "John Doe", + "email": "john@company.com" + }, + "members": [ + { + "id": "user_1357924680", + "name": "Jane Smith", + "email": "jane@company.com", + "role": "member", + "joined_at": "2024-11-20T10:30:00Z" + } + ] + } + ], + "pagination": { + "limit": 20, + "offset": 0, + "total": 1, + "has_more": false + } +}</code></pre> + </div> + </div> + </div> + </div> + </section> + + <section id="webhooks" class="doc-section"> + <h2>Webhooks</h2> + <p>Set up real-time notifications for events in your TaskFlow account.</p> + + <div class="webhook-events"> + <h3>Supported Events</h3> + <div class="event-grid"> + <div class="event-item"> + <div class="event-name">project.created</div> + <div class="event-description">New project created</div> + </div> + <div class="event-item"> + <div class="event-name">project.updated</div> + <div class="event-description">Project details changed</div> + </div> + <div class="event-item"> + <div class="event-name">task.created</div> + <div class="event-description">New task created</div> + </div> + <div class="event-item"> + <div class="event-name">task.completed</div> + <div class="event-description">Task marked as completed</div> + </div> + <div class="event-item"> + <div class="event-name">user.invited</div> + <div class="event-description">User invited to team</div> + </div> + <div class="event-item"> + <div class="event-name">comment.added</div> + <div class="event-description">Comment added to task</div> + </div> + </div> + </div> + + <div class="endpoint-group"> + <div class="endpoint"> + <div class="endpoint-header"> + <div class="method post">POST</div> + <div class="endpoint-path">/webhooks</div> + <div class="endpoint-title">Create Webhook</div> + </div> + + <div class="endpoint-content"> + <p>Create a new webhook endpoint.</p> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Request</span> + <button class="copy-btn" data-copy="webhook-create">Copy</button> + </div> + <pre><code id="webhook-create">curl -X POST "https://api.taskflow.com/v2/webhooks" \ + -H "Authorization: Bearer your_api_key_here" \ + -H "Content-Type: application/json" \ + -d '{ + "url": "https://your-app.com/webhooks/taskflow", + "events": ["task.created", "task.completed"], + "secret": "your_webhook_secret" + }'</code></pre> + </div> + </div> + </div> + </div> + </section> + + <section id="search" class="doc-section"> + <h2>Search</h2> + <p>Search across projects, tasks, and other resources.</p> + + <div class="endpoint-group"> + <div class="endpoint"> + <div class="endpoint-header"> + <div class="method get">GET</div> + <div class="endpoint-path">/search</div> + <div class="endpoint-title">Search Resources</div> + </div> + + <div class="endpoint-content"> + <p>Perform a full-text search across your TaskFlow data.</p> + + <h4>Query Parameters</h4> + <div class="parameters"> + <div class="parameter required"> + <div class="param-name">q</div> + <div class="param-type">string</div> + <div class="param-description">Search query</div> + </div> + <div class="parameter"> + <div class="param-name">type</div> + <div class="param-type">string</div> + <div class="param-description">Resource type: projects, tasks, users, teams</div> + </div> + <div class="parameter"> + <div class="param-name">limit</div> + <div class="param-type">integer</div> + <div class="param-description">Number of results (1-50, default: 10)</div> + </div> + </div> + + <div class="code-example"> + <div class="code-header"> + <span class="code-title">Example Request</span> + <button class="copy-btn" data-copy="search-request">Copy</button> + </div> + <pre><code id="search-request">curl -X GET "https://api.taskflow.com/v2/search?q=design&type=tasks&limit=5" \ + -H "Authorization: Bearer your_api_key_here"</code></pre> + </div> + </div> + </div> + </div> + </section> + + <section id="sdks" class="doc-section"> + <h2>SDKs</h2> + <p>Official SDKs and libraries for popular programming languages.</p> + + <div class="sdk-grid"> + <div class="sdk-card"> + <div class="sdk-icon">🟨</div> + <h3>JavaScript/Node.js</h3> + <p>Official JavaScript SDK for browser and Node.js applications.</p> + <div class="sdk-install"> + <code>npm install @taskflow/sdk</code> + </div> + <div class="sdk-links"> + <a href="#" class="sdk-link">Documentation</a> + <a href="#" class="sdk-link">GitHub</a> + </div> + </div> + + <div class="sdk-card"> + <div class="sdk-icon">🐍</div> + <h3>Python</h3> + <p>Official Python SDK with async support.</p> + <div class="sdk-install"> + <code>pip install taskflow-sdk</code> + </div> + <div class="sdk-links"> + <a href="#" class="sdk-link">Documentation</a> + <a href="#" class="sdk-link">PyPI</a> + </div> + </div> + + <div class="sdk-card"> + <div class="sdk-icon">☕</div> + <h3>Java</h3> + <p>Official Java SDK for enterprise applications.</p> + <div class="sdk-install"> + <code>implementation 'com.taskflow:sdk:2.1.0'</code> + </div> + <div class="sdk-links"> + <a href="#" class="sdk-link">Documentation</a> + <a href="#" class="sdk-link">Maven Central</a> + </div> + </div> + + <div class="sdk-card"> + <div class="sdk-icon">🔷</div> + <h3>Go</h3> + <p>Official Go SDK with full API coverage.</p> + <div class="sdk-install"> + <code>go get github.com/taskflow/go-sdk</code> + </div> + <div class="sdk-links"> + <a href="#" class="sdk-link">Documentation</a> + <a href="#" class="sdk-link">GitHub</a> + </div> + </div> + </div> + </section> + + <section id="changelog" class="doc-section"> + <h2>Changelog</h2> + <p>Recent updates and changes to the TaskFlow API.</p> + + <div class="changelog"> + <div class="changelog-entry"> + <div class="changelog-date">2025-01-15</div> + <div class="changelog-version">v2.1.0</div> + <div class="changelog-content"> + <h4>New Features</h4> + <ul> + <li>Added search endpoint with full-text search capabilities</li> + <li>Introduced webhook support for real-time notifications</li> + <li>Added subtasks support in task objects</li> + </ul> + <h4>Improvements</h4> + <ul> + <li>Increased rate limits for Pro and Enterprise tiers</li> + <li>Enhanced error messages with more detailed information</li> + <li>Added time tracking fields to tasks</li> + </ul> + </div> + </div> + + <div class="changelog-entry"> + <div class="changelog-date">2024-12-20</div> + <div class="changelog-version">v2.0.0</div> + <div class="changelog-content"> + <h4>Breaking Changes</h4> + <ul> + <li>Updated authentication to use Bearer tokens</li> + <li>Changed date format to ISO 8601</li> + <li>Renamed several field names for consistency</li> + </ul> + <h4>New Features</h4> + <ul> + <li>Added teams endpoint</li> + <li>Introduced pagination for all list endpoints</li> + <li>Added OAuth 2.0 support</li> + </ul> + </div> + </div> + </div> + </section> + + <section id="support" class="doc-section"> + <h2>Support</h2> + <p>Get help with the TaskFlow API.</p> + + <div class="support-options"> + <div class="support-option"> + <div class="support-icon">📚</div> + <h3>Documentation</h3> + <p>Comprehensive guides and tutorials</p> + <a href="#" class="support-link">View Docs</a> + </div> + + <div class="support-option"> + <div class="support-icon">💬</div> + <h3>Community Forum</h3> + <p>Ask questions and share knowledge</p> + <a href="#" class="support-link">Join Forum</a> + </div> + + <div class="support-option"> + <div class="support-icon">🎫</div> + <h3>Support Tickets</h3> + <p>Get direct help from our team</p> + <a href="contact.html" class="support-link">Contact Support</a> + </div> + + <div class="support-option"> + <div class="support-icon">📊</div> + <h3>API Status</h3> + <p>Check current API status and uptime</p> + <a href="status.html" class="support-link">View Status</a> + </div> + </div> + </section> + </main> + </div> + + <div class="api-tester" id="apiTester"> + <div class="tester-header"> + <h3>API Tester</h3> + <button class="close-btn" id="closeTester">×</button> + </div> + <div class="tester-content"> + <div class="tester-form"> + <div class="form-group"> + <label>Method</label> + <select id="testMethod"> + <option value="GET">GET</option> + <option value="POST">POST</option> + <option value="PUT">PUT</option> + <option value="DELETE">DELETE</option> + </select> + </div> + <div class="form-group"> + <label>Endpoint</label> + <input type="text" id="testEndpoint" placeholder="/projects"> + </div> + <div class="form-group"> + <label>Headers</label> + <textarea id="testHeaders" rows="3">Authorization: Bearer your_api_key_here +Content-Type: application/json</textarea> + </div> + <div class="form-group"> + <label>Request Body</label> + <textarea id="testBody" rows="5" placeholder='{"name": "Test Project"}'></textarea> + </div> + <button class="btn btn-primary" id="sendRequest">Send Request</button> + </div> + <div class="tester-response"> + <h4>Response</h4> + <div class="response-status" id="responseStatus"></div> + <pre id="responseBody"></pre> + </div> + </div> + </div> + + <div class="toast" id="toast"> + <div class="toast-content"> + <span class="toast-icon">✓</span> + <span class="toast-message"></span> + </div> + </div> + + <script src="api-docs-script.js"></script> +</body> +</html> |