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

POST/api/v2/user-files/upload/initiate

Initiate 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
}
POST/api/v2/user-files/upload/confirm

Confirm 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"]
}
POST/api/v2/user-files/upload/stream

Direct 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
POST/api/v2/user-files/upload/stream-batch

Multi-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 | rejected

File Listing & Search

GET/api/v2/user-files

List 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: 0

Response

{
"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
GET/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
GET/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 dimension

Response

// Returns 302 Redirect to presigned variant URL
// URL expires in 1 hour

File Updates & Deletion

PATCH/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 characters

Response

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Updated Photo Title",
"tags": ["updated", "reviewed"],
"updated_at": "2025-01-15T11:00:00Z"
}
DELETE/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"
}
POST/api/v2/user-files/batch-delete

Delete 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
}
}
GET/api/v2/user-files/{file_id}/download

Download 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
POST/api/v2/user-files/{file_id}/trigger-variants

Manually 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.

POST/api/v2/user-files/links

Save 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 true

Response

{
"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"
}
POST/api/v2/user-files/{link_id}/recrawl

Manually 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 hour

Link 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