summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--static/api-docs-script.js449
-rw-r--r--static/api-docs-styles.css1073
-rw-r--r--static/api-docs.html937
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>