Skip to content

Files & Uploads Endpoints

File upload via presigned URLs, file serving, and admin operations.


Presigned URL Upload

Method Endpoint Description
POST /api/v1/uploads/presigned-url Generate a presigned URL for direct R2 upload

Request

Field Type Required Description
filename string Yes Original filename
content_type string Yes MIME type of the file
size integer No File size in bytes (used for dynamic token expiration)

Response

Field Type Description
upload_url string Presigned R2 URL — client PUTs file directly here
file_url string CDN URL where the file will be accessible
upload_method string PUT
expires_in_seconds integer Token validity (default 15 min, adjusted by file size)
max_file_size integer Maximum allowed file size in bytes (52428800 = 50MB)

The client uploads the file directly to R2 using the presigned URL. The file is stored at temp/{file_id}_{timestamp}_{safe_filename} and later relocated to permanent storage during entity creation.

MediaResource Lifecycle

The file_url returned from the presigned response is a temporary CDN path pointing to the temp/ prefix. When the entity is created (e.g., POST /products), the Backend's MediaResourceService.ingest_all() processes the temp URL:

  1. HEAD the temp file to get ETag and size
  2. Compute content hash for deduplication
  3. On dedup miss: create MediaResource, relocate file to canonical path media/{resource_id}/file.{ext}
  4. On dedup hit: reuse existing MediaResource, delete temp file
  5. Create MediaResourceAttachment linking the resource to the entity

The final canonical URL is {CDN_URL}/media/{resource_id}/file.{ext}. See MediaResource Lifecycle for full details.


File Serving

Method Endpoint Description
GET /files/{file_path:path} Backward compatibility endpoint to serve a file via 302 redirect to CDN/MinIO

Query Parameters

Parameter Type Description
type string Optional format conversion (webp, jpeg, png, avif, gif)

Behavior

  • In production (Cloudflare Image Transformations enabled): redirects to /cdn-cgi/image/format={type},quality=90/{file_path}
  • In development (MinIO): redirects directly to {R2_PUBLIC_URL}/{file_path}

Admin Upload [ Deprecated, needs removal ]

Method Endpoint Description
POST /api/v1/uploads/admin/upload-lora Upload a LoRA model file (superuser only)

Requires superuser authentication. Used for uploading LoRA training model files to storage.


Validation Rules

Rule Value
Max file size 50MB
Allowed image types image/jpeg, image/png, image/webp, image/gif, image/avif
Other allowed types application/zip, application/pdf, video/mp4, audio/mpeg
Filename sanitization Directory traversal prevention, safe character enforcement

Bulk Upload

Method Endpoint Description
POST /bulk-upload/ Start a bulk CSV import
GET /bulk-upload/{id} Get bulk upload job status
GET /bulk-upload/{id}/errors Get upload errors for a job

Export Configuration

Method Endpoint Description
GET /export-configuration/ List export configurations
POST /export-configuration/ Create an export configuration

API Reference

Sartiq Backend Server - Files 0.1.0

export-configuration


GET /api/v1/users/export-configurations/{config_id}

Get Export Configuration

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
config_id path string No

Responses

