diff options
author | Robby Zambito <contact@robbyzambito.me> | 2025-08-07 00:37:09 -0400 |
---|---|---|
committer | Robby Zambito <contact@robbyzambito.me> | 2025-08-07 00:37:09 -0400 |
commit | 431037f4f6a8d31c523287e1bdbd88b6718de859 (patch) | |
tree | 80faff9fec2342051f78b15ffe1c2a87198b1a95 | |
parent | 6f1fb66792bd35166de5a338e5d174b22fa2c2ce (diff) |
Added API Docs
Prompt:
Generate a simple API docs page for the current public API. Include the endpoints that are used in the previously defined pages.
-rw-r--r-- | static/api-docs-script.js | 315 | ||||
-rw-r--r-- | static/api-docs-styles.css | 877 | ||||
-rw-r--r-- | static/api-docs.html | 956 |
3 files changed, 2148 insertions, 0 deletions
diff --git a/static/api-docs-script.js b/static/api-docs-script.js new file mode 100644 index 0000000..2f179b9 --- /dev/null +++ b/static/api-docs-script.js @@ -0,0 +1,315 @@ +// 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'); + } + }); +}); + +// Copy to clipboard functionality +document.querySelectorAll('.copy-btn').forEach(button => { + button.addEventListener('click', async () => { + const textToCopy = button.getAttribute('data-copy'); + + try { + await navigator.clipboard.writeText(textToCopy); + + // Update button state + const originalText = button.textContent; + button.textContent = 'Copied!'; + button.classList.add('copied'); + + setTimeout(() => { + button.textContent = originalText; + button.classList.remove('copied'); + }, 2000); + + showToast('Copied to clipboard!', 'success'); + } catch (err) { + console.error('Failed to copy text: ', err); + showToast('Failed to copy to clipboard', 'error'); + } + }); +}); + +// Toast notification +const showToast = (message, type = 'success') => { + const toast = document.getElementById('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'); + }, 3000); +}; + +// Intersection Observer for active navigation +const observerOptions = { + threshold: 0.1, + rootMargin: '-100px 0px -50% 0px' +}; + +const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const id = entry.target.id; + const navLink = document.querySelector(`.nav-item[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[id]').forEach(section => { + observer.observe(section); +}); + +// Navbar background on scroll +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 +document.querySelectorAll('.btn').forEach(btn => { + btn.addEventListener('click', (e) => { + const buttonText = btn.textContent.toLowerCase(); + + if (buttonText.includes('trial') || buttonText.includes('start')) { + if (!btn.closest('form')) { + e.preventDefault(); + showToast('Starting your free trial! Redirecting...', 'success'); + setTimeout(() => { + window.location.href = 'signup.html'; + }, 2000); + } + } else if (buttonText.includes('documentation') || buttonText.includes('github') || buttonText.includes('pypi')) { + e.preventDefault(); + showToast('Opening external documentation...', 'success'); + } else if (buttonText.includes('import collection')) { + e.preventDefault(); + showToast('Postman collection downloaded!', 'success'); + } + }); +}); + +// Syntax highlighting for code blocks (basic) +const highlightCode = () => { + document.querySelectorAll('pre code').forEach(block => { + let html = block.innerHTML; + + // Highlight JSON keys + html = html.replace(/"([^"]+)":/g, '<span style="color: #10b981;">"$1"</span>:'); + + // Highlight strings + html = html.replace(/: "([^"]+)"/g, ': <span style="color: #f59e0b;">"$1"</span>'); + + // Highlight numbers + html = html.replace(/: (\d+\.?\d*)/g, ': <span style="color: #3b82f6;">$1</span>'); + + // Highlight booleans + html = html.replace(/: (true|false)/g, ': <span style="color: #8b5cf6;">$1</span>'); + + // Highlight null + html = html.replace(/: (null)/g, ': <span style="color: #64748b;">$1</span>'); + + block.innerHTML = html; + }); +}; + +// Apply syntax highlighting on load +document.addEventListener('DOMContentLoaded', highlightCode); + +// Search functionality (basic) +const addSearchFunctionality = () => { + // Create search input + const searchContainer = document.createElement('div'); + searchContainer.style.cssText = ` + position: sticky; + top: 0; + background: var(--surface); + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--border); + margin-bottom: 1rem; + `; + + const searchInput = document.createElement('input'); + searchInput.type = 'text'; + searchInput.placeholder = 'Search documentation...'; + searchInput.style.cssText = ` + width: 100%; + padding: 0.75rem 1rem; + border: 1px solid var(--border); + border-radius: 0.5rem; + font-size: 0.875rem; + background: white; + `; + + searchContainer.appendChild(searchInput); + + // Insert search at the top of sidebar + const sidebarContent = document.querySelector('.sidebar-content'); + sidebarContent.insertBefore(searchContainer, sidebarContent.firstChild); + + // Search functionality + searchInput.addEventListener('input', (e) => { + const query = e.target.value.toLowerCase(); + const navItems = document.querySelectorAll('.nav-item'); + + navItems.forEach(item => { + const text = item.textContent.toLowerCase(); + const section = item.closest('.nav-section'); + + if (text.includes(query)) { + item.style.display = 'block'; + section.style.display = 'block'; + } else { + item.style.display = 'none'; + } + }); + + // Hide sections with no visible items + document.querySelectorAll('.nav-section').forEach(section => { + const visibleItems = section.querySelectorAll('.nav-item[style*="block"]'); + if (visibleItems.length === 0 && query !== '') { + section.style.display = 'none'; + } else { + section.style.display = 'block'; + } + }); + }); +}; + +// Add search functionality on load +document.addEventListener('DOMContentLoaded', addSearchFunctionality); + +// Keyboard shortcuts +document.addEventListener('keydown', (e) => { + // Ctrl/Cmd + K to focus search + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { + e.preventDefault(); + const searchInput = document.querySelector('input[placeholder*="Search"]'); + if (searchInput) { + searchInput.focus(); + } + } + + // Escape to clear search + if (e.key === 'Escape') { + const searchInput = document.querySelector('input[placeholder*="Search"]'); + if (searchInput && document.activeElement === searchInput) { + searchInput.value = ''; + searchInput.dispatchEvent(new Event('input')); + searchInput.blur(); + } + } +}); + +// Print styles +const addPrintStyles = () => { + const printStyles = document.createElement('style'); + printStyles.textContent = ` + @media print { + .navbar, + .sidebar, + .copy-btn, + .toast { + display: none !important; + } + + .docs-layout { + flex-direction: column; + } + + .main-content { + width: 100% !important; + } + + .content-container { + max-width: none !important; + padding: 0 !important; + } + + .code-block { + background: #f8f9fa !important; + color: #333 !important; + border: 1px solid #ddd !important; + } + + .endpoint { + break-inside: avoid; + } + } + `; + document.head.appendChild(printStyles); +}; + +addPrintStyles(); + +// Initialize everything when DOM is ready +document.addEventListener('DOMContentLoaded', () => { + // Set initial active nav item + const hash = window.location.hash; + if (hash) { + const navLink = document.querySelector(`.nav-item[href="${hash}"]`); + if (navLink) { + navLink.classList.add('active'); + } + } else { + // Default to first nav item + const firstNavItem = document.querySelector('.nav-item'); + if (firstNavItem) { + firstNavItem.classList.add('active'); + } + } +}); + +// Handle hash changes +window.addEventListener('hashchange', () => { + const hash = window.location.hash; + if (hash) { + const navLink = document.querySelector(`.nav-item[href="${hash}"]`); + if (navLink) { + document.querySelectorAll('.nav-item').forEach(item => { + item.classList.remove('active'); + }); + navLink.classList.add('active'); + } + } +}); diff --git a/static/api-docs-styles.css b/static/api-docs-styles.css new file mode 100644 index 0000000..378f28a --- /dev/null +++ b/static/api-docs-styles.css @@ -0,0 +1,877 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + --primary-color: #6366f1; + --primary-dark: #4f46e5; + --secondary-color: #f1f5f9; + --text-primary: #1e293b; + --text-secondary: #64748b; + --text-muted: #94a3b8; + --background: #ffffff; + --surface: #f8fafc; + --border: #e2e8f0; + --border-light: #f1f5f9; + --success: #10b981; + --warning: #f59e0b; + --error: #ef4444; + --info: #3b82f6; + --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%); + --code-bg: #1e293b; + --code-text: #e2e8f0; +} + +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-secondary); + border: none; +} + +.btn-ghost:hover { + background: var(--surface); + color: var(--text-primary); +} + +/* Layout */ +.docs-layout { + display: flex; + margin-top: 80px; + min-height: calc(100vh - 80px); +} + +.sidebar { + width: 280px; + background: var(--surface); + border-right: 1px solid var(--border); + position: sticky; + top: 80px; + height: calc(100vh - 80px); + overflow-y: auto; +} + +.sidebar-content { + padding: 2rem 1.5rem; +} + +.sidebar-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; + padding-bottom: 1rem; + border-bottom: 1px solid var(--border); +} + +.sidebar-header h3 { + font-size: 1.25rem; + font-weight: 600; +} + +.api-version { + background: var(--primary-color); + color: white; + padding: 0.25rem 0.75rem; + border-radius: 1rem; + font-size: 0.75rem; + font-weight: 600; +} + +.sidebar-nav { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.nav-section h4 { + font-size: 0.875rem; + font-weight: 600; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.75rem; +} + +.nav-section ul { + list-style: none; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.nav-item { + display: block; + padding: 0.5rem 0.75rem; + color: var(--text-secondary); + text-decoration: none; + border-radius: 0.375rem; + font-size: 0.875rem; + transition: all 0.3s ease; +} + +.nav-item:hover, +.nav-item.active { + background: var(--primary-color); + color: white; +} + +.main-content { + flex: 1; + overflow-x: hidden; +} + +.content-container { + max-width: 800px; + padding: 2rem; +} + +/* Documentation Sections */ +.doc-section { + margin-bottom: 4rem; + scroll-margin-top: 100px; +} + +.doc-section h1 { + font-size: 3rem; + font-weight: 700; + margin-bottom: 1rem; + background: var(--gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.doc-section h2 { + font-size: 2rem; + font-weight: 700; + margin-bottom: 1.5rem; + color: var(--text-primary); +} + +.doc-section h3 { + font-size: 1.5rem; + font-weight: 600; + margin-bottom: 1rem; + margin-top: 2rem; +} + +.doc-section h4 { + font-size: 1.125rem; + font-weight: 600; + margin-bottom: 0.75rem; + margin-top: 1.5rem; +} + +.lead { + font-size: 1.25rem; + color: var(--text-secondary); + margin-bottom: 2rem; + line-height: 1.7; +} + +.doc-section p { + margin-bottom: 1rem; + color: var(--text-secondary); + line-height: 1.7; +} + +.doc-section code { + background: var(--surface); + padding: 0.125rem 0.375rem; + border-radius: 0.25rem; + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; + color: var(--primary-color); +} + +/* Info Cards */ +.info-card { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + margin: 2rem 0; + overflow: hidden; +} + +.info-header { + background: var(--surface); + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--border); +} + +.info-header h3 { + font-size: 1rem; + font-weight: 600; + margin: 0; +} + +/* Features Grid */ +.features-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1.5rem; + margin: 2rem 0; +} + +.feature-card { + background: white; + padding: 1.5rem; + border-radius: 0.75rem; + border: 1px solid var(--border); + text-align: center; +} + +.feature-icon { + font-size: 2rem; + margin-bottom: 1rem; +} + +.feature-card h4 { + font-size: 1.125rem; + font-weight: 600; + margin-bottom: 0.5rem; + margin-top: 0; +} + +.feature-card p { + color: var(--text-secondary); + font-size: 0.875rem; + margin: 0; +} + +/* Code Examples */ +.code-example { + margin: 1.5rem 0; + border-radius: 0.75rem; + overflow: hidden; + border: 1px solid var(--border); +} + +.code-header { + background: var(--surface); + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--border); + font-size: 0.875rem; + font-weight: 500; + color: var(--text-secondary); +} + +.code-block { + position: relative; + background: var(--code-bg); + color: var(--code-text); + padding: 1.5rem; + overflow-x: auto; +} + +.code-block pre { + margin: 0; + font-family: 'JetBrains Mono', monospace; + font-size: 0.875rem; + line-height: 1.5; +} + +.code-block code { + background: none; + color: inherit; + padding: 0; + border-radius: 0; +} + +.copy-btn { + position: absolute; + top: 1rem; + right: 1rem; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.2); + color: white; + padding: 0.5rem 0.75rem; + border-radius: 0.375rem; + font-size: 0.75rem; + cursor: pointer; + transition: all 0.3s ease; +} + +.copy-btn:hover { + background: rgba(255, 255, 255, 0.2); +} + +.copy-btn.copied { + background: var(--success); + border-color: var(--success); +} + +/* Alerts */ +.alert { + display: flex; + align-items: flex-start; + gap: 1rem; + padding: 1rem 1.5rem; + border-radius: 0.75rem; + margin: 1.5rem 0; +} + +.alert-info { + background: rgba(59, 130, 246, 0.1); + border: 1px solid rgba(59, 130, 246, 0.2); +} + +.alert-icon { + font-size: 1.25rem; + margin-top: 0.125rem; +} + +.alert-content { + flex: 1; + color: var(--text-primary); + line-height: 1.6; +} + +.alert-content strong { + font-weight: 600; +} + +.alert-link { + color: var(--primary-color); + text-decoration: none; +} + +.alert-link:hover { + text-decoration: underline; +} + +/* Tables */ +.table-container { + margin: 1.5rem 0; + overflow-x: auto; + border-radius: 0.75rem; + border: 1px solid var(--border); +} + +.api-table { + width: 100%; + border-collapse: collapse; + background: white; +} + +.api-table th { + background: var(--surface); + padding: 1rem; + text-align: left; + font-weight: 600; + font-size: 0.875rem; + color: var(--text-primary); + border-bottom: 1px solid var(--border); +} + +.api-table td { + padding: 1rem; + border-bottom: 1px solid var(--border-light); + font-size: 0.875rem; + color: var(--text-secondary); +} + +.api-table tr:last-child td { + border-bottom: none; +} + +.api-table code { + background: var(--surface); + padding: 0.125rem 0.375rem; + border-radius: 0.25rem; + font-family: 'JetBrains Mono', monospace; + font-size: 0.75rem; + color: var(--primary-color); +} + +/* Status Codes and Badges */ +.status-code { + padding: 0.25rem 0.75rem; + border-radius: 0.375rem; + font-size: 0.75rem; + font-weight: 600; + font-family: 'JetBrains Mono', monospace; +} + +.status-code.success { + background: rgba(16, 185, 129, 0.1); + color: var(--success); +} + +.status-code.client-error { + background: rgba(245, 158, 11, 0.1); + color: var(--warning); +} + +.status-code.server-error { + background: rgba(239, 68, 68, 0.1); + color: var(--error); +} + +.plan-badge { + padding: 0.25rem 0.75rem; + border-radius: 1rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; +} + +.plan-badge.free { + background: rgba(100, 116, 139, 0.1); + color: var(--text-secondary); +} + +.plan-badge.pro { + background: rgba(99, 102, 241, 0.1); + color: var(--primary-color); +} + +.plan-badge.enterprise { + background: rgba(16, 185, 129, 0.1); + color: var(--success); +} + +.required { + color: var(--error); + font-weight: 600; + font-size: 0.75rem; +} + +.optional { + color: var(--text-muted); + font-weight: 500; + font-size: 0.75rem; +} + +/* Endpoints */ +.endpoint { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + margin: 2rem 0; + overflow: hidden; +} + +.endpoint-header { + background: var(--surface); + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--border); + display: flex; + align-items: center; + gap: 1rem; +} + +.method { + padding: 0.375rem 0.75rem; + border-radius: 0.375rem; + font-size: 0.75rem; + font-weight: 700; + font-family: 'JetBrains Mono', monospace; + text-transform: uppercase; +} + +.method.get { + background: rgba(16, 185, 129, 0.1); + color: var(--success); +} + +.method.post { + background: rgba(59, 130, 246, 0.1); + color: var(--info); +} + +.method.put { + background: rgba(245, 158, 11, 0.1); + color: var(--warning); +} + +.method.delete { + background: rgba(239, 68, 68, 0.1); + color: var(--error); +} + +.path { + font-family: 'JetBrains Mono', monospace; + font-size: 1rem; + font-weight: 600; + color: var(--text-primary); +} + +.endpoint > p { + padding: 1.5rem; + margin: 0; + color: var(--text-secondary); +} + +.endpoint h4 { + padding: 0 1.5rem; + margin-top: 1.5rem; + margin-bottom: 0.75rem; +} + +.endpoint .code-example { + margin: 1rem 1.5rem; +} + +.endpoint .table-container { + margin: 1rem 1.5rem; +} + +/* SDK Grid */ +.sdk-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 1.5rem; + margin: 2rem 0; +} + +.sdk-card { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 1.5rem; +} + +.sdk-header { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 1rem; +} + +.sdk-icon { + font-size: 2rem; +} + +.sdk-header h4 { + margin: 0; + font-size: 1.125rem; + font-weight: 600; +} + +.sdk-card p { + color: var(--text-secondary); + margin-bottom: 1.5rem; +} + +.sdk-actions { + display: flex; + gap: 0.75rem; +} + +/* Postman Card */ +.postman-card { + background: white; + border: 1px solid var(--border); + border-radius: 0.75rem; + padding: 1.5rem; + display: flex; + justify-content: space-between; + align-items: center; + margin: 1.5rem 0; +} + +.postman-content { + display: flex; + align-items: center; + gap: 1rem; +} + +.postman-icon { + font-size: 2rem; +} + +.postman-content h4 { + margin: 0 0 0.25rem 0; + font-size: 1.125rem; + font-weight: 600; +} + +.postman-content p { + margin: 0; + color: var(--text-secondary); + font-size: 0.875rem; +} + +/* Changelog */ +.changelog { + display: flex; + flex-direction: column; + gap: 2rem; +} + +.changelog-item { + display: flex; + gap: 2rem; + padding-bottom: 2rem; + border-bottom: 1px solid var(--border); +} + +.changelog-item:last-child { + border-bottom: none; + padding-bottom: 0; +} + +.changelog-date { + min-width: 150px; +} + +.changelog-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; + margin-bottom: 0.5rem; +} + +.changelog-timestamp { + font-size: 0.875rem; + color: var(--text-secondary); +} + +.changelog-content h4 { + margin-top: 0; + margin-bottom: 0.75rem; + font-size: 1.125rem; + font-weight: 600; +} + +.changelog-content ul { + margin: 0; + padding-left: 1.5rem; +} + +.changelog-content li { + color: var(--text-secondary); + margin-bottom: 0.25rem; +} + +/* 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%; + height: auto; + position: static; + border-right: none; + border-bottom: 1px solid var(--border); + } + + .sidebar-content { + padding: 1.5rem; + } + + .sidebar-nav { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + } + + .nav-section { + background: white; + padding: 1rem; + border-radius: 0.5rem; + border: 1px solid var(--border); + } +} + +@media (max-width: 768px) { + .nav-menu { + display: none; + } + + .content-container { + padding: 1rem; + } + + .doc-section h1 { + font-size: 2rem; + } + + .doc-section h2 { + font-size: 1.5rem; + } + + .features-grid { + grid-template-columns: 1fr; + } + + .sdk-grid { + grid-template-columns: 1fr; + } + + .postman-card { + flex-direction: column; + gap: 1rem; + text-align: center; + } + + .changelog-item { + flex-direction: column; + gap: 1rem; + } + + .endpoint-header { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .toast { + top: 1rem; + right: 1rem; + left: 1rem; + } +} + +@media (max-width: 480px) { + .sidebar-nav { + grid-template-columns: 1fr; + } + + .api-table { + font-size: 0.75rem; + } + + .api-table th, + .api-table td { + padding: 0.75rem 0.5rem; + } +} diff --git a/static/api-docs.html b/static/api-docs.html new file mode 100644 index 0000000..07e02ac --- /dev/null +++ b/static/api-docs.html @@ -0,0 +1,956 @@ +<!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"> + <div class="sidebar-content"> + <div class="sidebar-header"> + <h3>API Documentation</h3> + <div class="api-version">v1.0</div> + </div> + + <nav class="sidebar-nav"> + <div class="nav-section"> + <h4>Getting Started</h4> + <ul> + <li><a href="#overview" class="nav-item">Overview</a></li> + <li><a href="#authentication" class="nav-item">Authentication</a></li> + <li><a href="#rate-limits" class="nav-item">Rate Limits</a></li> + <li><a href="#errors" class="nav-item">Error Handling</a></li> + </ul> + </div> + + <div class="nav-section"> + <h4>Authentication</h4> + <ul> + <li><a href="#auth-login" class="nav-item">Login</a></li> + <li><a href="#auth-refresh" class="nav-item">Refresh Token</a></li> + <li><a href="#auth-logout" class="nav-item">Logout</a></li> + </ul> + </div> + + <div class="nav-section"> + <h4>Contact</h4> + <ul> + <li><a href="#contact-submit" class="nav-item">Submit Contact Form</a></li> + </ul> + </div> + + <div class="nav-section"> + <h4>Status</h4> + <ul> + <li><a href="#status-overall" class="nav-item">Overall Status</a></li> + <li><a href="#status-services" class="nav-item">Services Status</a></li> + <li><a href="#status-metrics" class="nav-item">Metrics</a></li> + <li><a href="#status-incidents" class="nav-item">Incidents</a></li> + <li><a href="#status-maintenance" class="nav-item">Maintenance</a></li> + <li><a href="#status-uptime" class="nav-item">Uptime History</a></li> + <li><a href="#status-subscribe" class="nav-item">Subscribe</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="#postman" class="nav-item">Postman Collection</a></li> + <li><a href="#changelog" class="nav-item">Changelog</a></li> + </ul> + </div> + </nav> + </div> + </aside> + + <main class="main-content"> + <div class="content-container"> + <section id="overview" class="doc-section"> + <h1>TaskFlow API Documentation</h1> + <p class="lead"> + Welcome to the TaskFlow API documentation. Our REST API allows you to integrate TaskFlow's + project management capabilities into your applications. + </p> + + <div class="info-card"> + <div class="info-header"> + <h3>Base URL</h3> + </div> + <div class="code-block"> + <code>https://api.taskflow.com/v1</code> + <button class="copy-btn" data-copy="https://api.taskflow.com/v1">Copy</button> + </div> + </div> + + <div class="features-grid"> + <div class="feature-card"> + <div class="feature-icon">đ</div> + <h4>Secure</h4> + <p>OAuth 2.0 and API key authentication with HTTPS encryption</p> + </div> + <div class="feature-card"> + <div class="feature-icon">âĄ</div> + <h4>Fast</h4> + <p>Global CDN with average response times under 200ms</p> + </div> + <div class="feature-card"> + <div class="feature-icon">đ</div> + <h4>Reliable</h4> + <p>99.9% uptime SLA with comprehensive monitoring</p> + </div> + <div class="feature-card"> + <div class="feature-icon">đ</div> + <h4>RESTful</h4> + <p>Standard HTTP methods with JSON request/response format</p> + </div> + </div> + </section> + + <section id="authentication" class="doc-section"> + <h2>Authentication</h2> + <p> + TaskFlow API uses Bearer token authentication. Include your API token in the + <code>Authorization</code> header of your requests. + </p> + + <div class="code-example"> + <div class="code-header"> + <span>Request Headers</span> + </div> + <div class="code-block"> + <pre><code>Authorization: Bearer YOUR_API_TOKEN +Content-Type: application/json</code></pre> + <button class="copy-btn" data-copy="Authorization: Bearer YOUR_API_TOKEN Content-Type: application/json">Copy</button> + </div> + </div> + + <div class="alert alert-info"> + <div class="alert-icon">âšī¸</div> + <div class="alert-content"> + <strong>Getting Your API Token:</strong> You can generate API tokens from your + <a href="#" class="alert-link">account settings</a> page after signing in. + </div> + </div> + </section> + + <section id="rate-limits" class="doc-section"> + <h2>Rate Limits</h2> + <p> + API requests are rate limited to ensure fair usage and system stability. + </p> + + <div class="table-container"> + <table class="api-table"> + <thead> + <tr> + <th>Plan</th> + <th>Requests per minute</th> + <th>Requests per hour</th> + <th>Burst limit</th> + </tr> + </thead> + <tbody> + <tr> + <td><span class="plan-badge free">Free</span></td> + <td>60</td> + <td>1,000</td> + <td>100</td> + </tr> + <tr> + <td><span class="plan-badge pro">Pro</span></td> + <td>300</td> + <td>10,000</td> + <td>500</td> + </tr> + <tr> + <td><span class="plan-badge enterprise">Enterprise</span></td> + <td>1,000</td> + <td>50,000</td> + <td>2,000</td> + </tr> + </tbody> + </table> + </div> + + <h3>Rate Limit Headers</h3> + <p>Every API response includes rate limit information in the headers:</p> + + <div class="code-example"> + <div class="code-header"> + <span>Response Headers</span> + </div> + <div class="code-block"> + <pre><code>X-RateLimit-Limit: 300 +X-RateLimit-Remaining: 299 +X-RateLimit-Reset: 1640995200</code></pre> + <button class="copy-btn" data-copy="X-RateLimit-Limit: 300 X-RateLimit-Remaining: 299 X-RateLimit-Reset: 1640995200">Copy</button> + </div> + </div> + </section> + + <section id="errors" class="doc-section"> + <h2>Error Handling</h2> + <p> + TaskFlow API uses conventional HTTP response codes to indicate success or failure of requests. + </p> + + <div class="table-container"> + <table class="api-table"> + <thead> + <tr> + <th>Status Code</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><span class="status-code success">200</span></td> + <td>OK - Request successful</td> + </tr> + <tr> + <td><span class="status-code success">201</span></td> + <td>Created - Resource created successfully</td> + </tr> + <tr> + <td><span class="status-code client-error">400</span></td> + <td>Bad Request - Invalid request parameters</td> + </tr> + <tr> + <td><span class="status-code client-error">401</span></td> + <td>Unauthorized - Invalid or missing authentication</td> + </tr> + <tr> + <td><span class="status-code client-error">403</span></td> + <td>Forbidden - Insufficient permissions</td> + </tr> + <tr> + <td><span class="status-code client-error">404</span></td> + <td>Not Found - Resource not found</td> + </tr> + <tr> + <td><span class="status-code client-error">429</span></td> + <td>Too Many Requests - Rate limit exceeded</td> + </tr> + <tr> + <td><span class="status-code server-error">500</span></td> + <td>Internal Server Error - Server error</td> + </tr> + </tbody> + </table> + </div> + + <h3>Error Response Format</h3> + <div class="code-example"> + <div class="code-header"> + <span>Error Response</span> + </div> + <div class="code-block"> + <pre><code>{ + "error": { + "code": "VALIDATION_ERROR", + "message": "Invalid email format", + "details": { + "field": "email", + "value": "invalid-email" + } + } +}</code></pre> + <button class="copy-btn" data-copy='{"error":{"code":"VALIDATION_ERROR","message":"Invalid email format","details":{"field":"email","value":"invalid-email"}}}'>Copy</button> + </div> + </div> + </section> + + <section id="auth-login" class="doc-section"> + <h2>Authentication Endpoints</h2> + + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method post">POST</span> + <span class="path">/auth/login</span> + </div> + <p>Authenticate a user and receive access tokens.</p> + + <h4>Request Body</h4> + <div class="code-example"> + <div class="code-header"> + <span>JSON</span> + </div> + <div class="code-block"> + <pre><code>{ + "email": "user@example.com", + "password": "securepassword123" +}</code></pre> + <button class="copy-btn" data-copy='{"email":"user@example.com","password":"securepassword123"}'>Copy</button> + </div> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>{ + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "refresh_token": "def502004a8b7e...", + "token_type": "Bearer", + "expires_in": 3600, + "user": { + "id": "user_123", + "email": "user@example.com", + "name": "John Doe" + } +}</code></pre> + <button class="copy-btn" data-copy='{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","refresh_token":"def502004a8b7e...","token_type":"Bearer","expires_in":3600,"user":{"id":"user_123","email":"user@example.com","name":"John Doe"}}'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="auth-refresh" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method post">POST</span> + <span class="path">/auth/refresh</span> + </div> + <p>Refresh an expired access token using a refresh token.</p> + + <h4>Request Body</h4> + <div class="code-example"> + <div class="code-header"> + <span>JSON</span> + </div> + <div class="code-block"> + <pre><code>{ + "refresh_token": "def502004a8b7e..." +}</code></pre> + <button class="copy-btn" data-copy='{"refresh_token":"def502004a8b7e..."}'>Copy</button> + </div> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>{ + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "token_type": "Bearer", + "expires_in": 3600 +}</code></pre> + <button class="copy-btn" data-copy='{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","token_type":"Bearer","expires_in":3600}'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="auth-logout" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method post">POST</span> + <span class="path">/auth/logout</span> + </div> + <p>Invalidate the current access token and refresh token.</p> + + <h4>Headers</h4> + <div class="code-example"> + <div class="code-header"> + <span>Required</span> + </div> + <div class="code-block"> + <pre><code>Authorization: Bearer YOUR_ACCESS_TOKEN</code></pre> + <button class="copy-btn" data-copy="Authorization: Bearer YOUR_ACCESS_TOKEN">Copy</button> + </div> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>{ + "message": "Successfully logged out" +}</code></pre> + <button class="copy-btn" data-copy='{"message":"Successfully logged out"}'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="contact-submit" class="doc-section"> + <h2>Contact Endpoints</h2> + + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method post">POST</span> + <span class="path">/contact</span> + </div> + <p>Submit a contact form message.</p> + + <h4>Request Body</h4> + <div class="code-example"> + <div class="code-header"> + <span>JSON</span> + </div> + <div class="code-block"> + <pre><code>{ + "firstName": "John", + "lastName": "Doe", + "email": "john.doe@example.com", + "phone": "+1-555-123-4567", + "company": "Acme Corp", + "subject": "general", + "priority": "medium", + "message": "I'm interested in learning more about TaskFlow for my team.", + "newsletter": true, + "privacy": true +}</code></pre> + <button class="copy-btn" data-copy='{"firstName":"John","lastName":"Doe","email":"john.doe@example.com","phone":"+1-555-123-4567","company":"Acme Corp","subject":"general","priority":"medium","message":"I am interested in learning more about TaskFlow for my team.","newsletter":true,"privacy":true}'>Copy</button> + </div> + </div> + + <h4>Parameters</h4> + <div class="table-container"> + <table class="api-table"> + <thead> + <tr> + <th>Parameter</th> + <th>Type</th> + <th>Required</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>firstName</code></td> + <td>string</td> + <td><span class="required">Yes</span></td> + <td>Contact's first name</td> + </tr> + <tr> + <td><code>lastName</code></td> + <td>string</td> + <td><span class="required">Yes</span></td> + <td>Contact's last name</td> + </tr> + <tr> + <td><code>email</code></td> + <td>string</td> + <td><span class="required">Yes</span></td> + <td>Valid email address</td> + </tr> + <tr> + <td><code>phone</code></td> + <td>string</td> + <td><span class="optional">No</span></td> + <td>Phone number</td> + </tr> + <tr> + <td><code>company</code></td> + <td>string</td> + <td><span class="optional">No</span></td> + <td>Company name</td> + </tr> + <tr> + <td><code>subject</code></td> + <td>enum</td> + <td><span class="required">Yes</span></td> + <td>general, support, sales, billing, feature, partnership, other</td> + </tr> + <tr> + <td><code>priority</code></td> + <td>enum</td> + <td><span class="optional">No</span></td> + <td>low, medium, high, urgent (default: low)</td> + </tr> + <tr> + <td><code>message</code></td> + <td>string</td> + <td><span class="required">Yes</span></td> + <td>Message content (max 1000 characters)</td> + </tr> + <tr> + <td><code>newsletter</code></td> + <td>boolean</td> + <td><span class="optional">No</span></td> + <td>Subscribe to newsletter (default: false)</td> + </tr> + <tr> + <td><code>privacy</code></td> + <td>boolean</td> + <td><span class="required">Yes</span></td> + <td>Privacy policy agreement</td> + </tr> + </tbody> + </table> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>{ + "id": "contact_123456", + "message": "Contact form submitted successfully", + "ticket_id": "TF-2025-001234", + "estimated_response_time": "24 hours" +}</code></pre> + <button class="copy-btn" data-copy='{"id":"contact_123456","message":"Contact form submitted successfully","ticket_id":"TF-2025-001234","estimated_response_time":"24 hours"}'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="status-overall" class="doc-section"> + <h2>Status Endpoints</h2> + + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method get">GET</span> + <span class="path">/status</span> + </div> + <p>Get overall system status and key metrics.</p> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>{ + "status": "operational", + "description": "All systems are operating normally", + "uptime": 99.95, + "responseTime": 245, + "activeIncidents": 0, + "scheduledMaintenance": 0, + "lastUpdated": "2025-08-07T15:30:00Z" +}</code></pre> + <button class="copy-btn" data-copy='{"status":"operational","description":"All systems are operating normally","uptime":99.95,"responseTime":245,"activeIncidents":0,"scheduledMaintenance":0,"lastUpdated":"2025-08-07T15:30:00Z"}'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="status-services" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method get">GET</span> + <span class="path">/status/services</span> + </div> + <p>Get status of individual services.</p> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>[ + { + "id": "api", + "name": "API Gateway", + "description": "Core API services", + "status": "operational", + "responseTime": 180, + "uptime": 99.98 + }, + { + "id": "web", + "name": "Web Application", + "description": "TaskFlow web interface", + "status": "operational", + "responseTime": 120, + "uptime": 99.95 + } +]</code></pre> + <button class="copy-btn" data-copy='[{"id":"api","name":"API Gateway","description":"Core API services","status":"operational","responseTime":180,"uptime":99.98},{"id":"web","name":"Web Application","description":"TaskFlow web interface","status":"operational","responseTime":120,"uptime":99.95}]'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="status-metrics" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method get">GET</span> + <span class="path">/status/metrics</span> + </div> + <p>Get detailed performance metrics.</p> + + <h4>Query Parameters</h4> + <div class="table-container"> + <table class="api-table"> + <thead> + <tr> + <th>Parameter</th> + <th>Type</th> + <th>Default</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>range</code></td> + <td>enum</td> + <td>24h</td> + <td>Time range: 1h, 6h, 24h, 7d</td> + </tr> + <tr> + <td><code>metric</code></td> + <td>enum</td> + <td>all</td> + <td>Specific metric: responseTime, volume, errors</td> + </tr> + </tbody> + </table> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>{ + "range": "24h", + "responseTime": { + "average": 245, + "p95": 380, + "p99": 520, + "data": [ + { + "timestamp": "2025-08-07T14:00:00Z", + "value": 240 + } + ] + }, + "volume": { + "total": 1250000, + "average": 868, + "data": [ + { + "timestamp": "2025-08-07T14:00:00Z", + "value": 850 + } + ] + } +}</code></pre> + <button class="copy-btn" data-copy='{"range":"24h","responseTime":{"average":245,"p95":380,"p99":520,"data":[{"timestamp":"2025-08-07T14:00:00Z","value":240}]},"volume":{"total":1250000,"average":868,"data":[{"timestamp":"2025-08-07T14:00:00Z","value":850}]}}'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="status-incidents" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method get">GET</span> + <span class="path">/status/incidents</span> + </div> + <p>Get current and recent incidents.</p> + + <h4>Query Parameters</h4> + <div class="table-container"> + <table class="api-table"> + <thead> + <tr> + <th>Parameter</th> + <th>Type</th> + <th>Default</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>status</code></td> + <td>enum</td> + <td>all</td> + <td>Filter by status: investigating, identified, monitoring, resolved</td> + </tr> + <tr> + <td><code>limit</code></td> + <td>integer</td> + <td>10</td> + <td>Number of incidents to return (max 50)</td> + </tr> + </tbody> + </table> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>[ + { + "id": "incident_123", + "title": "Intermittent API Timeouts", + "description": "Some users may experience slow response times when accessing the API.", + "status": "investigating", + "severity": "minor", + "startTime": "2025-08-07T13:30:00Z", + "endTime": null, + "affectedServices": ["api", "web"], + "updates": [ + { + "timestamp": "2025-08-07T13:30:00Z", + "status": "investigating", + "message": "We are investigating reports of slow API response times." + } + ] + } +]</code></pre> + <button class="copy-btn" data-copy='[{"id":"incident_123","title":"Intermittent API Timeouts","description":"Some users may experience slow response times when accessing the API.","status":"investigating","severity":"minor","startTime":"2025-08-07T13:30:00Z","endTime":null,"affectedServices":["api","web"],"updates":[{"timestamp":"2025-08-07T13:30:00Z","status":"investigating","message":"We are investigating reports of slow API response times."}]}]'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="status-maintenance" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method get">GET</span> + <span class="path">/status/maintenance</span> + </div> + <p>Get scheduled maintenance windows.</p> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>[ + { + "id": "maintenance_456", + "title": "Database Maintenance Window", + "description": "Scheduled maintenance to upgrade database servers.", + "startTime": "2025-08-08T02:00:00Z", + "endTime": "2025-08-08T04:00:00Z", + "affectedServices": ["database", "api"], + "impact": "Brief service interruptions may occur", + "status": "scheduled" + } +]</code></pre> + <button class="copy-btn" data-copy='[{"id":"maintenance_456","title":"Database Maintenance Window","description":"Scheduled maintenance to upgrade database servers.","startTime":"2025-08-08T02:00:00Z","endTime":"2025-08-08T04:00:00Z","affectedServices":["database","api"],"impact":"Brief service interruptions may occur","status":"scheduled"}]'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="status-uptime" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method get">GET</span> + <span class="path">/status/uptime</span> + </div> + <p>Get historical uptime data.</p> + + <h4>Query Parameters</h4> + <div class="table-container"> + <table class="api-table"> + <thead> + <tr> + <th>Parameter</th> + <th>Type</th> + <th>Default</th> + <th>Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>days</code></td> + <td>integer</td> + <td>90</td> + <td>Number of days to return (max 365)</td> + </tr> + </tbody> + </table> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>[ + { + "date": "2025-08-07", + "uptime": 100.0 + }, + { + "date": "2025-08-06", + "uptime": 99.95 + } +]</code></pre> + <button class="copy-btn" data-copy='[{"date":"2025-08-07","uptime":100.0},{"date":"2025-08-06","uptime":99.95}]'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="status-subscribe" class="doc-section"> + <div class="endpoint"> + <div class="endpoint-header"> + <span class="method post">POST</span> + <span class="path">/status/subscribe</span> + </div> + <p>Subscribe to status page notifications.</p> + + <h4>Request Body</h4> + <div class="code-example"> + <div class="code-header"> + <span>JSON</span> + </div> + <div class="code-block"> + <pre><code>{ + "email": "user@example.com", + "notifications": ["incidents", "maintenance"], + "services": ["api", "web"] +}</code></pre> + <button class="copy-btn" data-copy='{"email":"user@example.com","notifications":["incidents","maintenance"],"services":["api","web"]}'>Copy</button> + </div> + </div> + + <h4>Response</h4> + <div class="code-example"> + <div class="code-header"> + <span>200 OK</span> + </div> + <div class="code-block"> + <pre><code>{ + "id": "subscription_789", + "message": "Successfully subscribed to status notifications", + "email": "user@example.com", + "confirmationSent": true +}</code></pre> + <button class="copy-btn" data-copy='{"id":"subscription_789","message":"Successfully subscribed to status notifications","email":"user@example.com","confirmationSent":true}'>Copy</button> + </div> + </div> + </div> + </section> + + <section id="sdks" class="doc-section"> + <h2>SDKs & Tools</h2> + <p>Official SDKs and tools to help you integrate with TaskFlow API.</p> + + <div class="sdk-grid"> + <div class="sdk-card"> + <div class="sdk-header"> + <div class="sdk-icon">đ¨</div> + <h4>JavaScript SDK</h4> + </div> + <p>Official JavaScript/TypeScript SDK for browser and Node.js applications.</p> + <div class="sdk-actions"> + <a href="#" class="btn btn-secondary">Documentation</a> + <a href="#" class="btn btn-ghost">GitHub</a> + </div> + </div> + + <div class="sdk-card"> + <div class="sdk-header"> + <div class="sdk-icon">đ</div> + <h4>Python SDK</h4> + </div> + <p>Official Python SDK with full API coverage and async support.</p> + <div class="sdk-actions"> + <a href="#" class="btn btn-secondary">Documentation</a> + <a href="#" class="btn btn-ghost">PyPI</a> + </div> + </div> + + <div class="sdk-card"> + <div class="sdk-header"> + <div class="sdk-icon">đˇ</div> + <h4>Go SDK</h4> + </div> + <p>Official Go SDK with comprehensive error handling and context support.</p> + <div class="sdk-actions"> + <a href="#" class="btn btn-secondary">Documentation</a> + <a href="#" class="btn btn-ghost">GitHub</a> + </div> + </div> + </div> + </section> + + <section id="postman" class="doc-section"> + <h3>Postman Collection</h3> + <p>Import our Postman collection to quickly test API endpoints.</p> + + <div class="postman-card"> + <div class="postman-content"> + <div class="postman-icon">đŽ</div> + <div> + <h4>TaskFlow API Collection</h4> + <p>Complete collection with all endpoints, examples, and environment variables.</p> + </div> + </div> + <a href="#" class="btn btn-primary">Import Collection</a> + </div> + </section> + + <section id="changelog" class="doc-section"> + <h2>Changelog</h2> + <div class="changelog"> + <div class="changelog-item"> + <div class="changelog-date"> + <div class="changelog-version">v1.0.0</div> + <div class="changelog-timestamp">August 7, 2025</div> + </div> + <div class="changelog-content"> + <h4>Initial API Release</h4> + <ul> + <li>Authentication endpoints (login, refresh, logout)</li> + <li>Contact form submission</li> + <li>Status page endpoints</li> + <li>Rate limiting implementation</li> + <li>Comprehensive error handling</li> + </ul> + </div> + </div> + </div> + </section> + </div> + </main> + </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> |