Get Project
Retrieve detailed information about a specific project by its ID.
Endpoint
GET /api/projects/{project_id}Authentication
Required: API key
Authorization: Bearer YOUR_API_KEYRequest
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
project_id | UUID | Yes | Unique project identifier |
Headers
| Header | Value | Required |
|---|---|---|
Authorization | Bearer YOUR_API_KEY | Yes |
Response
Success Response (200 OK)
{
"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"
}Response Fields
| Field | Type | Description |
|---|---|---|
id | UUID | Unique project identifier |
name | string | Project name |
description | string|null | Project description |
bucket_name | string | GCS bucket name |
is_default | boolean | Whether this is the default project |
is_active | boolean | Whether project is active |
file_count | integer | Number of files in project |
total_size_bytes | integer | Total size of all files in bytes |
created_date | datetime | When project was created (ISO 8601 UTC) |
updated_date | datetime | When project was last updated (ISO 8601 UTC) |
Error Responses
| Status | Error | Description | Solution |
|---|---|---|---|
| 401 | Unauthorized | Missing or invalid authentication | Verify Bearer token or API key |
| 403 | Forbidden | Project belongs to another user | Verify project_id belongs to your account |
| 404 | Not Found | Project doesn’t exist | Check project_id is correct |
| 422 | Unprocessable Entity | Invalid UUID format | Ensure project_id is valid UUID |
| 429 | Too Many Requests | Rate limit exceeded | Wait and retry with exponential backoff |
| 500 | Internal Server Error | Server error | Contact support if error persists |
Example Error Response (404 Not Found):
{
"detail": "Project not found"
}Example Error Response (422 Validation):
{
"detail": [
{
"loc": ["path", "project_id"],
"msg": "value is not a valid uuid",
"type": "type_error.uuid"
}
]
}Examples
cURL
curl "https://markdownapi.io/api/projects/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "Authorization: Bearer YOUR_TOKEN"Python (httpx)
import httpx
import os
from uuid import UUID
async def get_project(project_id: UUID | str):
"""Get project details by ID with error handling."""
api_key = os.getenv("MARKDOWN_API_KEY")
async with httpx.AsyncClient() as client:
try:
response = await client.get(
f"https://markdownapi.io/api/projects/{project_id}",
headers={"Authorization": f"Bearer {api_key}"},
timeout=10.0
)
response.raise_for_status()
project = response.json()
print(f"Project: {project['name']}")
print(f" Files: {project['file_count']}")
print(f" Size: {project['total_size_bytes']:,} bytes")
print(f" Created: {project['created_date']}")
return project
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
print(f"✗ Project not found")
elif e.response.status_code == 403:
print(f"✗ Access denied - not your project")
else:
print(f"✗ HTTP error: {e.response.status_code}")
raise
except Exception as e:
print(f"✗ Unexpected error: {e}")
raise
# Usage
# project = await get_project("a1b2c3d4-e5f6-7890-abcd-ef1234567890")TypeScript
interface ProjectResponse {
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;
}
async function getProject(projectId: string): Promise<ProjectResponse> {
const apiKey = process.env.MARKDOWN_API_KEY;
try {
const response = await fetch(
`https://markdownapi.io/api/projects/${projectId}`,
{
headers: {
'Authorization': `Bearer ${apiKey!}`,
},
}
);
if (!response.ok) {
if (response.status === 404) {
throw new Error('Project not found');
} else if (response.status === 403) {
throw new Error('Access denied - not your project');
}
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const project: ProjectResponse = await response.json();
console.log(`Project: ${project.name}`);
console.log(` Files: ${project.file_count}`);
console.log(` Size: ${project.total_size_bytes.toLocaleString()} bytes`);
console.log(` Created: ${project.created_date}`);
return project;
} catch (error) {
console.error('✗ Failed to get project:', error);
throw error;
}
}
// Usage
// const project = await getProject('a1b2c3d4-e5f6-7890-abcd-ef1234567890');Common Use Cases
1. Check Project Storage
async def check_project_storage(project_id: UUID):
"""Check if project is approaching storage limits."""
project = await get_project(project_id)
size_mb = project['total_size_bytes'] / (1024 * 1024)
if size_mb > 90 * 1024: # 90 GB
print(f"⚠ Warning: {size_mb:.1f} MB (limit: 100 GB)")
else:
print(f"Storage: {size_mb:.1f} MB")
return size_mb
# Usage
# storage = await check_project_storage(project_id)2. Verify Project Exists
async def project_exists(project_id: UUID) -> bool:
"""Check if project exists and is accessible."""
try:
await get_project(project_id)
return True
except httpx.HTTPStatusError as e:
if e.response.status_code in (404, 403):
return False
raise
# Usage
# if await project_exists(project_id):
# print("Project exists")3. Get Project Statistics
async def get_project_stats(project_id: UUID):
"""Get formatted project statistics."""
project = await get_project(project_id)
return {
'name': project['name'],
'files': project['file_count'],
'size_mb': project['total_size_bytes'] / (1024 * 1024),
'avg_file_size_kb': (project['total_size_bytes'] / project['file_count'] / 1024)
if project['file_count'] > 0 else 0,
'is_active': project['is_active'],
}
# Usage
# stats = await get_project_stats(project_id)4. Refresh Project Info
async def refresh_project_info(project_id: UUID):
"""Refresh cached project information."""
project = await get_project(project_id)
# Update your cache/state
app.state.projects[project_id] = project
print(f"✓ Refreshed: {project['name']}")
print(f" Files: {project['file_count']}")
print(f" Last updated: {project['updated_date']}")
return project
# Usage
# project = await refresh_project_info(project_id)5. Compare Project Sizes
async def compare_projects(project_ids: list[UUID]):
"""Compare storage usage across projects."""
projects = await asyncio.gather(*[
get_project(pid) for pid in project_ids
])
for project in sorted(projects, key=lambda p: p['total_size_bytes'], reverse=True):
size_mb = project['total_size_bytes'] / (1024 * 1024)
print(f"{project['name']}: {size_mb:.2f} MB ({project['file_count']} files)")
# Usage
# await compare_projects([project_id_1, project_id_2, project_id_3])Performance Characteristics
Timing
- Typical duration: 20-50ms
- Single database query with pre-calculated statistics
- Fast lookups using indexed project_id
Caching Strategy
Since statistics update with every file operation, caching should be short-lived:
from functools import lru_cache
from datetime import datetime, timedelta
class ProjectInfoCache:
def __init__(self):
self.cache = {}
self.ttl = timedelta(minutes=1)
async def get(self, project_id: UUID):
"""Get project with 1-minute cache."""
cache_entry = self.cache.get(project_id)
if cache_entry:
cached_at, project = cache_entry
if datetime.utcnow() - cached_at < self.ttl:
return project
project = await get_project(project_id)
self.cache[project_id] = (datetime.utcnow(), project)
return project
# Usage
# cache = ProjectInfoCache()
# project = await cache.get(project_id)Best Practices
1. Validate UUID Format
from uuid import UUID
def validate_project_id(project_id: str) -> UUID:
"""Validate and convert project ID to UUID."""
try:
return UUID(project_id)
except ValueError:
raise ValueError(f"Invalid project ID format: {project_id}")
# Usage
# project_id = validate_project_id(user_input)2. Handle Not Found Gracefully
async def get_project_safe(project_id: UUID):
"""Get project with graceful not-found handling."""
try:
return await get_project(project_id)
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
return None # Or default project
raise
# Usage
# project = await get_project_safe(project_id)
# if project is None:
# project = await get_default_project()3. Use for Verification
Always verify project exists before file operations:
async def upload_file_to_project(project_id: UUID, file_path: str):
"""Upload file with project verification."""
# Verify project exists first
project = await get_project(project_id)
if not project['is_active']:
raise ValueError("Cannot upload to inactive project")
# Proceed with upload
await upload_file(project_id, file_path)See Also
- List Projects - View all projects
- Update Project - Modify project details
- List Files - View files in project
- Projects Overview - Learn about projects
Last updated on