{
    "created_at": "2025-01-01T00:00:00Z",
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "image_format": "webp",
    "metadata_adapter": "default",
    "name": "Default",
    "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
    "organization_id": "123e4567-e89b-12d3-a456-426614174001",
    "updated_at": "2025-01-01T00:00:00Z"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
        },
        "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
        },
        "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
        },
        "organization_id": {
            "anyOf": [
                {
                    "type": "string",
                    "format": "uuid"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Organization Id"
        },
        "shooting_type_id": {
            "type": "string",
            "format": "uuid",
            "title": "Shooting Type Id"
        },
        "shooting_type_key": {
            "$ref": "#/components/schemas/ShootingTypeKey"
        },
        "is_system": {
            "type": "boolean",
            "title": "Is System"
        },
        "name": {
            "type": "string",
            "title": "Name"
        },
        "metadata_adapter": {
            "$ref": "#/components/schemas/MetadataAdapter"
        },
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat"
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "type": "boolean",
            "title": "Ai Disclosure Enabled",
            "default": false
        }
    },
    "type": "object",
    "required": [
        "id",
        "created_at",
        "updated_at",
        "organization_id",
        "shooting_type_id",
        "shooting_type_key",
        "is_system",
        "name",
        "metadata_adapter",
        "image_format"
    ],
    "title": "ExportConfigurationPublic",
    "description": "Public schema for export configuration responses.",
    "example": {
        "created_at": "2025-01-01T00:00:00Z",
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "image_format": "webp",
        "metadata_adapter": "default",
        "name": "Default",
        "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
        "organization_id": "123e4567-e89b-12d3-a456-426614174001",
        "updated_at": "2025-01-01T00:00:00Z"
    }
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

PATCH /api/v1/users/export-configurations/{config_id}

Update Export Configuration

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
config_id path string No

Request body

{
    "image_format": "jpeg",
    "metadata_adapter": "ovs"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "name": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Name"
        },
        "metadata_adapter": {
            "anyOf": [
                {
                    "$ref": "#/components/schemas/MetadataAdapter"
                },
                {
                    "type": "null"
                }
            ]
        },
        "image_format": {
            "anyOf": [
                {
                    "$ref": "#/components/schemas/ImageFormat"
                },
                {
                    "type": "null"
                }
            ]
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "anyOf": [
                {
                    "type": "boolean"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Ai Disclosure Enabled"
        }
    },
    "type": "object",
    "title": "ExportConfigurationUpdate",
    "description": "Schema for updating an existing export configuration.\n\nAll fields are optional to support partial updates via PATCH.",
    "example": {
        "image_format": "jpeg",
        "metadata_adapter": "ovs"
    }
}

Responses

{
    "created_at": "2025-01-01T00:00:00Z",
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "image_format": "webp",
    "metadata_adapter": "default",
    "name": "Default",
    "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
    "organization_id": "123e4567-e89b-12d3-a456-426614174001",
    "updated_at": "2025-01-01T00:00:00Z"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
        },
        "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
        },
        "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
        },
        "organization_id": {
            "anyOf": [
                {
                    "type": "string",
                    "format": "uuid"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Organization Id"
        },
        "shooting_type_id": {
            "type": "string",
            "format": "uuid",
            "title": "Shooting Type Id"
        },
        "shooting_type_key": {
            "$ref": "#/components/schemas/ShootingTypeKey"
        },
        "is_system": {
            "type": "boolean",
            "title": "Is System"
        },
        "name": {
            "type": "string",
            "title": "Name"
        },
        "metadata_adapter": {
            "$ref": "#/components/schemas/MetadataAdapter"
        },
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat"
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "type": "boolean",
            "title": "Ai Disclosure Enabled",
            "default": false
        }
    },
    "type": "object",
    "required": [
        "id",
        "created_at",
        "updated_at",
        "organization_id",
        "shooting_type_id",
        "shooting_type_key",
        "is_system",
        "name",
        "metadata_adapter",
        "image_format"
    ],
    "title": "ExportConfigurationPublic",
    "description": "Public schema for export configuration responses.",
    "example": {
        "created_at": "2025-01-01T00:00:00Z",
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "image_format": "webp",
        "metadata_adapter": "default",
        "name": "Default",
        "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
        "organization_id": "123e4567-e89b-12d3-a456-426614174001",
        "updated_at": "2025-01-01T00:00:00Z"
    }
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

DELETE /api/v1/users/export-configurations/{config_id}

Delete Export Configuration

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
config_id path string No

Responses

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "message": {
            "type": "string",
            "title": "Message"
        }
    },
    "type": "object",
    "required": [
        "message"
    ],
    "title": "Message"
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

