Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
import asyncio
|
|
|
|
|
import logging
|
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter, HTTPException, Query
|
|
|
|
|
|
|
|
|
|
from app.schemas.common import TaskDetail, TaskResponse, TaskStatus
|
|
|
|
|
from app.schemas.image_editing import (
|
|
|
|
|
ExpandRequest,
|
|
|
|
|
InpaintRequest,
|
|
|
|
|
RelightRequest,
|
|
|
|
|
StyleTransferRequest,
|
|
|
|
|
UpscaleCreativeRequest,
|
|
|
|
|
UpscalePrecisionRequest,
|
|
|
|
|
)
|
|
|
|
|
from app.services import freepik_client, task_tracker
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
from app.services.freepik_client import TaskResult, _extract_task_id
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix='/api/v1/edit', tags=['image-editing'])
|
|
|
|
|
|
|
|
|
|
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
async def _submit_and_respond(result: TaskResult, sync: bool, metadata: dict) -> TaskResponse | TaskDetail:
|
|
|
|
|
freepik_task_id = _extract_task_id(result.data)
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
if not freepik_task_id:
|
|
|
|
|
raise HTTPException(status_code=502, detail='No task_id in Freepik response')
|
|
|
|
|
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
internal_id = task_tracker.submit(freepik_task_id, result.status_path, metadata)
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
|
|
|
|
|
if not sync:
|
|
|
|
|
return TaskResponse(
|
|
|
|
|
task_id=internal_id,
|
|
|
|
|
status=TaskStatus.pending,
|
|
|
|
|
created_at=datetime.now(timezone.utc),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
from app.config import settings
|
|
|
|
|
elapsed = 0
|
|
|
|
|
while elapsed < settings.task_poll_timeout_seconds:
|
|
|
|
|
await asyncio.sleep(2)
|
|
|
|
|
elapsed += 2
|
|
|
|
|
task = task_tracker.get_task(internal_id)
|
|
|
|
|
if not task:
|
|
|
|
|
raise HTTPException(status_code=500, detail='Task disappeared')
|
|
|
|
|
if task['status'] == TaskStatus.completed:
|
|
|
|
|
return TaskDetail(
|
|
|
|
|
task_id=internal_id,
|
|
|
|
|
status=TaskStatus.completed,
|
|
|
|
|
created_at=task['created_at'],
|
|
|
|
|
updated_at=task['updated_at'],
|
|
|
|
|
progress=1.0,
|
|
|
|
|
result_url=f'/api/v1/tasks/{internal_id}/result',
|
|
|
|
|
)
|
|
|
|
|
if task['status'] == TaskStatus.failed:
|
|
|
|
|
raise HTTPException(status_code=502, detail=task.get('error', 'Task failed'))
|
|
|
|
|
|
|
|
|
|
raise HTTPException(status_code=504, detail='Task did not complete in time')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/upscale/creative', response_model=TaskResponse)
|
|
|
|
|
async def upscale_creative(request: UpscaleCreativeRequest, sync: bool = Query(False)):
|
|
|
|
|
result = await freepik_client.upscale_creative(
|
|
|
|
|
image=request.image,
|
|
|
|
|
prompt=request.prompt,
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
scale_factor=request.scale_factor,
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
creativity=request.creativity,
|
|
|
|
|
resemblance=request.resemblance,
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
optimized_for=request.optimized_for,
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
)
|
|
|
|
|
return await _submit_and_respond(result, sync, {'operation': 'upscale-creative'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/upscale/precision', response_model=TaskResponse)
|
|
|
|
|
async def upscale_precision(request: UpscalePrecisionRequest, sync: bool = Query(False)):
|
|
|
|
|
result = await freepik_client.upscale_precision(
|
|
|
|
|
image=request.image,
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
scale_factor=request.scale_factor,
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
)
|
|
|
|
|
return await _submit_and_respond(result, sync, {'operation': 'upscale-precision'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/relight', response_model=TaskResponse)
|
|
|
|
|
async def relight(request: RelightRequest, sync: bool = Query(False)):
|
|
|
|
|
result = await freepik_client.relight_image(
|
|
|
|
|
image=request.image,
|
|
|
|
|
prompt=request.prompt,
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
transfer_light_from_reference_image=request.transfer_light_from_reference_image,
|
|
|
|
|
light_transfer_strength=request.light_transfer_strength,
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
)
|
|
|
|
|
return await _submit_and_respond(result, sync, {'operation': 'relight'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/style-transfer', response_model=TaskResponse)
|
|
|
|
|
async def style_transfer(request: StyleTransferRequest, sync: bool = Query(False)):
|
|
|
|
|
result = await freepik_client.style_transfer(
|
|
|
|
|
image=request.image,
|
fix: align Freepik API paths with OpenAPI spec
The original implementation used guessed endpoint paths that don't match
the actual Freepik API. Key fixes based on their OpenAPI spec:
- Task polling is per-endpoint (e.g. GET /v1/ai/text-to-image/flux-dev/{task-id})
not a generic /v1/ai/tasks/{id}. freepik_client now returns TaskResult
with status_path, and task_tracker polls using that path.
- Fixed endpoint paths: flux-pro -> flux-pro-v1-1, upscale -> image-upscaler,
relight -> image-relight, style-transfer -> image-style-transfer,
expand -> image-expand/flux-pro, inpaint -> ideogram-image-edit,
remove-background -> beta/remove-background, classifier -> classifier/image,
audio-isolate -> audio-isolation, icon -> text-to-icon
- Fixed video paths: kling -> kling-o1-pro with kling-o1 status path,
minimax -> minimax-hailuo-02-1080p, seedance -> seedance-pro-1080p
- Fixed request schemas to match actual API params (e.g. scale_factor
not scale, reference_image not style_reference, image_url for bg removal)
- Fixed response parsing: status is uppercase (COMPLETED not completed),
results in data.generated[] array, classifier returns [{class_name, probability}]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:26:42 +01:00
|
|
|
reference_image=request.reference_image,
|
|
|
|
|
prompt=request.prompt,
|
|
|
|
|
style_strength=request.style_strength,
|
|
|
|
|
structure_strength=request.structure_strength,
|
Initial commit: Freepik REST API
FastAPI async wrapper for Freepik cloud AI API supporting image generation
(Mystic, Flux Dev/Pro, SeedReam), video generation (Kling, MiniMax, Seedance),
image editing (upscale, relight, style transfer, expand, inpaint), and
utilities (background removal, classifier, audio isolation). Includes async
task tracking with polling, Docker containerization, and Gitea CI/CD workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 14:07:36 +01:00
|
|
|
)
|
|
|
|
|
return await _submit_and_respond(result, sync, {'operation': 'style-transfer'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/expand', response_model=TaskResponse)
|
|
|
|
|
async def expand(request: ExpandRequest, sync: bool = Query(False)):
|
|
|
|
|
result = await freepik_client.expand_image(
|
|
|
|
|
image=request.image,
|
|
|
|
|
prompt=request.prompt,
|
|
|
|
|
)
|
|
|
|
|
return await _submit_and_respond(result, sync, {'operation': 'expand'})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post('/inpaint', response_model=TaskResponse)
|
|
|
|
|
async def inpaint(request: InpaintRequest, sync: bool = Query(False)):
|
|
|
|
|
result = await freepik_client.inpaint(
|
|
|
|
|
image=request.image,
|
|
|
|
|
mask=request.mask,
|
|
|
|
|
prompt=request.prompt,
|
|
|
|
|
)
|
|
|
|
|
return await _submit_and_respond(result, sync, {'operation': 'inpaint'})
|