Documentation
Files API Reference
User file management, search, filtering, uploads, and website link storage
File Management
Manage uploaded images, documents, videos, and saved website links. Supports full-text search, filtering by tags/dates/media type, and folder organization.
Uploads
/api/v2/user-files/upload/initiateInitiate a presigned URL upload for an image file (max 50MB). Returns a presigned URL to upload to.
Request
// multipart/form-data fields (NOT JSON):// Required:// filename: string - Original filename// content_type: string - image/jpeg, image/jpg, image/png, image/webp, image/gif// size_bytes: integer - File size in bytes (max 50MB / 52,428,800)// Optional:// title: string (max 255 chars)// tags: string - Comma-separated tags (e.g. "damage,concrete")// auto_describe: boolean (default true)
// Example using curl:curl -X POST /api/v2/user-files/upload/initiate \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "filename=site_photo.jpg" \ -F "content_type=image/jpeg" \ -F "size_bytes=2048576" \ -F "title=Site Photo A" \ -F "tags=damage,concrete"Response
{ "upload_url": "https://s3.amazonaws.com/bucket/...", "upload_method": "PUT", // "POST" or "PUT" "upload_fields": null, "upload_headers": null, "object_key": "uploads/{tenant_id}/{uuid}/site_photo.jpg", "image_id": "550e8400-e29b-41d4-a716-446655440000", "expires_at": "2025-01-15T10:40:00Z", "max_size_bytes": 52428800, "thumbnail_url": null, "variant_urls": null}/api/v2/user-files/upload/confirmConfirm a presigned URL upload completed. Triggers variant generation and optional auto-description.
Request
{ "object_key": "uploads/{tenant_id}/{uuid}/site_photo.jpg", "size_bytes": 2048576, "image_id": "550e8400-e29b-41d4-a716-446655440000"}Response
{ "image_id": "550e8400-e29b-41d4-a716-446655440000", "description_status": "pending", "title": "Site Photo A", "tags": ["damage", "concrete"]}/api/v2/user-files/upload/streamDirect streaming upload for a single file. Accepts multipart/form-data.
Request
// multipart/form-data fields:// file: (binary, required) - the file to upload// title: (string, optional) - file title// tags: (string, optional) - comma-separated tags// auto_describe: (boolean, optional, default true)// skip_duplicates: (boolean, optional, default false)// storage_target: (string, optional) - "default" or "custom"Response
{ "image_id": "550e8400-e29b-41d4-a716-446655440000", "object_key": "uploads/{tenant_id}/{uuid}/site_photo.jpg", "upload_method": "STREAMING", "status": "completed", "processing_time_ms": 1250.5, "s3_upload_completed": true, "variants_queued": true, "description_queued": true, "skipped": false, "skipped_existing_image_id": null, "storage_target": "default", "media_type": "image", "document_type": null, "text_extraction_status": null}
// For document uploads, media_type will be "document"// and document_type / text_extraction_status will be populated/api/v2/user-files/upload/stream-batchMulti-file streaming batch upload. Accepts multipart/form-data with multiple files.
Request
// multipart/form-data fields:// files: (binary[], required) - files to upload (multiple)// auto_describe: (boolean, optional, default true)// skip_duplicates: (boolean, optional, default false)// tags: (string, optional) - comma-separated tags applied to all files// intent: (string, optional) - "describe" | "verify" | "rules"// verification_level: (string, optional)// storage_target: (string, optional) - "default" or "custom"Response
{ "session_id": "550e8400-e29b-41d4-a716-446655440000", "total_files": 3, "accepted_files": 3, "rejected_files": 0, "status": "completed", "immediate_results": [ { "image_id": "660f9500-e29b-41d4-a716-446655440000", "filename": "photo1.jpg", "object_key": "uploads/...", "status": "completed", "processing_time_ms": 850.2, "skipped": false, "skipped_existing_image_id": null, "error": null, "storage_target": "default", "media_type": "image", "document_type": null, "text_extraction_status": null } ], "status_url": "/api/v2/uploads/sessions/{session_id}/status", "websocket_channel": "batch.{session_id}", "rejections": null}
// immediate_results only present for batches of 5 or fewer files// For larger batches, poll status_url or subscribe to websocket_channel// status values: completed | partial | failed | rejectedFile Listing & Search
/api/v2/user-filesList user files with search and filtering
Request
// Query parameters:?search=damage report // optional, full-text search&search_mode=all // optional, default: all, options: all | metadata | visible_text&tags=safety,inspection // optional, filter by tags&media_types=image,document // optional, options: image | video | document | link&folder_id=folder_abc123 // optional, filter by folder&has_description=true // optional, filter by description status&ids=uuid1,uuid2 // optional, filter by specific file IDs (max 500)&date_from=2025-01-01T00:00:00Z // optional&date_to=2025-01-31T23:59:59Z // optional&sort_by=content_created_at // optional, default: content_created_at, options: created_at | content_created_at | title | size_bytes&sort_order=desc // optional, default: desc, options: asc | desc&limit=20 // optional, default: 20, 1-100&offset=0 // optional, default: 0Response
{ "files": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "title": "Site Photo A", "filename": "site_photo.jpg", "thumbnail_url": "https://cdn.aionvision.tech/thumbs/...", "upload_description": "Damaged concrete pillar with visible cracks...", "visible_text": "WARNING: STRUCTURAL DAMAGE", "tags": ["damage", "concrete"], "size_bytes": 2048576, "created_at": "2025-01-15T10:30:00Z", "content_created_at": "2025-01-14T08:00:00Z", "has_full_description": true, "dimensions": {"width": 4000, "height": 3000}, "format": "jpeg", "variant_status": "completed", "variant_count": 5, "medium_url": "https://cdn.aionvision.tech/medium/...", "full_url": "https://cdn.aionvision.tech/large/...", "blur_hash": "L6PZfSi_.AyE_3t7t7R**0o#DgR4", "description_status": "completed", "description_error": null, "confidence_score": 0.95, "content_type": "image/jpeg", "media_type": "image",
"video_metadata": null, "video_analysis_status": null, "document_type": null, "source_url": null } ], "total_count": 150, "has_more": true}
// Conditional fields by media_type:// video: video_metadata, video_analysis_status, video_analysis_job_id,// scene_count, has_audio_transcript, video_url// document: document_type, page_count, text_extraction_status,// chunk_count, document_url// link: source_url, domain, og_metadata, favicon_url,// crawl_status, extracted_images, extracted_images_count/api/v2/user-files/{file_id}Get detailed file information including processing history. Accepts full UUID or 8-character prefix.
Response
{ "id": "550e8400-e29b-41d4-a716-446655440000", "object_key": "uploads/{tenant_id}/{uuid}/site_photo.jpg", "title": "Site Photo A", "tags": ["damage", "concrete"], "size_bytes": 2048576, "content_type": "image/jpeg", "dimensions": {"width": 4000, "height": 3000}, "format": "jpeg", "full_url": "https://cdn.aionvision.tech/large/...", "thumbnail_url": "https://cdn.aionvision.tech/thumbs/...", "medium_url": "https://cdn.aionvision.tech/medium/...", "original_url": "https://cdn.aionvision.tech/originals/...", "variant_status": "completed", "variant_count": 5, "upload_description": "Damaged concrete pillar...", "visible_text": "WARNING: STRUCTURAL DAMAGE", "description_generated_at": "2025-01-15T10:32:00Z", "full_descriptions": [ { "id": "770a0600-e29b-41d4-a716-446655440000", "description": "Image shows a concrete pillar with visible cracks...", "visible_text": "WARNING: STRUCTURAL DAMAGE", "confidence_score": 0.95, "providers_used": ["provider_a", "provider_b"], "verification_level": "standard", "processing_time_ms": 1250, "created_at": "2025-01-15T10:32:00Z" } ], "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:35:00Z", "content_created_at": "2025-01-14T08:00:00Z", "upload_method": "STREAMING", "original_filename": "site_photo.jpg", "hash": "sha256:abc123...", "processing_history": [ { "id": "880b1700-e29b-41d4-a716-446655440000", "operation_type": "describe", "status": "completed", "created_at": "2025-01-15T10:30:05Z", "completed_at": "2025-01-15T10:32:00Z", "error_message": null } ], "blur_hash": "L6PZfSi_.AyE_3t7t7R**0o#DgR4", "description_status": "completed", "media_type": "image"}
// Additional fields for documents:// document_type, page_count, text_extraction_status, chunk_count, document_url// Additional fields for links:// source_url, domain, og_metadata, favicon_url, page_title,// crawl_status, crawl_error, crawled_at, extracted_images, extracted_images_count/api/v2/user-files/{file_id}/variant/{variant_type}Get a specific image variant. Returns 302 redirect to presigned S3 URL.
Request
// variant_type options:// - original: Original uploaded image// - tiny_64: 64px max dimension// - small_256: 256px max dimension// - medium_750: 750px max dimension// - large_1024: 1024px max dimensionResponse
// Returns 302 Redirect to presigned variant URL// URL expires in 1 hourFile Updates & Deletion
/api/v2/user-files/{file_id}Update file metadata (title, tags). Both fields are optional.
Request
{ "title": "Updated Photo Title", "tags": ["updated", "reviewed"]}
// title: optional, max 255 characters// tags: optional, max 40 tags, each max 50 charactersResponse
{ "id": "550e8400-e29b-41d4-a716-446655440000", "title": "Updated Photo Title", "tags": ["updated", "reviewed"], "updated_at": "2025-01-15T11:00:00Z"}/api/v2/user-files/{file_id}Soft-delete a file and its variants. Recoverable within 30 days.
Response
{ "id": "550e8400-e29b-41d4-a716-446655440000", "deleted_at": "2025-01-15T11:00:00Z", "message": "File deleted successfully"}/api/v2/user-files/batch-deleteDelete multiple files at once. Requires 1-100 unique UUIDs.
Request
{ "file_ids": [ "550e8400-e29b-41d4-a716-446655440000", "660f9500-f39c-52e5-b827-557766550111" ]}Response
{ "deleted": [ {"id": "550e8400-e29b-41d4-a716-446655440000", "status": "deleted", "message": null, "deleted_at": "2025-01-15T11:00:00Z"} ], "skipped": [], "failed": [ {"id": "660f9500-f39c-52e5-b827-557766550111", "status": "failed", "message": "File not found", "deleted_at": null} ], "summary": { "total": 2, "deleted": 1, "skipped": 0, "failed": 1 }}/api/v2/user-files/{file_id}/downloadDownload original file. Returns 302 redirect to presigned S3 URL with Content-Disposition header.
Response
// Returns 302 Redirect to presigned download URL// URL expires in 1 hour// Content-Disposition header set for download/api/v2/user-files/{file_id}/trigger-variantsManually trigger variant generation for an image. Useful for recovery if variants failed.
Response
{ "success": true, "message": "Variant generation triggered", "task_id": "task_550e8400", "current_status": "queued", "image_id": "550e8400-e29b-41d4-a716-446655440000"}
// If already processing:// { "success": true, "message": "Variant generation already in progress",// "skipped_duplicate": true, ... }Website Links
Link Management
Save website links for later reference. Links are automatically crawled to extract Open Graph metadata, favicon, and page content for AI-powered search and analysis.
/api/v2/user-files/linksSave a website link. Returns 201 Created. URL must start with http:// or https://.
Request
{ "url": "https://github.com/example/repo", "title": "My Favorite Repo", "tags": ["development", "reference"], "folder_id": "550e8400-e29b-41d4-a716-446655440000", "auto_crawl": true}
// url: required, max 2048 chars, must start with http:// or https://// title: optional, max 500 chars// tags: optional, max 40 tags, each max 50 chars// folder_id: optional UUID// auto_crawl: optional, default trueResponse
{ "id": "550e8400-e29b-41d4-a716-446655440000", "source_url": "https://github.com/example/repo", "title": "My Favorite Repo", "domain": "github.com", "crawl_status": "queued", "is_duplicate": false, "created_at": "2025-01-15T10:30:00Z"}/api/v2/user-files/{link_id}/recrawlManually trigger a recrawl to refresh link metadata. Rate limited to once per hour.
Response
{ "status": "queued", "link_id": "550e8400-e29b-41d4-a716-446655440000"}
// Error responses:// 400 - Not a link or already processing// 404 - Link not found// 429 - Recrawl limited to once per hourLink Crawling
- • Automatic crawling: Links are crawled asynchronously after creation
- • Metadata extracted: Open Graph title, description, image, favicon
- • Page content: Text content is extracted for search and analysis
- • Duplicates: Duplicate URLs are detected with a warning but still allowed
Link Fields in User Files
Links appear in GET /api/v2/user-files with media_type: "link". Filter links using ?media_types=link. Link-specific fields include:
- •
source_url: Original URL - •
domain: Extracted domain (e.g., "github.com") - •
page_title: Page title from crawl - •
og_metadata: Open Graph data (title, description, image, site_name) - •
favicon_url: Site favicon URL - •
crawl_status: pending | queued | processing | completed | failed - •
crawl_error: Error message if crawl failed - •
crawled_at: Last crawl timestamp - •
extracted_images: Images extracted from page - •
extracted_images_count: Count of extracted images