GET /api/v1/users/organizations/{org_id}/export-configurations

List Organization Export Configurations

Description

List organization rows, or a Shooting-compatible contextual picker.

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
org_id path string No
shooting_id query No

Responses

[
    {
        "created_at": "2025-01-01T00:00:00Z",
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "image_format": "webp",
        "metadata_adapter": "default",
        "name": "Default",
        "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
        "organization_id": "123e4567-e89b-12d3-a456-426614174001",
        "updated_at": "2025-01-01T00:00:00Z"
    }
]
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "type": "array",
    "items": {
        "$ref": "#/components/schemas/ExportConfigurationPublic"
    },
    "title": "Response List Organization Export Configurations"
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

GET /api/v1/users/organizations/{org_id}/export-configuration

Get Organization Export Configuration

Description

Legacy singleton read, valid only when one compatible org row exists.

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
org_id path string No
shooting_id query No

Responses

{
    "created_at": "2025-01-01T00:00:00Z",
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "image_format": "webp",
    "metadata_adapter": "default",
    "name": "Default",
    "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
    "organization_id": "123e4567-e89b-12d3-a456-426614174001",
    "updated_at": "2025-01-01T00:00:00Z"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
        },
        "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
        },
        "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
        },
        "organization_id": {
            "anyOf": [
                {
                    "type": "string",
                    "format": "uuid"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Organization Id"
        },
        "shooting_type_id": {
            "type": "string",
            "format": "uuid",
            "title": "Shooting Type Id"
        },
        "shooting_type_key": {
            "$ref": "#/components/schemas/ShootingTypeKey"
        },
        "is_system": {
            "type": "boolean",
            "title": "Is System"
        },
        "name": {
            "type": "string",
            "title": "Name"
        },
        "metadata_adapter": {
            "$ref": "#/components/schemas/MetadataAdapter"
        },
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat"
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "type": "boolean",
            "title": "Ai Disclosure Enabled",
            "default": false
        }
    },
    "type": "object",
    "required": [
        "id",
        "created_at",
        "updated_at",
        "organization_id",
        "shooting_type_id",
        "shooting_type_key",
        "is_system",
        "name",
        "metadata_adapter",
        "image_format"
    ],
    "title": "ExportConfigurationPublic",
    "description": "Public schema for export configuration responses.",
    "example": {
        "created_at": "2025-01-01T00:00:00Z",
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "image_format": "webp",
        "metadata_adapter": "default",
        "name": "Default",
        "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
        "organization_id": "123e4567-e89b-12d3-a456-426614174001",
        "updated_at": "2025-01-01T00:00:00Z"
    }
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

POST /api/v1/users/organizations/{org_id}/export-configuration

Create Organization Export Configuration

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
org_id path string No

Request body

{
    "image_format": "webp",
    "metadata_adapter": "default",
    "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "name": {
            "type": "string",
            "title": "Name",
            "default": "Default"
        },
        "metadata_adapter": {
            "$ref": "#/components/schemas/MetadataAdapter",
            "default": "default"
        },
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat",
            "default": "webp"
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "type": "boolean",
            "title": "Ai Disclosure Enabled",
            "default": false
        },
        "shooting_type_id": {
            "anyOf": [
                {
                    "type": "string",
                    "format": "uuid"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Shooting Type Id"
        }
    },
    "type": "object",
    "title": "ExportConfigurationCreate",
    "description": "Schema for creating a new export configuration.",
    "example": {
        "image_format": "webp",
        "metadata_adapter": "default",
        "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}"
    }
}

Responses

