Skip to Content

Upload File

Upload a Markdown or MDX file to a project. Files are stored in Google Cloud Storage and can be retrieved later.

Endpoint

POST /api/projects/{project_id}/files

Authentication

Required: API key in Authorization header

Authorization: Bearer YOUR_API_KEY

Request

Path Parameters

ParameterTypeRequiredDescription
project_idUUIDYesThe project ID

Headers

HeaderValueRequired
Content-Typemultipart/form-dataYes

Request Body

FieldTypeRequiredConstraintsDescription
filefileYes.md or .mdx, max 10MBThe Markdown/MDX file
metadataJSON stringNoValid JSON objectOptional metadata

File Constraints:

  • Extensions: .md, .mdx
  • Maximum size: 10 MB
  • Unique filename within project
  • UTF-8 encoding

Response

Success Response (201 Created)

{ "filename": "article.mdx", "project_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "size_bytes": 4096, "content_type": "text/markdown", "metadata": { "title": "My Article", "author": "John Doe" }, "storage_path": "gs://markdown-api-user123-a1b2c3d4/article.mdx", "created_date": "2025-01-09T10:00:00Z", "updated_date": "2025-01-09T10:00:00Z" }

Error Responses

StatusErrorDescription
400Bad RequestInvalid file format
401UnauthorizedInvalid authentication
404Not FoundProject does not exist
409ConflictFile already exists
413Payload Too LargeFile exceeds 10MB
415Unsupported Media TypeInvalid extension

Examples

cURL

curl -X POST "https://markdownapi.io/api/projects/PROJECT_ID/files" \ -H "Authorization: Bearer YOUR_TOKEN" \ -F "file=@article.mdx" \ -F 'metadata={"title":"My Article","author":"John Doe"}'

Python (httpx)

import httpx import os import json async def upload_file(project_id: str, file_path: str, metadata: dict | None = None): api_key = os.getenv("MARKDOWN_API_KEY") async with httpx.AsyncClient() as client: with open(file_path, 'rb') as f: files = {'file': (os.path.basename(file_path), f, 'text/markdown')} data = {} if metadata: data['metadata'] = json.dumps(metadata) response = await client.post( f"https://markdownapi.io/api/projects/{project_id}/files", headers={"Authorization": f"Bearer {api_key}"}, files=files, data=data, timeout=60.0 ) response.raise_for_status() file_info = response.json() print(f"✓ File uploaded: {file_info['filename']}") print(f" Size: {file_info['size_bytes']} bytes") return file_info

TypeScript

interface UploadFileOptions { projectId: string; file: File; metadata?: Record<string, any>; } async function uploadFile({ projectId, file, metadata }: UploadFileOptions) { const apiKey = process.env.MARKDOWN_API_KEY; const formData = new FormData(); formData.append('file', file); if (metadata) { formData.append('metadata', JSON.stringify(metadata)); } const response = await fetch( `https://markdownapi.io/api/projects/${projectId}/files`, { method: 'POST', headers: { 'Authorization': `Bearer ${apiKey!}` }, body: formData, } ); if (!response.ok) throw new Error(`HTTP ${response.status}`); const fileInfo = await response.json(); console.log(`✓ File uploaded: ${fileInfo.filename}`); return fileInfo; }

Best Practices

Unique Filenames

Use descriptive, unique filenames:

# Good "2025-01-09-introduction-to-ai.mdx" "client-abc-report-q1-2025.md" # Avoid "article.mdx" "file.md"

Rich Metadata

Include comprehensive metadata:

metadata = { "title": "Introduction to AI", "author": "Jane Doe", "date": "2025-01-09", "tags": ["ai", "tutorial"], "status": "published" }

Error Handling

Always handle upload errors:

try: file_info = await upload_file(project_id, file_path) except httpx.HTTPStatusError as e: if e.response.status_code == 409: # Handle duplicate pass elif e.response.status_code == 413: # Handle file too large pass

Validate Before Upload

Check file validity:

def validate_file(file_path: str): # Check extension if not file_path.endswith(('.md', '.mdx')): raise ValueError("File must be .md or .mdx") # Check size import os size_mb = os.path.getsize(file_path) / (1024 * 1024) if size_mb > 10: raise ValueError(f"File too large: {size_mb:.2f}MB (max 10MB)")

Rate Limiting

Upload operations are rate-limited:

  • Standard accounts: 1000 requests/hour
  • Recommended: 10-50 uploads/minute
  • Burst allowance: Up to 100 uploads/minute

See Also

Last updated on