Skip to Content

List Projects

Retrieve all projects in your account with their statistics and metadata. Returns all projects including inactive ones.

Endpoint

GET /api/projects

Authentication

Required: API key

Authorization: Bearer YOUR_API_KEY

Request

Headers

HeaderValueRequired
AuthorizationBearer YOUR_API_KEYYes

Query Parameters

None. Returns all projects for the authenticated user.

Response

Success Response (200 OK)

{ "projects": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "AI Articles 2025", "description": "Collection of AI-generated articles", "bucket_name": "markdown-api-user123-a1b2c3d4", "is_default": false, "is_active": true, "file_count": 42, "total_size_bytes": 2097152, "created_date": "2025-01-09T10:00:00Z", "updated_date": "2025-01-09T15:30:00Z" }, { "id": "b2c3d4e5-f6a7-8901-bcde-f1234567890a", "name": "Default Project", "description": null, "bucket_name": "markdown-api-user123-b2c3d4e5", "is_default": true, "is_active": true, "file_count": 15, "total_size_bytes": 524288, "created_date": "2025-01-01T00:00:00Z", "updated_date": "2025-01-05T12:00:00Z" } ], "total_count": 2 }

Response Fields

FieldTypeDescription
projectsarrayArray of project objects
total_countintegerTotal number of projects returned

Project Object Fields:

FieldTypeDescription
idUUIDUnique project identifier
namestringProject name
descriptionstring|nullProject description
bucket_namestringGCS bucket name
is_defaultbooleanWhether this is the default project
is_activebooleanWhether project is active
file_countintegerNumber of files in project
total_size_bytesintegerTotal size of all files in bytes
created_datedatetimeWhen project was created (ISO 8601 UTC)
updated_datedatetimeWhen project was last updated (ISO 8601 UTC)

Error Responses

StatusErrorDescriptionSolution
401UnauthorizedMissing or invalid authenticationVerify Bearer token or API key
429Too Many RequestsRate limit exceededWait and retry with exponential backoff
500Internal Server ErrorServer errorContact support if error persists

Examples

cURL

curl "https://markdownapi.io/api/projects" \ -H "Authorization: Bearer YOUR_TOKEN"

Python (httpx)

import httpx import os async def list_projects(): """List all projects with error handling.""" api_key = os.getenv("MARKDOWN_API_KEY") async with httpx.AsyncClient() as client: try: response = await client.get( "https://markdownapi.io/api/projects", headers={"Authorization": f"Bearer {api_key}"}, timeout=10.0 ) response.raise_for_status() data = response.json() print(f"Found {data['total_count']} projects:") for project in data['projects']: print(f" • {project['name']}") print(f" Files: {project['file_count']}, " f"Size: {project['total_size_bytes']} bytes") return data['projects'] except httpx.HTTPStatusError as e: print(f"✗ HTTP error: {e.response.status_code}") raise except Exception as e: print(f"✗ Unexpected error: {e}") raise # Usage # projects = await list_projects()

TypeScript

interface Project { id: string; name: string; description: string | null; bucket_name: string; is_default: boolean; is_active: boolean; file_count: number; total_size_bytes: number; created_date: string; updated_date: string; } interface ListProjectsResponse { projects: Project[]; total_count: number; } async function listProjects(): Promise<Project[]> { const apiKey = process.env.MARKDOWN_API_KEY; try { const response = await fetch('https://markdownapi.io/api/projects', { headers: { 'Authorization': `Bearer ${apiKey!}`, }, }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data: ListProjectsResponse = await response.json(); console.log(`Found ${data.total_count} projects:`); data.projects.forEach(project => { console.log(` • ${project.name}`); console.log(` Files: ${project.file_count}, Size: ${project.total_size_bytes} bytes`); }); return data.projects; } catch (error) { console.error('✗ Failed to list projects:', error); throw error; } } // Usage // const projects = await listProjects();

Common Use Cases

1. Find Project by Name

async def find_project_by_name(name: str): """Find project by exact name match.""" projects = await list_projects() return next((p for p in projects if p['name'] == name), None) # Usage # project = await find_project_by_name("AI Articles 2025")

2. Get Default Project

async def get_default_project(): """Get the default project.""" projects = await list_projects() return next((p for p in projects if p['is_default']), None) # Usage # default_project = await get_default_project()

3. Get Active Projects Only

async def get_active_projects(): """Filter to only active projects.""" projects = await list_projects() return [p for p in projects if p['is_active']] # Usage # active_projects = await get_active_projects()

4. Calculate Total Storage

async def calculate_total_storage(): """Calculate total storage across all projects.""" projects = await list_projects() total_bytes = sum(p['total_size_bytes'] for p in projects) total_mb = total_bytes / (1024 * 1024) print(f"Total storage: {total_mb:.2f} MB") return total_bytes # Usage # total = await calculate_total_storage()

5. Sort Projects by Size

async def get_largest_projects(limit: int = 5): """Get projects sorted by size (largest first).""" projects = await list_projects() sorted_projects = sorted( projects, key=lambda p: p['total_size_bytes'], reverse=True ) return sorted_projects[:limit] # Usage # largest = await get_largest_projects(5)

Performance Characteristics

Timing

  • Typical duration: 50-150ms
  • Scales with: Number of projects (minimal impact up to 1000 projects)
  • Optimization: Results include pre-calculated statistics

Caching Recommendations

Projects change infrequently - implement caching:

from datetime import datetime, timedelta class ProjectCache: def __init__(self, ttl_minutes: int = 5): self.cache = None self.cached_at = None self.ttl = timedelta(minutes=ttl_minutes) async def get_projects(self): """Get projects with 5-minute cache.""" now = datetime.utcnow() if self.cache is None or \ self.cached_at is None or \ now - self.cached_at > self.ttl: self.cache = await list_projects() self.cached_at = now return self.cache # Usage # cache = ProjectCache(ttl_minutes=5) # projects = await cache.get_projects() # Cached for 5 minutes

Best Practices

1. Cache Results

List projects API is ideal for caching since projects change infrequently.

2. Filter Client-Side

Since all projects are returned, filter in your application rather than making multiple API calls.

3. Store Project IDs

After listing once, store project IDs in your application configuration.

# On application startup projects = await list_projects() project_map = {p['name']: p['id'] for p in projects} # Later, use cached IDs project_id = project_map['AI Articles 2025']

4. Monitor Growth

Track project count over time to plan capacity:

async def check_project_limits(): """Alert if approaching soft limits.""" projects = await list_projects() count = len(projects) if count > 900: print(f"⚠ Warning: {count} projects (soft limit: 1000)") elif count > 500: print(f"ℹ Info: {count} projects")

Pagination

Currently, this endpoint returns all projects without pagination. For accounts with many projects (>100), future versions may introduce pagination.

Future API (example):

GET /api/projects?limit=50&offset=100

For now, all projects are returned in a single response.

See Also

Last updated on