{
    "created_at": "2025-01-01T00:00:00Z",
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "image_format": "webp",
    "metadata_adapter": "default",
    "name": "Default",
    "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
    "organization_id": "123e4567-e89b-12d3-a456-426614174001",
    "updated_at": "2025-01-01T00:00:00Z"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
        },
        "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
        },
        "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
        },
        "organization_id": {
            "anyOf": [
                {
                    "type": "string",
                    "format": "uuid"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Organization Id"
        },
        "shooting_type_id": {
            "type": "string",
            "format": "uuid",
            "title": "Shooting Type Id"
        },
        "shooting_type_key": {
            "$ref": "#/components/schemas/ShootingTypeKey"
        },
        "is_system": {
            "type": "boolean",
            "title": "Is System"
        },
        "name": {
            "type": "string",
            "title": "Name"
        },
        "metadata_adapter": {
            "$ref": "#/components/schemas/MetadataAdapter"
        },
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat"
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "type": "boolean",
            "title": "Ai Disclosure Enabled",
            "default": false
        }
    },
    "type": "object",
    "required": [
        "id",
        "created_at",
        "updated_at",
        "organization_id",
        "shooting_type_id",
        "shooting_type_key",
        "is_system",
        "name",
        "metadata_adapter",
        "image_format"
    ],
    "title": "ExportConfigurationPublic",
    "description": "Public schema for export configuration responses.",
    "example": {
        "created_at": "2025-01-01T00:00:00Z",
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "image_format": "webp",
        "metadata_adapter": "default",
        "name": "Default",
        "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
        "organization_id": "123e4567-e89b-12d3-a456-426614174001",
        "updated_at": "2025-01-01T00:00:00Z"
    }
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

PATCH /api/v1/users/organizations/{org_id}/export-configuration

Update Organization Export Configuration

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
org_id path string No
shooting_id query No

Request body

{
    "image_format": "jpeg",
    "metadata_adapter": "ovs"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "name": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Name"
        },
        "metadata_adapter": {
            "anyOf": [
                {
                    "$ref": "#/components/schemas/MetadataAdapter"
                },
                {
                    "type": "null"
                }
            ]
        },
        "image_format": {
            "anyOf": [
                {
                    "$ref": "#/components/schemas/ImageFormat"
                },
                {
                    "type": "null"
                }
            ]
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "anyOf": [
                {
                    "type": "boolean"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Ai Disclosure Enabled"
        }
    },
    "type": "object",
    "title": "ExportConfigurationUpdate",
    "description": "Schema for updating an existing export configuration.\n\nAll fields are optional to support partial updates via PATCH.",
    "example": {
        "image_format": "jpeg",
        "metadata_adapter": "ovs"
    }
}

Responses

{
    "created_at": "2025-01-01T00:00:00Z",
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "image_format": "webp",
    "metadata_adapter": "default",
    "name": "Default",
    "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
    "organization_id": "123e4567-e89b-12d3-a456-426614174001",
    "updated_at": "2025-01-01T00:00:00Z"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
        },
        "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
        },
        "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
        },
        "organization_id": {
            "anyOf": [
                {
                    "type": "string",
                    "format": "uuid"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Organization Id"
        },
        "shooting_type_id": {
            "type": "string",
            "format": "uuid",
            "title": "Shooting Type Id"
        },
        "shooting_type_key": {
            "$ref": "#/components/schemas/ShootingTypeKey"
        },
        "is_system": {
            "type": "boolean",
            "title": "Is System"
        },
        "name": {
            "type": "string",
            "title": "Name"
        },
        "metadata_adapter": {
            "$ref": "#/components/schemas/MetadataAdapter"
        },
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat"
        },
        "naming_convention_template": {
            "anyOf": [
                {
                    "type": "string"
                },
                {
                    "type": "null"
                }
            ],
            "title": "Naming Convention Template"
        },
        "ai_disclosure_enabled": {
            "type": "boolean",
            "title": "Ai Disclosure Enabled",
            "default": false
        }
    },
    "type": "object",
    "required": [
        "id",
        "created_at",
        "updated_at",
        "organization_id",
        "shooting_type_id",
        "shooting_type_key",
        "is_system",
        "name",
        "metadata_adapter",
        "image_format"
    ],
    "title": "ExportConfigurationPublic",
    "description": "Public schema for export configuration responses.",
    "example": {
        "created_at": "2025-01-01T00:00:00Z",
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "image_format": "webp",
        "metadata_adapter": "default",
        "name": "Default",
        "naming_convention_template": "{brand}_{product_sku}_{shot_type}_{version}",
        "organization_id": "123e4567-e89b-12d3-a456-426614174001",
        "updated_at": "2025-01-01T00:00:00Z"
    }
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

DELETE /api/v1/users/organizations/{org_id}/export-configuration

Delete Organization Export Configuration

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No
org_id path string No
shooting_id query No

Responses

{
    "message": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "message": {
            "type": "string",
            "title": "Message"
        }
    },
    "type": "object",
    "required": [
        "message"
    ],
    "title": "Message"
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

POST /api/v1/export-configurations/agent-create

Agent Create Export Configuration

Description

Export configuration in the format the run observed. JOB-SCOPED token only.

The body carries the image format and nothing else: the organization comes from the job, the metadata adapter is always DEFAULT, and there is no naming template. An adapter encodes a delivery contract with a named customer — picking one from a scraped storefront would rename that customer's files.

Reuse-by-match, never update: an existing configuration with the same format, the DEFAULT adapter and no naming template is returned untouched (created: false); a tuned configuration is neither matched nor modified, so the run creates its own row beside it.

409 when the job has no target shooting — an org-level configuration no guideline will point at is litter that outlives the run.

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No

Request body

{
    "image_format": "jpeg"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat"
        }
    },
    "additionalProperties": false,
    "type": "object",
    "required": [
        "image_format"
    ],
    "title": "ExportConfigurationAgentCreate",
    "description": "Body of ``POST /export-configurations/agent-create`` (plan 003).\n\nOne field. ``organization_id`` comes from the job token;\n``metadata_adapter`` and ``naming_convention_template`` are absent by\nconstruction — an adapter renames every exported file according to a\ndelivery contract with a named customer, and nothing in a scraped product\ngrid could evidence such a choice.\n\n``extra=\"forbid\"`` so a body carrying one of them fails loudly instead of\nbeing accepted and stripped, which from the caller's side is\nindistinguishable from being honoured.\n\n``image_format`` is typed as the ENUM with a before-validator, not as a\nstring: the alias translation happens once, here at the edge, so the\nservice, the repository and the column all see an ``ImageFormat`` and an\nunmappable format is a 422 by construction rather than a check somebody\nlater forgets."
}

Responses

{
    "id": "8cb2a2a8-a3e4-4f4e-8db2-25245d028d9f",
    "name": "string",
    "image_format": "jpeg",
    "created": true
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
        },
        "name": {
            "type": "string",
            "title": "Name"
        },
        "image_format": {
            "$ref": "#/components/schemas/ImageFormat"
        },
        "created": {
            "type": "boolean",
            "title": "Created"
        }
    },
    "type": "object",
    "required": [
        "id",
        "name",
        "image_format",
        "created"
    ],
    "title": "ExportConfigurationAgentPublic",
    "description": "Response of ``POST /export-configurations/agent-create``.\n\nNarrow on purpose, like the stylist agent response: the job token gets the\nid it needs to attach, the format so the run can report what was set, and\n``created`` — false when an existing matching configuration was reused\nuntouched."
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

uploads


POST /api/v1/uploads/presigned-url

Get Presigned Url

Description

Generate presigned URL for file upload. In local implementation, returns a token and upload endpoint instead.

Accepts EITHER a logged-in user OR a capture-session upload token (SAR-1822). A capture-session token is upload-only and pinned to its own drop: the requested folder must be the token's media/ingest/<drop_id>[/...] folder.

Enhanced features: - Dynamic token expiration based on file size - Better content type validation - File size limits for < 10MB files

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No

Request body

{
    "folder": "string",
    "filename": "string",
    "content_type": "string",
    "file_size": null
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "folder": {
            "type": "string",
            "title": "Folder"
        },
        "filename": {
            "type": "string",
            "title": "Filename"
        },
        "content_type": {
            "type": "string",
            "title": "Content Type"
        },
        "file_size": {
            "anyOf": [
                {
                    "type": "integer"
                },
                {
                    "type": "null"
                }
            ],
            "title": "File Size"
        }
    },
    "type": "object",
    "required": [
        "folder",
        "filename",
        "content_type"
    ],
    "title": "PresignedUrlRequest"
}

Responses

Schema of the response body

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

POST /api/v1/uploads/delete-object

Delete Uploaded Object

Description

Delete a just-uploaded object from a capture-session drop (SAR-1825).

The phone's "long-press to remove a shot" affordance: photos stream into the drop the moment they are taken, so removing one before the seal must delete the storage object — the seal-on-close pass sweeps everything under the drop folder.

CAPTURE TOKENS ONLY, and only within the token's own drop folder: this is deliberately narrower than presign (an operator manages drops through the ingest job flow, never by raw object deletion).

Input parameters

Parameter In Type Default Nullable Description
OAuth2PasswordBearer header string N/A No

Request body

{
    "object_key": "string"
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the request body
{
    "properties": {
        "object_key": {
            "type": "string",
            "title": "Object Key"
        }
    },
    "type": "object",
    "required": [
        "object_key"
    ],
    "title": "DeleteObjectRequest"
}

Responses

Schema of the response body
{
    "additionalProperties": true,
    "type": "object",
    "title": "Response Delete Uploaded Object"
}

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

files


GET /files/{file_path}

Serve File

Description

Serve files by redirecting to the storage backend (MinIO or Cloudflare R2 CDN).

In production with Cloudflare, uses Image Transformations for format conversion. In local dev (MinIO), redirects directly to the MinIO URL.

Input parameters

Parameter In Type Default Nullable Description
file_path path string No
type query No Target image format

Responses

Schema of the response body

{
    "detail": [
        {
            "loc": [
                null
            ],
            "msg": "string",
            "type": "string",
            "input": null,
            "ctx": {}
        }
    ]
}
⚠️ This example has been generated automatically from the schema and it is not accurate. Refer to the schema for more information.

Schema of the response body
{
    "properties": {
        "detail": {
            "items": {
                "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
        }
    },
    "type": "object",
    "title": "HTTPValidationError"
}

Schemas

DeleteObjectRequest

Name Type Description
object_key string

ExportConfigurationAgentCreate

Name Type Description
image_format ImageFormat

ExportConfigurationAgentPublic

Name Type Description
created boolean
id string(uuid)
image_format ImageFormat
name string

ExportConfigurationCreate

Name Type Description
ai_disclosure_enabled boolean
image_format ImageFormat
metadata_adapter MetadataAdapter
name string
naming_convention_template
shooting_type_id

ExportConfigurationPublic

Name Type Description
ai_disclosure_enabled boolean
created_at string(date-time)
id string(uuid)
image_format ImageFormat
is_system boolean
metadata_adapter MetadataAdapter
name string
naming_convention_template
organization_id
shooting_type_id string(uuid)
shooting_type_key ShootingTypeKey
updated_at string(date-time)

ExportConfigurationUpdate

Name Type Description
ai_disclosure_enabled
image_format
metadata_adapter
name
naming_convention_template

HTTPValidationError

Name Type Description
detail Array<ValidationError>

ImageFormat

Type: string

Message

Name Type Description
message string

MetadataAdapter

Type: string

PresignedUrlRequest

Name Type Description
content_type string
file_size
filename string
folder string

ShootingTypeKey

Type: string

ValidationError

Name Type Description
ctx
input
loc Array<>
msg string
type string

Security schemes

Name Type Scheme Description
OAuth2PasswordBearer oauth2