mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Merge branch 'feat/section-based-tool-urls' into chore/consolidate-v2.0.0
This commit is contained in:
+175
-169
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Batch processing route.
|
||||
*
|
||||
* POST /api/v1/tools/:toolId/batch
|
||||
* POST /api/v1/tools/:section/:toolId/batch
|
||||
*
|
||||
* Accepts multipart with multiple files + settings JSON.
|
||||
* Each file is enqueued as a batch-child BullMQ job; a batch-finalize
|
||||
@@ -12,7 +12,7 @@ import { randomUUID } from "node:crypto";
|
||||
import { mkdir } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { getBundleForTool, TOOL_BUNDLE_MAP, TOOLS } from "@snapotter/shared";
|
||||
import { getBundleForTool, TOOL_BUNDLE_MAP, TOOLS, toolSection } from "@snapotter/shared";
|
||||
import archiver from "archiver";
|
||||
import type { FlowJob } from "bullmq";
|
||||
import { eq } from "drizzle-orm";
|
||||
@@ -56,10 +56,17 @@ function injectTraceContextIntoFlow(node: FlowJob): void {
|
||||
|
||||
export async function registerBatchRoutes(app: FastifyInstance): Promise<void> {
|
||||
app.post(
|
||||
"/api/v1/tools/:toolId/batch",
|
||||
"/api/v1/tools/:section/:toolId/batch",
|
||||
{ config: { rateLimit: { max: 20, timeWindow: "1 minute" } } },
|
||||
async (request: FastifyRequest<{ Params: { toolId: string } }>, reply: FastifyReply) => {
|
||||
const { toolId } = request.params;
|
||||
async (
|
||||
request: FastifyRequest<{ Params: { section: string; toolId: string } }>,
|
||||
reply: FastifyReply,
|
||||
) => {
|
||||
const { section, toolId } = request.params;
|
||||
const tool = TOOLS.find((t) => t.id === toolId);
|
||||
if (!tool || toolSection(tool) !== section) {
|
||||
return reply.status(404).send({ error: "Not found", code: "NOT_FOUND" });
|
||||
}
|
||||
|
||||
// Batch processing (especially with AI) can take tens of minutes.
|
||||
// Disable the Node.js HTTP socket timeout so the connection is not
|
||||
@@ -182,7 +189,7 @@ export async function registerBatchRoutes(app: FastifyInstance): Promise<void> {
|
||||
|
||||
// Resolve the tool's modality so non-image files (audio/video/document)
|
||||
// validate through their own handler instead of the image validator.
|
||||
const modality = TOOLS.find((t) => t.id === toolId)?.modality ?? "image";
|
||||
const modality = tool.modality;
|
||||
const batchScratch = join(tmpdir(), "snapotter-scratch", `batch-${parentId}`);
|
||||
await mkdir(batchScratch, { recursive: true });
|
||||
|
||||
|
||||
@@ -2,7 +2,14 @@ import { randomUUID } from "node:crypto";
|
||||
import { mkdir, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { extname, join } from "node:path";
|
||||
import { ANALYTICS_EVENTS, getBundleForTool, TOOL_BUNDLE_MAP, TOOLS } from "@snapotter/shared";
|
||||
import {
|
||||
ANALYTICS_EVENTS,
|
||||
apiToolPath,
|
||||
getBundleForTool,
|
||||
type Section,
|
||||
TOOL_BUNDLE_MAP,
|
||||
TOOLS,
|
||||
} from "@snapotter/shared";
|
||||
import { and, inArray, sql } from "drizzle-orm";
|
||||
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
||||
import type { z } from "zod";
|
||||
@@ -67,6 +74,12 @@ export type ToolProcessV2 = (ctx: ToolProcessCtxV2) => Promise<ToolProcessResult
|
||||
export interface ToolRouteConfig<T> {
|
||||
/** Unique tool identifier, used as the URL path segment. */
|
||||
toolId: string;
|
||||
/**
|
||||
* Override the URL section for non-catalog alias routes kept for
|
||||
* backwards-compatible URLs (e.g. adjust-colors' brightness-contrast).
|
||||
* Catalog tools omit this; their section is derived via apiToolPath.
|
||||
*/
|
||||
section?: Section;
|
||||
/**
|
||||
* How many file parts the route accepts (default 1). Inputs beyond the
|
||||
* first are validated by the same modality handler and appended to
|
||||
@@ -186,7 +199,7 @@ export function registerToolProcessFn(config: AnyToolRouteConfig): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory that registers a POST /api/v1/tools/:toolId route.
|
||||
* Factory that registers a POST /api/v1/tools/:section/:toolId route.
|
||||
*
|
||||
* The route accepts multipart with:
|
||||
* - A file part (the image to process)
|
||||
@@ -211,7 +224,9 @@ export function createToolRoute<T>(app: FastifyInstance, config: ToolRouteConfig
|
||||
toolRegistry.set(config.toolId, resolved);
|
||||
|
||||
app.post(
|
||||
`/api/v1/tools/${config.toolId}`,
|
||||
config.section
|
||||
? `/api/v1/tools/${config.section}/${config.toolId}`
|
||||
: apiToolPath(config.toolId),
|
||||
{ config: { rateLimit: { max: 60, timeWindow: "1 minute" } } },
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
// Check per-tool access before processing uploads
|
||||
|
||||
@@ -133,14 +133,20 @@ async function processColorAdjustments(
|
||||
}
|
||||
|
||||
export function registerColorAdjustments(app: FastifyInstance) {
|
||||
const allIds = [
|
||||
"adjust-colors",
|
||||
"brightness-contrast",
|
||||
"saturation",
|
||||
"color-channels",
|
||||
"color-effects",
|
||||
];
|
||||
for (const toolId of allIds) {
|
||||
createToolRoute(app, { toolId, settingsSchema, process: processColorAdjustments });
|
||||
createToolRoute(app, {
|
||||
toolId: "adjust-colors",
|
||||
settingsSchema,
|
||||
process: processColorAdjustments,
|
||||
});
|
||||
// Backwards-compatible alias routes consolidated into adjust-colors. These
|
||||
// ids are not catalog TOOLS, so pass the section explicitly (all image).
|
||||
const aliasIds = ["brightness-contrast", "saturation", "color-channels", "color-effects"];
|
||||
for (const toolId of aliasIds) {
|
||||
createToolRoute(app, {
|
||||
toolId,
|
||||
section: "image",
|
||||
settingsSchema,
|
||||
process: processColorAdjustments,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ registerAiJobHandler("ai-canvas-expand", async (input, data, ctx) => {
|
||||
|
||||
export function registerAiCanvasExpand(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/ai-canvas-expand",
|
||||
"/api/v1/tools/image/ai-canvas-expand",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "ai-canvas-expand";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
|
||||
@@ -90,7 +90,7 @@ registerAiJobHandler("auto-subtitles", async (input, data, ctx) => {
|
||||
});
|
||||
|
||||
export function registerAutoSubtitles(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/auto-subtitles", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/video/auto-subtitles", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "auto-subtitles";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -110,7 +110,7 @@ registerAiJobHandler("background-replace", async (input, data, ctx) => {
|
||||
|
||||
export function registerBackgroundReplace(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/background-replace",
|
||||
"/api/v1/tools/image/background-replace",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "background-replace";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
|
||||
@@ -19,7 +19,7 @@ const settingsSchema = z.object({
|
||||
*/
|
||||
export function registerBarcodeGenerate(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/barcode-generate",
|
||||
"/api/v1/tools/image/barcode-generate",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let body: unknown;
|
||||
try {
|
||||
|
||||
@@ -79,7 +79,7 @@ function buildOverlaySvg(
|
||||
* Read barcodes (all 1D + 2D types) from uploaded images using zxing-wasm.
|
||||
*/
|
||||
export function registerBarcodeRead(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/barcode-read", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/barcode-read", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
@@ -245,7 +245,7 @@ export async function processBeautify(
|
||||
|
||||
export function registerBeautify(app: FastifyInstance) {
|
||||
// Custom HTTP route (multi-file upload: main image + optional background image)
|
||||
app.post("/api/v1/tools/beautify", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/beautify", async (request, reply) => {
|
||||
let mainBuffer: Buffer | null = null;
|
||||
let bgImageBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
@@ -80,7 +80,7 @@ registerAiJobHandler("blur-background", async (input, data, ctx) => {
|
||||
|
||||
export function registerBlurBackground(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/blur-background",
|
||||
"/api/v1/tools/image/blur-background",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "blur-background";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
|
||||
@@ -65,7 +65,7 @@ registerAiJobHandler("blur-faces", async (input, data, ctx) => {
|
||||
|
||||
/** Face detection and blurring route. */
|
||||
export function registerBlurFaces(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/blur-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/blur-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "blur-faces";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -17,7 +17,7 @@ const settingsSchema = z.object({
|
||||
* No image processing - just renames.
|
||||
*/
|
||||
export function registerBulkRename(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/bulk-rename", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/bulk-rename", async (request, reply) => {
|
||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
|
||||
@@ -421,7 +421,7 @@ function getAspectMultiplier(ar: string): number | null {
|
||||
// ── Route registration ────────────���─────────────────────────────────
|
||||
|
||||
export function registerCollage(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/collage", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/collage", async (request, reply) => {
|
||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ function extractColors(
|
||||
}
|
||||
|
||||
export function registerColorPalette(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/color-palette", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/color-palette", async (request, reply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
let rawSettings: string | undefined;
|
||||
|
||||
@@ -66,7 +66,7 @@ registerAiJobHandler("colorize", async (input, data, ctx) => {
|
||||
* with OpenCV DNN fallback.
|
||||
*/
|
||||
export function registerColorize(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/colorize", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/colorize", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "colorize";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { decompressSvgz, sanitizeSvg } from "../../lib/svg-sanitize.js";
|
||||
* Compare two images: compute a pixel-level diff and similarity score.
|
||||
*/
|
||||
export function registerCompare(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/compare", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/compare", async (request, reply) => {
|
||||
let bufferA: Buffer | null = null;
|
||||
let bufferB: Buffer | null = null;
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ const settingsSchema = z.object({
|
||||
});
|
||||
|
||||
export function registerCompose(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/compose", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/compose", async (request, reply) => {
|
||||
let baseBuffer: Buffer | null = null;
|
||||
let overlayBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
@@ -28,7 +28,7 @@ type Settings = z.infer<typeof settingsSchema>;
|
||||
/** Content-aware resize (seam carving via caire) route. */
|
||||
export function registerContentAwareResize(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/content-aware-resize",
|
||||
"/api/v1/tools/image/content-aware-resize",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
@@ -68,7 +68,7 @@ const BROWSER_PREVIEWABLE = new Set([
|
||||
export function registerEditMetadata(app: FastifyInstance) {
|
||||
// Inspect endpoint - returns parsed metadata via ExifTool
|
||||
app.post(
|
||||
"/api/v1/tools/edit-metadata/inspect",
|
||||
"/api/v1/tools/image/edit-metadata/inspect",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
@@ -109,7 +109,7 @@ export function registerEditMetadata(app: FastifyInstance) {
|
||||
);
|
||||
|
||||
// Edit endpoint - writes metadata in-place using ExifTool (no pixel re-encoding)
|
||||
app.post("/api/v1/tools/edit-metadata", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/edit-metadata", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
@@ -58,7 +58,7 @@ registerAiJobHandler("enhance-faces", async (input, data, ctx) => {
|
||||
|
||||
/** Face enhancement route using GFPGAN/CodeFormer. */
|
||||
export function registerEnhanceFaces(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/enhance-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/enhance-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "enhance-faces";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -33,7 +33,7 @@ const settingsSchema = z.object({
|
||||
* via getObjectBuffer(data.inputRefs[1]) inside the handler.
|
||||
*/
|
||||
export function registerEraseObject(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/erase-object", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/erase-object", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "erase-object";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -79,7 +79,7 @@ interface UploadedFile {
|
||||
}
|
||||
|
||||
export function registerFavicon(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/favicon", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/favicon", async (request, reply) => {
|
||||
const uploadedFiles: UploadedFile[] = [];
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ async function extractFileInfo(file: FileData): Promise<FileInfo> {
|
||||
}
|
||||
|
||||
export function registerFindDuplicates(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/find-duplicates", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/find-duplicates", async (request, reply) => {
|
||||
const files: FileData[] = [];
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ const settingsSchema = z.object({
|
||||
|
||||
export function registerGifTools(app: FastifyInstance) {
|
||||
// ── Metadata endpoint ───────────────────────────────────────────
|
||||
app.post("/api/v1/tools/gif-tools/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/gif-tools/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
|
||||
try {
|
||||
|
||||
@@ -34,7 +34,7 @@ const settingsSchema = z
|
||||
|
||||
export function registerHtmlToImage(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/html-to-image",
|
||||
"/api/v1/tools/image/html-to-image",
|
||||
{
|
||||
config: {
|
||||
rateLimit: { max: 120, timeWindow: "1 hour" },
|
||||
|
||||
@@ -110,7 +110,7 @@ export function registerImageEnhancement(app: FastifyInstance) {
|
||||
});
|
||||
|
||||
app.post(
|
||||
"/api/v1/tools/image-enhancement/analyze",
|
||||
"/api/v1/tools/image/image-enhancement/analyze",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
@@ -54,7 +54,7 @@ function detectMimeType(format: string): string {
|
||||
|
||||
export function registerImageToBase64(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/image-to-base64",
|
||||
"/api/v1/tools/image/image-to-base64",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||
let settings = {};
|
||||
|
||||
@@ -97,7 +97,7 @@ async function flattenAlpha(buf: Buffer): Promise<Buffer> {
|
||||
}
|
||||
|
||||
export function registerImageToPdf(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/image-to-pdf", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/image-to-pdf", async (request, reply) => {
|
||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ const execFileAsync = promisify(execFile);
|
||||
* Does NOT use createToolRoute since it doesn't produce a processed file.
|
||||
*/
|
||||
export function registerInfo(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ export function registerMemeGenerator(app: FastifyInstance) {
|
||||
},
|
||||
});
|
||||
|
||||
app.post("/api/v1/tools/meme-generator", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/meme-generator", async (request, reply) => {
|
||||
const contentTypeHeader = request.headers["content-type"] ?? "";
|
||||
const isMultipart = contentTypeHeader.includes("multipart/form-data");
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ registerAiJobHandler("noise-removal", async (input, data, ctx) => {
|
||||
* Uses the Python sidecar for multi-tier denoising.
|
||||
*/
|
||||
export function registerNoiseRemoval(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/noise-removal", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/noise-removal", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "noise-removal";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -57,7 +57,7 @@ registerAiJobHandler("ocr-pdf", async (input, data, ctx) => {
|
||||
});
|
||||
|
||||
export function registerOcrPdf(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/ocr-pdf", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/pdf/ocr-pdf", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "ocr-pdf";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -28,7 +28,7 @@ const settingsSchema = z.object({
|
||||
* Returns JSON with extracted text rather than an image.
|
||||
*/
|
||||
export function registerOcr(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/ocr", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/ocr", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "ocr";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -63,7 +63,7 @@ async function processImage(inputBuffer: Buffer, settings: Settings, filename: s
|
||||
export function registerOptimizeForWeb(app: FastifyInstance) {
|
||||
// Lightweight preview route for live parameter tuning
|
||||
app.post(
|
||||
"/api/v1/tools/optimize-for-web/preview",
|
||||
"/api/v1/tools/image/optimize-for-web/preview",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
@@ -131,7 +131,7 @@ async function generatePrintSheet(
|
||||
export function registerPassportPhoto(app: FastifyInstance) {
|
||||
// ── Phase 1: Analyze (face landmarks + bg removal) ────────────────
|
||||
app.post(
|
||||
"/api/v1/tools/passport-photo/analyze",
|
||||
"/api/v1/tools/image/passport-photo/analyze",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "passport-photo";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
@@ -310,7 +310,7 @@ export function registerPassportPhoto(app: FastifyInstance) {
|
||||
|
||||
// ── Base route: return 501 so generic callers don't get 404 ──────
|
||||
app.post(
|
||||
"/api/v1/tools/passport-photo",
|
||||
"/api/v1/tools/image/passport-photo",
|
||||
async (_request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "passport-photo";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
@@ -324,14 +324,14 @@ export function registerPassportPhoto(app: FastifyInstance) {
|
||||
});
|
||||
}
|
||||
return reply.status(400).send({
|
||||
error: "Use /api/v1/tools/passport-photo/analyze or /generate",
|
||||
error: "Use /api/v1/tools/image/passport-photo/analyze or /generate",
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// ── Phase 2: Generate (crop + resize + tile) ─────────────────────
|
||||
app.post(
|
||||
"/api/v1/tools/passport-photo/generate",
|
||||
"/api/v1/tools/image/passport-photo/generate",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const parseResult = generateSettingsSchema.safeParse(request.body);
|
||||
if (!parseResult.success) {
|
||||
|
||||
@@ -181,7 +181,7 @@ function isPdfBuffer(buf: Buffer): boolean {
|
||||
// ── Route registration ───────────────────────────────────────────
|
||||
export function registerPdfToImage(app: FastifyInstance) {
|
||||
// ── Info endpoint ────────────────────────────────────────────
|
||||
app.post("/api/v1/tools/pdf-to-image/info", async (request, reply) => {
|
||||
app.post("/api/v1/tools/pdf/pdf-to-image/info", async (request, reply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
try {
|
||||
const result = await readPdfFromParts(request);
|
||||
@@ -223,7 +223,7 @@ export function registerPdfToImage(app: FastifyInstance) {
|
||||
});
|
||||
|
||||
// ── Preview endpoint (thumbnails) ─────────────────────────────
|
||||
app.post("/api/v1/tools/pdf-to-image/preview", async (request, reply) => {
|
||||
app.post("/api/v1/tools/pdf/pdf-to-image/preview", async (request, reply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
try {
|
||||
const result = await readPdfFromParts(request);
|
||||
@@ -288,7 +288,7 @@ export function registerPdfToImage(app: FastifyInstance) {
|
||||
});
|
||||
|
||||
// ── Main processing endpoint ─────────────────────────────────
|
||||
app.post("/api/v1/tools/pdf-to-image", async (request, reply) => {
|
||||
app.post("/api/v1/tools/pdf/pdf-to-image", async (request, reply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ const settingsSchema = z.object({
|
||||
* images from text input, not from uploaded files.
|
||||
*/
|
||||
export function registerQrGenerate(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/qr-generate", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/qr-generate", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let body: unknown;
|
||||
try {
|
||||
body = request.body;
|
||||
|
||||
@@ -58,7 +58,7 @@ registerAiJobHandler("red-eye-removal", async (input, data, ctx) => {
|
||||
/** Red eye detection and removal route. */
|
||||
export function registerRedEyeRemoval(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/red-eye-removal",
|
||||
"/api/v1/tools/image/red-eye-removal",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "red-eye-removal";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
|
||||
@@ -92,7 +92,7 @@ registerAiJobHandler("remove-background", async (input, data, ctx) => {
|
||||
export function registerRemoveBackground(app: FastifyInstance) {
|
||||
// ── Phase 1: Background removal ──────────────────────────────────
|
||||
app.post(
|
||||
"/api/v1/tools/remove-background",
|
||||
"/api/v1/tools/image/remove-background",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "remove-background";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
@@ -229,7 +229,7 @@ export function registerRemoveBackground(app: FastifyInstance) {
|
||||
|
||||
// ── Phase 2: Effects-only (no AI re-run) ─────────────────────────
|
||||
app.post(
|
||||
"/api/v1/tools/remove-background/effects",
|
||||
"/api/v1/tools/image/remove-background/effects",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let settingsRaw: string | null = null;
|
||||
let bgImageBuffer: Buffer | null = null;
|
||||
|
||||
@@ -83,7 +83,7 @@ registerAiJobHandler("restore-photo", async (input, data, ctx) => {
|
||||
* optional colorization.
|
||||
*/
|
||||
export function registerRestorePhoto(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/restore-photo", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/restore-photo", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
if (!isToolInstalled("restore-photo")) {
|
||||
const bundle = getBundleForTool("restore-photo");
|
||||
return reply.status(501).send({
|
||||
|
||||
@@ -44,7 +44,7 @@ function resolveOutputFormat(
|
||||
}
|
||||
|
||||
export function registerSplit(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/split", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/split", async (request, reply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
@@ -44,7 +44,7 @@ interface PreparedImage {
|
||||
}
|
||||
|
||||
export function registerStitch(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/stitch", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/stitch", async (request, reply) => {
|
||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ function parseIccProfile(iccBuffer: Buffer): Record<string, string> {
|
||||
export function registerStripMetadata(app: FastifyInstance) {
|
||||
// Inspect endpoint — returns parsed metadata as JSON
|
||||
app.post(
|
||||
"/api/v1/tools/strip-metadata/inspect",
|
||||
"/api/v1/tools/image/strip-metadata/inspect",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
@@ -105,7 +105,7 @@ async function convertSvg(
|
||||
*/
|
||||
export function registerSvgToRaster(app: FastifyInstance) {
|
||||
// --- Batch endpoint (registered first for route priority) ---
|
||||
app.post("/api/v1/tools/svg-to-raster/batch", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/svg-to-raster/batch", async (request, reply) => {
|
||||
const files: ParsedSvgFile[] = [];
|
||||
let settingsRaw: string | null = null;
|
||||
let clientJobId: string | null = null;
|
||||
@@ -347,7 +347,7 @@ export function registerSvgToRaster(app: FastifyInstance) {
|
||||
});
|
||||
|
||||
// --- Single-file endpoint ---
|
||||
app.post("/api/v1/tools/svg-to-raster", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/svg-to-raster", async (request, reply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "output";
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
@@ -79,7 +79,7 @@ registerAiJobHandler("transcribe-audio", async (input, data, ctx) => {
|
||||
|
||||
export function registerTranscribeAudio(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/transcribe-audio",
|
||||
"/api/v1/tools/audio/transcribe-audio",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "transcribe-audio";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
|
||||
@@ -152,7 +152,7 @@ registerAiJobHandler("transparency-fixer", async (input, data, ctx) => {
|
||||
|
||||
export function registerTransparencyFixer(app: FastifyInstance) {
|
||||
app.post(
|
||||
"/api/v1/tools/transparency-fixer",
|
||||
"/api/v1/tools/image/transparency-fixer",
|
||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
if (!isToolInstalled(TOOL_ID)) {
|
||||
const bundle = getBundleForTool(TOOL_ID);
|
||||
|
||||
@@ -116,7 +116,7 @@ registerAiJobHandler("upscale", async (input, data, ctx) => {
|
||||
* Uses Real-ESRGAN when available, falls back to Lanczos.
|
||||
*/
|
||||
export function registerUpscale(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/upscale", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
app.post("/api/v1/tools/image/upscale", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
const toolId = "upscale";
|
||||
if (!isToolInstalled(toolId)) {
|
||||
const bundle = getBundleForTool(toolId);
|
||||
|
||||
@@ -98,7 +98,7 @@ async function vectorizeBuffer(
|
||||
}
|
||||
|
||||
export function registerVectorize(app: FastifyInstance) {
|
||||
app.post("/api/v1/tools/vectorize", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/vectorize", async (request, reply) => {
|
||||
let fileBuffer: Buffer | null = null;
|
||||
let filename = "output";
|
||||
let settingsRaw: string | null = null;
|
||||
|
||||
@@ -21,7 +21,7 @@ const settingsSchema = z.object({
|
||||
|
||||
export function registerWatermarkImage(app: FastifyInstance) {
|
||||
// Custom route since we need two file uploads
|
||||
app.post("/api/v1/tools/watermark-image", async (request, reply) => {
|
||||
app.post("/api/v1/tools/image/watermark-image", async (request, reply) => {
|
||||
let mainBuffer: Buffer | null = null;
|
||||
let watermarkBuffer: Buffer | null = null;
|
||||
let filename = "image";
|
||||
|
||||
@@ -66,8 +66,8 @@ export default defineConfig({
|
||||
|
||||
- Base URL: \`http://localhost:1349\`
|
||||
- Auth: Session token via \`POST /api/auth/login\` or API key (\`Authorization: Bearer si_...\`)
|
||||
- Tools: \`POST /api/v1/tools/{toolId}\` (multipart: file + settings JSON)
|
||||
- Batch: \`POST /api/v1/tools/{toolId}/batch\` (multiple files, returns ZIP)
|
||||
- Tools: \`POST /api/v1/tools/{section}/{toolId}\` (multipart: file + settings JSON)
|
||||
- Batch: \`POST /api/v1/tools/{section}/{toolId}/batch\` (multiple files, returns ZIP)
|
||||
- Pipelines: \`POST /api/v1/pipeline/execute\` (chain tools sequentially)
|
||||
- Interactive API docs on running instance: \`/api/docs\`
|
||||
- OpenAPI spec on running instance: \`/api/v1/openapi.yaml\`
|
||||
@@ -294,18 +294,13 @@ export default defineConfig({
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "PDF & Documents",
|
||||
text: "PDF",
|
||||
items: [
|
||||
{ text: "PDF to Image", link: "/tools/pdf/pdf-to-image" },
|
||||
{ text: "Merge PDFs", link: "/tools/pdf/merge-pdf" },
|
||||
{ text: "Split PDF", link: "/tools/pdf/split-pdf" },
|
||||
{ text: "Compress PDF", link: "/tools/pdf/compress-pdf" },
|
||||
{ text: "Rotate PDF", link: "/tools/pdf/rotate-pdf" },
|
||||
{ text: "Convert Document", link: "/tools/pdf/convert-document" },
|
||||
{ text: "Convert Presentation", link: "/tools/pdf/convert-presentation" },
|
||||
{ text: "Convert Spreadsheet", link: "/tools/pdf/convert-spreadsheet" },
|
||||
{ text: "Excel to PDF", link: "/tools/pdf/excel-to-pdf" },
|
||||
{ text: "Word to PDF", link: "/tools/pdf/word-to-pdf" },
|
||||
{ text: "Extract Pages", link: "/tools/pdf/extract-pages" },
|
||||
{ text: "Remove Pages", link: "/tools/pdf/remove-pages" },
|
||||
{ text: "Organize PDF", link: "/tools/pdf/organize-pdf" },
|
||||
@@ -325,29 +320,34 @@ export default defineConfig({
|
||||
{ text: "PDF to Text", link: "/tools/pdf/pdf-to-text" },
|
||||
{ text: "PDF to Word", link: "/tools/pdf/pdf-to-word" },
|
||||
{ text: "PDF Metadata", link: "/tools/pdf/pdf-metadata" },
|
||||
{ text: "PowerPoint to PDF", link: "/tools/pdf/powerpoint-to-pdf" },
|
||||
{ text: "HTML to PDF", link: "/tools/pdf/html-to-pdf" },
|
||||
{ text: "Markdown to Word", link: "/tools/pdf/markdown-to-docx" },
|
||||
{ text: "Markdown to HTML", link: "/tools/pdf/markdown-to-html" },
|
||||
{ text: "Markdown to PDF", link: "/tools/pdf/markdown-to-pdf" },
|
||||
{ text: "Convert EPUB", link: "/tools/pdf/epub-convert" },
|
||||
{ text: "Convert to EPUB", link: "/tools/pdf/to-epub" },
|
||||
{ text: "PDF OCR", link: "/tools/pdf/ocr-pdf" },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Data",
|
||||
text: "Files",
|
||||
items: [
|
||||
{ text: "Chart Maker", link: "/tools/data/chart-maker" },
|
||||
{ text: "CSV to Excel", link: "/tools/data/csv-excel" },
|
||||
{ text: "CSV to JSON", link: "/tools/data/csv-json" },
|
||||
{ text: "JSON to XML", link: "/tools/data/json-xml" },
|
||||
{ text: "Split CSV", link: "/tools/data/split-csv" },
|
||||
{ text: "Merge CSVs", link: "/tools/data/merge-csvs" },
|
||||
{ text: "YAML / JSON", link: "/tools/data/yaml-json" },
|
||||
{ text: "XML to CSV", link: "/tools/data/xml-to-csv" },
|
||||
{ text: "Create ZIP", link: "/tools/data/create-zip" },
|
||||
{ text: "Extract ZIP", link: "/tools/data/extract-zip" },
|
||||
{ text: "Convert Document", link: "/tools/files/convert-document" },
|
||||
{ text: "Convert Presentation", link: "/tools/files/convert-presentation" },
|
||||
{ text: "Convert Spreadsheet", link: "/tools/files/convert-spreadsheet" },
|
||||
{ text: "Excel to PDF", link: "/tools/files/excel-to-pdf" },
|
||||
{ text: "Word to PDF", link: "/tools/files/word-to-pdf" },
|
||||
{ text: "PowerPoint to PDF", link: "/tools/files/powerpoint-to-pdf" },
|
||||
{ text: "HTML to PDF", link: "/tools/files/html-to-pdf" },
|
||||
{ text: "Markdown to Word", link: "/tools/files/markdown-to-docx" },
|
||||
{ text: "Markdown to HTML", link: "/tools/files/markdown-to-html" },
|
||||
{ text: "Markdown to PDF", link: "/tools/files/markdown-to-pdf" },
|
||||
{ text: "Convert EPUB", link: "/tools/files/epub-convert" },
|
||||
{ text: "Convert to EPUB", link: "/tools/files/to-epub" },
|
||||
{ text: "Chart Maker", link: "/tools/files/chart-maker" },
|
||||
{ text: "CSV to Excel", link: "/tools/files/csv-excel" },
|
||||
{ text: "CSV to JSON", link: "/tools/files/csv-json" },
|
||||
{ text: "JSON to XML", link: "/tools/files/json-xml" },
|
||||
{ text: "Split CSV", link: "/tools/files/split-csv" },
|
||||
{ text: "Merge CSVs", link: "/tools/files/merge-csvs" },
|
||||
{ text: "YAML / JSON", link: "/tools/files/yaml-json" },
|
||||
{ text: "XML to CSV", link: "/tools/files/xml-to-csv" },
|
||||
{ text: "Create ZIP", link: "/tools/files/create-zip" },
|
||||
{ text: "Extract ZIP", link: "/tools/files/extract-zip" },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
+4
-4
@@ -235,13 +235,13 @@ Two-phase workflow: analyze (detect face + remove background) then generate (cro
|
||||
|
||||
### Phase 1: Analyze
|
||||
|
||||
`POST /api/v1/tools/passport-photo/analyze`
|
||||
`POST /api/v1/tools/image/passport-photo/analyze`
|
||||
|
||||
Accepts an image file (multipart). Returns face landmark data, a base64 preview, and image dimensions.
|
||||
|
||||
### Phase 2: Generate
|
||||
|
||||
`POST /api/v1/tools/passport-photo/generate`
|
||||
`POST /api/v1/tools/image/passport-photo/generate`
|
||||
|
||||
Accepts a JSON body with the Phase 1 results plus generation settings:
|
||||
|
||||
@@ -370,7 +370,7 @@ Fixes "fake transparent" PNGs where the background was removed but left behind f
|
||||
| `removeWatermark` | boolean | `false` | Apply watermark removal pre-processing (median filter) |
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/transparency-fixer \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/transparency-fixer \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-F "file=@fake-transparent.png" \
|
||||
-F 'settings={"defringe":30,"outputFormat":"png"}'
|
||||
@@ -401,7 +401,7 @@ Analyzes the image and applies automatic corrections for exposure, contrast, whi
|
||||
| `corrections.denoise` | boolean | `true` | Apply denoising |
|
||||
| `deepEnhance` | boolean | `false` | Enable AI noise removal via SCUNet (requires `upscale-enhance` bundle) |
|
||||
|
||||
An additional analysis endpoint is available at `POST /api/v1/tools/image-enhancement/analyze` which returns the detected corrections without applying them.
|
||||
An additional analysis endpoint is available at `POST /api/v1/tools/image/image-enhancement/analyze` which returns the detected corrections without applying them.
|
||||
|
||||
### Content-Aware Resize (Seam Carving)
|
||||
|
||||
|
||||
+21
-19
@@ -25,7 +25,7 @@ curl -X POST http://localhost:1349/api/auth/login \
|
||||
# Returns: {"token":"<session-token>"}
|
||||
|
||||
# Use token
|
||||
curl http://localhost:1349/api/v1/tools/resize \
|
||||
curl http://localhost:1349/api/v1/tools/image/resize \
|
||||
-H "Authorization: Bearer <session-token>"
|
||||
```
|
||||
|
||||
@@ -42,7 +42,7 @@ curl -X POST http://localhost:1349/api/v1/api-keys \
|
||||
# Returns: {"key":"si_<96 hex chars>","id":"...","name":"my-script"}
|
||||
|
||||
# Use the key
|
||||
curl http://localhost:1349/api/v1/tools/resize \
|
||||
curl http://localhost:1349/api/v1/tools/image/resize \
|
||||
-H "Authorization: Bearer si_<your-key>"
|
||||
```
|
||||
|
||||
@@ -87,19 +87,21 @@ Every tool follows the same pattern:
|
||||
|
||||
```bash
|
||||
# Single file
|
||||
curl -X POST http://localhost:1349/api/v1/tools/<toolId> \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/<section>/<toolId> \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-F "file=@input.jpg" \
|
||||
-F 'settings={"width":800,"height":600}'
|
||||
|
||||
# Batch (returns ZIP)
|
||||
curl -X POST http://localhost:1349/api/v1/tools/<toolId>/batch \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/<section>/<toolId>/batch \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-F "files=@a.jpg" \
|
||||
-F "files=@b.jpg" \
|
||||
-F 'settings={...}'
|
||||
```
|
||||
|
||||
`<section>` is one of `image`, `video`, `audio`, `pdf`, or `files`.
|
||||
|
||||
- Upload is `multipart/form-data`.
|
||||
- `settings` is a JSON string with tool-specific options.
|
||||
- **Fast tools** (200) return JSON: `{"jobId":"...","downloadUrl":"/api/v1/download/<jobId>/<filename>","originalSize":1234,"processedSize":567}`. Fetch the processed file from `downloadUrl`.
|
||||
@@ -331,7 +333,7 @@ All AI tools run on your hardware (CPU or NVIDIA GPU). No internet required.
|
||||
|
||||
Capture a webpage as an image. Unlike other tools, this endpoint accepts `application/json` instead of multipart form data (no file upload needed).
|
||||
|
||||
**Endpoint:** `POST /api/v1/tools/html-to-image`
|
||||
**Endpoint:** `POST /api/v1/tools/image/html-to-image`
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
@@ -348,7 +350,7 @@ Capture a webpage as an image. Unlike other tools, this endpoint accepts `applic
|
||||
**Example:**
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/html-to-image \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/html-to-image \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"url": "https://snapotter.com", "format": "png", "devicePreset": "desktop"}'
|
||||
@@ -367,28 +369,28 @@ curl -X POST http://localhost:1349/api/v1/tools/html-to-image \
|
||||
|
||||
### Tool Sub-Routes
|
||||
|
||||
Some tools expose additional endpoints beyond the standard `POST /api/v1/tools/<toolId>`:
|
||||
Some tools expose additional endpoints beyond the standard `POST /api/v1/tools/<section>/<toolId>`:
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/api/v1/tools/remove-background/effects` | Apply background effects (color/gradient/blur/shadow) without re-running AI. Uses cached mask from initial removal. |
|
||||
| `POST` | `/api/v1/tools/edit-metadata/inspect` | Read existing EXIF/IPTC/XMP metadata from an image |
|
||||
| `POST` | `/api/v1/tools/strip-metadata/inspect` | Inspect metadata fields before stripping |
|
||||
| `POST` | `/api/v1/tools/passport-photo/analyze` | Phase 1: AI face detection + background removal. Returns face landmarks and cached data. |
|
||||
| `POST` | `/api/v1/tools/passport-photo/generate` | Phase 2: Crop, resize, and tile using cached analysis. No AI re-run. |
|
||||
| `POST` | `/api/v1/tools/gif-tools/info` | Get GIF metadata (frame count, dimensions, duration) |
|
||||
| `POST` | `/api/v1/tools/pdf-to-image/info` | Get PDF metadata (page count, dimensions) |
|
||||
| `POST` | `/api/v1/tools/pdf-to-image/preview` | Generate a preview of a specific PDF page |
|
||||
| `POST` | `/api/v1/tools/svg-to-raster/batch` | Batch convert multiple SVGs to raster |
|
||||
| `POST` | `/api/v1/tools/image-enhancement/analyze` | Analyze image quality and return enhancement recommendations |
|
||||
| `POST` | `/api/v1/tools/optimize-for-web/preview` | Lightweight preview for live parameter tuning. Returns optimized image with size headers. |
|
||||
| `POST` | `/api/v1/tools/image/remove-background/effects` | Apply background effects (color/gradient/blur/shadow) without re-running AI. Uses cached mask from initial removal. |
|
||||
| `POST` | `/api/v1/tools/image/edit-metadata/inspect` | Read existing EXIF/IPTC/XMP metadata from an image |
|
||||
| `POST` | `/api/v1/tools/image/strip-metadata/inspect` | Inspect metadata fields before stripping |
|
||||
| `POST` | `/api/v1/tools/image/passport-photo/analyze` | Phase 1: AI face detection + background removal. Returns face landmarks and cached data. |
|
||||
| `POST` | `/api/v1/tools/image/passport-photo/generate` | Phase 2: Crop, resize, and tile using cached analysis. No AI re-run. |
|
||||
| `POST` | `/api/v1/tools/image/gif-tools/info` | Get GIF metadata (frame count, dimensions, duration) |
|
||||
| `POST` | `/api/v1/tools/pdf/pdf-to-image/info` | Get PDF metadata (page count, dimensions) |
|
||||
| `POST` | `/api/v1/tools/pdf/pdf-to-image/preview` | Generate a preview of a specific PDF page |
|
||||
| `POST` | `/api/v1/tools/image/svg-to-raster/batch` | Batch convert multiple SVGs to raster |
|
||||
| `POST` | `/api/v1/tools/image/image-enhancement/analyze` | Analyze image quality and return enhancement recommendations |
|
||||
| `POST` | `/api/v1/tools/image/optimize-for-web/preview` | Lightweight preview for live parameter tuning. Returns optimized image with size headers. |
|
||||
|
||||
## Batch Processing
|
||||
|
||||
Apply any tool to multiple files at once. Returns a ZIP archive.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/compress/batch \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/compress/batch \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-F "files=@a.jpg" \
|
||||
-F "files=@b.jpg" \
|
||||
|
||||
@@ -81,7 +81,7 @@ This VitePress site. Deployed to Cloudflare Pages automatically on push to `main
|
||||
## How a request flows
|
||||
|
||||
1. The user picks a tool in the web UI and uploads a file.
|
||||
2. The frontend sends a multipart POST to `/api/v1/tools/:toolId` with the file and settings.
|
||||
2. The frontend sends a multipart POST to `/api/v1/tools/:section/:toolId` with the file and settings.
|
||||
3. The API route validates the input with Zod, then dispatches processing.
|
||||
4. For standard tools, the job is enqueued to the appropriate BullMQ pool (image, media, or docs based on modality). The in-process BullMQ worker auto-orients the image based on EXIF metadata, runs the tool's process function, and returns the result.
|
||||
5. For AI tools, the TypeScript bridge sends a request to the persistent Python dispatcher (or spawns a fresh subprocess as fallback), waits for it to finish, and reads the output file.
|
||||
|
||||
@@ -139,7 +139,7 @@ Every file you process can be saved to your **Files** library. SnapOtter tracks
|
||||
Every tool is accessible via HTTP:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/resize \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/resize \
|
||||
-H "Authorization: Bearer si_<your-api-key>" \
|
||||
-F "file=@photo.jpg" \
|
||||
-F 'settings={"width":800,"height":600,"fit":"cover"}'
|
||||
|
||||
+44
-44
@@ -36,8 +36,8 @@
|
||||
/tools/burn-subtitles.html /tools/video/burn-subtitles 301
|
||||
/tools/change-fps /tools/video/change-fps 301
|
||||
/tools/change-fps.html /tools/video/change-fps 301
|
||||
/tools/chart-maker /tools/data/chart-maker 301
|
||||
/tools/chart-maker.html /tools/data/chart-maker 301
|
||||
/tools/chart-maker /tools/files/chart-maker 301
|
||||
/tools/chart-maker.html /tools/files/chart-maker 301
|
||||
/tools/circle-crop /tools/image/circle-crop 301
|
||||
/tools/circle-crop.html /tools/image/circle-crop 301
|
||||
/tools/collage /tools/image/collage 301
|
||||
@@ -63,27 +63,27 @@
|
||||
/tools/convert /tools/image/convert 301
|
||||
/tools/convert-audio /tools/audio/convert-audio 301
|
||||
/tools/convert-audio.html /tools/audio/convert-audio 301
|
||||
/tools/convert-document /tools/pdf/convert-document 301
|
||||
/tools/convert-document.html /tools/pdf/convert-document 301
|
||||
/tools/convert-presentation /tools/pdf/convert-presentation 301
|
||||
/tools/convert-presentation.html /tools/pdf/convert-presentation 301
|
||||
/tools/convert-spreadsheet /tools/pdf/convert-spreadsheet 301
|
||||
/tools/convert-spreadsheet.html /tools/pdf/convert-spreadsheet 301
|
||||
/tools/convert-document /tools/files/convert-document 301
|
||||
/tools/convert-document.html /tools/files/convert-document 301
|
||||
/tools/convert-presentation /tools/files/convert-presentation 301
|
||||
/tools/convert-presentation.html /tools/files/convert-presentation 301
|
||||
/tools/convert-spreadsheet /tools/files/convert-spreadsheet 301
|
||||
/tools/convert-spreadsheet.html /tools/files/convert-spreadsheet 301
|
||||
/tools/convert-video /tools/video/convert-video 301
|
||||
/tools/convert-video.html /tools/video/convert-video 301
|
||||
/tools/convert.html /tools/image/convert 301
|
||||
/tools/create-zip /tools/data/create-zip 301
|
||||
/tools/create-zip.html /tools/data/create-zip 301
|
||||
/tools/create-zip /tools/files/create-zip 301
|
||||
/tools/create-zip.html /tools/files/create-zip 301
|
||||
/tools/crop /tools/image/crop 301
|
||||
/tools/crop-pdf /tools/pdf/crop-pdf 301
|
||||
/tools/crop-pdf.html /tools/pdf/crop-pdf 301
|
||||
/tools/crop-video /tools/video/crop-video 301
|
||||
/tools/crop-video.html /tools/video/crop-video 301
|
||||
/tools/crop.html /tools/image/crop 301
|
||||
/tools/csv-excel /tools/data/csv-excel 301
|
||||
/tools/csv-excel.html /tools/data/csv-excel 301
|
||||
/tools/csv-json /tools/data/csv-json 301
|
||||
/tools/csv-json.html /tools/data/csv-json 301
|
||||
/tools/csv-excel /tools/files/csv-excel 301
|
||||
/tools/csv-excel.html /tools/files/csv-excel 301
|
||||
/tools/csv-json /tools/files/csv-json 301
|
||||
/tools/csv-json.html /tools/files/csv-json 301
|
||||
/tools/duotone /tools/image/duotone 301
|
||||
/tools/duotone.html /tools/image/duotone 301
|
||||
/tools/edit-metadata /tools/image/edit-metadata 301
|
||||
@@ -92,20 +92,20 @@
|
||||
/tools/embed-subtitles.html /tools/video/embed-subtitles 301
|
||||
/tools/enhance-faces /tools/image/enhance-faces 301
|
||||
/tools/enhance-faces.html /tools/image/enhance-faces 301
|
||||
/tools/epub-convert /tools/pdf/epub-convert 301
|
||||
/tools/epub-convert.html /tools/pdf/epub-convert 301
|
||||
/tools/epub-convert /tools/files/epub-convert 301
|
||||
/tools/epub-convert.html /tools/files/epub-convert 301
|
||||
/tools/erase-object /tools/image/erase-object 301
|
||||
/tools/erase-object.html /tools/image/erase-object 301
|
||||
/tools/excel-to-pdf /tools/pdf/excel-to-pdf 301
|
||||
/tools/excel-to-pdf.html /tools/pdf/excel-to-pdf 301
|
||||
/tools/excel-to-pdf /tools/files/excel-to-pdf 301
|
||||
/tools/excel-to-pdf.html /tools/files/excel-to-pdf 301
|
||||
/tools/extract-audio /tools/video/extract-audio 301
|
||||
/tools/extract-audio.html /tools/video/extract-audio 301
|
||||
/tools/extract-pages /tools/pdf/extract-pages 301
|
||||
/tools/extract-pages.html /tools/pdf/extract-pages 301
|
||||
/tools/extract-subtitles /tools/video/extract-subtitles 301
|
||||
/tools/extract-subtitles.html /tools/video/extract-subtitles 301
|
||||
/tools/extract-zip /tools/data/extract-zip 301
|
||||
/tools/extract-zip.html /tools/data/extract-zip 301
|
||||
/tools/extract-zip /tools/files/extract-zip 301
|
||||
/tools/extract-zip.html /tools/files/extract-zip 301
|
||||
/tools/fade-audio /tools/audio/fade-audio 301
|
||||
/tools/fade-audio.html /tools/audio/fade-audio 301
|
||||
/tools/favicon /tools/image/favicon 301
|
||||
@@ -126,8 +126,8 @@
|
||||
/tools/histogram.html /tools/image/histogram 301
|
||||
/tools/html-to-image /tools/image/html-to-image 301
|
||||
/tools/html-to-image.html /tools/image/html-to-image 301
|
||||
/tools/html-to-pdf /tools/pdf/html-to-pdf 301
|
||||
/tools/html-to-pdf.html /tools/pdf/html-to-pdf 301
|
||||
/tools/html-to-pdf /tools/files/html-to-pdf 301
|
||||
/tools/html-to-pdf.html /tools/files/html-to-pdf 301
|
||||
/tools/image-enhancement /tools/image/image-enhancement 301
|
||||
/tools/image-enhancement.html /tools/image/image-enhancement 301
|
||||
/tools/image-pad /tools/image/image-pad 301
|
||||
@@ -140,24 +140,24 @@
|
||||
/tools/images-to-video.html /tools/video/images-to-video 301
|
||||
/tools/info /tools/image/info 301
|
||||
/tools/info.html /tools/image/info 301
|
||||
/tools/json-xml /tools/data/json-xml 301
|
||||
/tools/json-xml.html /tools/data/json-xml 301
|
||||
/tools/json-xml /tools/files/json-xml 301
|
||||
/tools/json-xml.html /tools/files/json-xml 301
|
||||
/tools/linearize-pdf /tools/pdf/linearize-pdf 301
|
||||
/tools/linearize-pdf.html /tools/pdf/linearize-pdf 301
|
||||
/tools/lqip-placeholder /tools/image/lqip-placeholder 301
|
||||
/tools/lqip-placeholder.html /tools/image/lqip-placeholder 301
|
||||
/tools/markdown-to-docx /tools/pdf/markdown-to-docx 301
|
||||
/tools/markdown-to-docx.html /tools/pdf/markdown-to-docx 301
|
||||
/tools/markdown-to-html /tools/pdf/markdown-to-html 301
|
||||
/tools/markdown-to-html.html /tools/pdf/markdown-to-html 301
|
||||
/tools/markdown-to-pdf /tools/pdf/markdown-to-pdf 301
|
||||
/tools/markdown-to-pdf.html /tools/pdf/markdown-to-pdf 301
|
||||
/tools/markdown-to-docx /tools/files/markdown-to-docx 301
|
||||
/tools/markdown-to-docx.html /tools/files/markdown-to-docx 301
|
||||
/tools/markdown-to-html /tools/files/markdown-to-html 301
|
||||
/tools/markdown-to-html.html /tools/files/markdown-to-html 301
|
||||
/tools/markdown-to-pdf /tools/files/markdown-to-pdf 301
|
||||
/tools/markdown-to-pdf.html /tools/files/markdown-to-pdf 301
|
||||
/tools/meme-generator /tools/image/meme-generator 301
|
||||
/tools/meme-generator.html /tools/image/meme-generator 301
|
||||
/tools/merge-audio /tools/audio/merge-audio 301
|
||||
/tools/merge-audio.html /tools/audio/merge-audio 301
|
||||
/tools/merge-csvs /tools/data/merge-csvs 301
|
||||
/tools/merge-csvs.html /tools/data/merge-csvs 301
|
||||
/tools/merge-csvs /tools/files/merge-csvs 301
|
||||
/tools/merge-csvs.html /tools/files/merge-csvs 301
|
||||
/tools/merge-pdf /tools/pdf/merge-pdf 301
|
||||
/tools/merge-pdf.html /tools/pdf/merge-pdf 301
|
||||
/tools/merge-videos /tools/video/merge-videos 301
|
||||
@@ -198,8 +198,8 @@
|
||||
/tools/pitch-shift.html /tools/audio/pitch-shift 301
|
||||
/tools/pixelate /tools/image/pixelate 301
|
||||
/tools/pixelate.html /tools/image/pixelate 301
|
||||
/tools/powerpoint-to-pdf /tools/pdf/powerpoint-to-pdf 301
|
||||
/tools/powerpoint-to-pdf.html /tools/pdf/powerpoint-to-pdf 301
|
||||
/tools/powerpoint-to-pdf /tools/files/powerpoint-to-pdf 301
|
||||
/tools/powerpoint-to-pdf.html /tools/files/powerpoint-to-pdf 301
|
||||
/tools/protect-pdf /tools/pdf/protect-pdf 301
|
||||
/tools/protect-pdf.html /tools/pdf/protect-pdf 301
|
||||
/tools/qr-generate /tools/image/qr-generate 301
|
||||
@@ -245,8 +245,8 @@
|
||||
/tools/split /tools/image/split 301
|
||||
/tools/split-audio /tools/audio/split-audio 301
|
||||
/tools/split-audio.html /tools/audio/split-audio 301
|
||||
/tools/split-csv /tools/data/split-csv 301
|
||||
/tools/split-csv.html /tools/data/split-csv 301
|
||||
/tools/split-csv /tools/files/split-csv 301
|
||||
/tools/split-csv.html /tools/files/split-csv 301
|
||||
/tools/split-pdf /tools/pdf/split-pdf 301
|
||||
/tools/split-pdf.html /tools/pdf/split-pdf 301
|
||||
/tools/split.html /tools/image/split 301
|
||||
@@ -262,8 +262,8 @@
|
||||
/tools/svg-to-raster.html /tools/image/svg-to-raster 301
|
||||
/tools/text-overlay /tools/image/text-overlay 301
|
||||
/tools/text-overlay.html /tools/image/text-overlay 301
|
||||
/tools/to-epub /tools/pdf/to-epub 301
|
||||
/tools/to-epub.html /tools/pdf/to-epub 301
|
||||
/tools/to-epub /tools/files/to-epub 301
|
||||
/tools/to-epub.html /tools/files/to-epub 301
|
||||
/tools/transcribe-audio /tools/audio/transcribe-audio 301
|
||||
/tools/transcribe-audio.html /tools/audio/transcribe-audio 301
|
||||
/tools/transparency-fixer /tools/image/transparency-fixer 301
|
||||
@@ -306,9 +306,9 @@
|
||||
/tools/watermark-video.html /tools/video/watermark-video 301
|
||||
/tools/waveform-image /tools/audio/waveform-image 301
|
||||
/tools/waveform-image.html /tools/audio/waveform-image 301
|
||||
/tools/word-to-pdf /tools/pdf/word-to-pdf 301
|
||||
/tools/word-to-pdf.html /tools/pdf/word-to-pdf 301
|
||||
/tools/xml-to-csv /tools/data/xml-to-csv 301
|
||||
/tools/xml-to-csv.html /tools/data/xml-to-csv 301
|
||||
/tools/yaml-json /tools/data/yaml-json 301
|
||||
/tools/yaml-json.html /tools/data/yaml-json 301
|
||||
/tools/word-to-pdf /tools/files/word-to-pdf 301
|
||||
/tools/word-to-pdf.html /tools/files/word-to-pdf 301
|
||||
/tools/xml-to-csv /tools/files/xml-to-csv 301
|
||||
/tools/xml-to-csv.html /tools/files/xml-to-csv 301
|
||||
/tools/yaml-json /tools/files/yaml-json 301
|
||||
/tools/yaml-json.html /tools/files/yaml-json 301
|
||||
|
||||
@@ -8,7 +8,7 @@ Convert audio between mono and stereo layouts, or swap the left and right channe
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/audio-channels`
|
||||
`POST /api/v1/tools/audio/audio-channels`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio-channels \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/audio-channels \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"mode": "stereo-to-mono"}'
|
||||
|
||||
@@ -8,7 +8,7 @@ View, edit, or strip audio metadata tags such as title, artist, and album (ID3 a
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/audio-metadata`
|
||||
`POST /api/v1/tools/audio/audio-metadata`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -26,7 +26,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
Edit metadata tags:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio-metadata \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/audio-metadata \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"title": "My Song", "artist": "Artist Name", "album": "Album Name"}'
|
||||
@@ -35,7 +35,7 @@ curl -X POST http://localhost:1349/api/v1/tools/audio-metadata \
|
||||
Strip all metadata:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio-metadata \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/audio-metadata \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"strip": true}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Speed up or slow down audio playback by applying a speed multiplier.
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/audio-speed`
|
||||
`POST /api/v1/tools/audio/audio-speed`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio-speed \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/audio-speed \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"factor": 2}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Convert audio files between common formats including MP3, WAV, OGG, FLAC, and M4
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/convert-audio`
|
||||
`POST /api/v1/tools/audio/convert-audio`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -22,7 +22,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/convert-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/convert-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"format": "flac", "bitrateKbps": 256}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Add fade-in and fade-out effects to the beginning and end of an audio file.
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/fade-audio`
|
||||
`POST /api/v1/tools/audio/fade-audio`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -22,7 +22,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/fade-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/fade-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"fadeInS": 2, "fadeOutS": 3}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Combine two or more audio files into a single sequential track, concatenated in
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/merge-audio`
|
||||
`POST /api/v1/tools/audio/merge-audio`
|
||||
|
||||
Accepts multipart form data with multiple audio files and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with multiple audio files and a JSON `settings` fiel
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/merge-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/merge-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@intro.mp3" \
|
||||
-F "file=@main.mp3" \
|
||||
|
||||
@@ -8,7 +8,7 @@ Reduce background noise in an audio file using FFT-based denoising with selectab
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/noise-reduction`
|
||||
`POST /api/v1/tools/audio/noise-reduction`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/noise-reduction \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/noise-reduction \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"strength": "strong"}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Even out audio loudness to broadcast standard levels using EBU R128 normalizatio
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/normalize-audio`
|
||||
`POST /api/v1/tools/audio/normalize-audio`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. It applies EBU R128 loudness normaliza
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/normalize-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/normalize-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3"
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ Raise or lower the pitch of an audio file by a number of semitones without chang
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/pitch-shift`
|
||||
`POST /api/v1/tools/audio/pitch-shift`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/pitch-shift \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/pitch-shift \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"semitones": -5}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Reverse an audio file so it plays backwards.
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/reverse-audio`
|
||||
`POST /api/v1/tools/audio/reverse-audio`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. The entire audio file is reversed.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/reverse-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/reverse-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3"
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ Create a ringtone clip (.m4r) from any audio file by selecting a start time and
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/ringtone-maker`
|
||||
`POST /api/v1/tools/audio/ringtone-maker`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -22,7 +22,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/ringtone-maker \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/ringtone-maker \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"startS": 15, "durationS": 20}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Detect and remove silent sections from an audio file based on a configurable thr
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/silence-removal`
|
||||
`POST /api/v1/tools/audio/silence-removal`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -22,7 +22,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/silence-removal \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/silence-removal \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"thresholdDb": -45, "minSilenceS": 1}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Split an audio file into segments by fixed time intervals, equal parts, or autom
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/split-audio`
|
||||
`POST /api/v1/tools/audio/split-audio`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -27,7 +27,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
Split into 30-second segments:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/split-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/split-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"mode": "time", "segmentS": 30}'
|
||||
@@ -36,7 +36,7 @@ curl -X POST http://localhost:1349/api/v1/tools/split-audio \
|
||||
Split by silence detection:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/split-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/split-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"mode": "silence", "thresholdDb": -35, "minSilenceS": 0.5}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Convert speech to text using AI-powered transcription (faster-whisper). Supports
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/transcribe-audio`
|
||||
`POST /api/v1/tools/audio/transcribe-audio`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -22,7 +22,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/transcribe-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/transcribe-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"language": "en", "outputFormat": "srt"}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Cut a section out of an audio file by specifying start and end times in seconds.
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/trim-audio`
|
||||
`POST /api/v1/tools/audio/trim-audio`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -22,7 +22,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/trim-audio \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/trim-audio \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"startS": 10, "endS": 45}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Increase or decrease the volume of an audio file by applying a fixed gain in dec
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/volume-adjust`
|
||||
`POST /api/v1/tools/audio/volume-adjust`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/volume-adjust \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/volume-adjust \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"gainDb": 6}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Generate a waveform visualization as a PNG image from an audio file, with config
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/waveform-image`
|
||||
`POST /api/v1/tools/audio/waveform-image`
|
||||
|
||||
Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
|
||||
@@ -23,7 +23,7 @@ Accepts multipart form data with an audio file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/waveform-image \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/audio/waveform-image \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@audio.mp3" \
|
||||
-F 'settings={"width": 1920, "height": 400, "color": "#e07832"}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Create bar, line, or pie charts from CSV or JSON data. Returns a PNG image of th
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/chart-maker`
|
||||
`POST /api/v1/tools/files/chart-maker`
|
||||
|
||||
Accepts multipart form data with a CSV or JSON file and a JSON `settings` field.
|
||||
|
||||
@@ -24,7 +24,7 @@ Accepts multipart form data with a CSV or JSON file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/chart-maker \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/chart-maker \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@sales.csv" \
|
||||
-F 'settings={"kind": "line", "title": "Monthly Sales", "width": 960, "height": 540}'
|
||||
@@ -8,7 +8,7 @@ Convert documents between Word (DOCX), OpenDocument (ODT), RTF, and plain text f
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/convert-document`
|
||||
`POST /api/v1/tools/files/convert-document`
|
||||
|
||||
Accepts multipart form data with a Word/ODT/RTF/TXT file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with a Word/ODT/RTF/TXT file and a JSON `settings` f
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/convert-document \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/convert-document \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@report.docx" \
|
||||
-F 'settings={"format": "odt"}'
|
||||
+2
-2
@@ -8,7 +8,7 @@ Convert presentations between PowerPoint (PPTX) and OpenDocument Presentation (O
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/convert-presentation`
|
||||
`POST /api/v1/tools/files/convert-presentation`
|
||||
|
||||
Accepts multipart form data with a PowerPoint/ODP file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with a PowerPoint/ODP file and a JSON `settings` fie
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/convert-presentation \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/convert-presentation \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@slides.pptx" \
|
||||
-F 'settings={"format": "odp"}'
|
||||
+2
-2
@@ -8,7 +8,7 @@ Convert spreadsheets between Excel (XLSX), OpenDocument Spreadsheet (ODS), and C
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/convert-spreadsheet`
|
||||
`POST /api/v1/tools/files/convert-spreadsheet`
|
||||
|
||||
Accepts multipart form data with an Excel/ODS/CSV file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an Excel/ODS/CSV file and a JSON `settings` fie
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/convert-spreadsheet \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/convert-spreadsheet \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@data.xlsx" \
|
||||
-F 'settings={"format": "csv"}'
|
||||
@@ -8,7 +8,7 @@ Bundle multiple files of any type into a single ZIP archive. Duplicate filenames
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/create-zip`
|
||||
`POST /api/v1/tools/files/create-zip`
|
||||
|
||||
Accepts multipart form data with two or more files. No settings field is required.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload 2--50 files of any type to bund
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/create-zip \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/create-zip \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@report.pdf" \
|
||||
-F "file=@data.csv" \
|
||||
@@ -8,7 +8,7 @@ Convert between CSV and Excel (XLSX) formats in both directions. Upload a CSV or
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/csv-excel`
|
||||
`POST /api/v1/tools/files/csv-excel`
|
||||
|
||||
Accepts multipart form data with a CSV, TSV, or XLSX file and a JSON `settings` field.
|
||||
|
||||
@@ -23,7 +23,7 @@ Accepts multipart form data with a CSV, TSV, or XLSX file and a JSON `settings`
|
||||
CSV to Excel:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/csv-excel \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/csv-excel \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@data.csv" \
|
||||
-F 'settings={"sheet": 1}'
|
||||
@@ -32,7 +32,7 @@ curl -X POST http://localhost:1349/api/v1/tools/csv-excel \
|
||||
Excel to CSV:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/csv-excel \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/csv-excel \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@report.xlsx" \
|
||||
-F 'settings={"sheet": 2}'
|
||||
@@ -8,7 +8,7 @@ Convert between CSV and JSON formats in both directions. Upload a CSV or TSV fil
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/csv-json`
|
||||
`POST /api/v1/tools/files/csv-json`
|
||||
|
||||
Accepts multipart form data with a CSV, TSV, or JSON file and a JSON `settings` field.
|
||||
|
||||
@@ -23,7 +23,7 @@ Accepts multipart form data with a CSV, TSV, or JSON file and a JSON `settings`
|
||||
CSV to JSON:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/csv-json \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/csv-json \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@users.csv" \
|
||||
-F 'settings={"pretty": true}'
|
||||
@@ -32,7 +32,7 @@ curl -X POST http://localhost:1349/api/v1/tools/csv-json \
|
||||
JSON to CSV:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/csv-json \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/csv-json \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@users.json" \
|
||||
-F 'settings={}'
|
||||
@@ -8,7 +8,7 @@ Convert an EPUB e-book to PDF, Word (DOCX), HTML, or Markdown. Remote resources
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/epub-convert`
|
||||
`POST /api/v1/tools/files/epub-convert`
|
||||
|
||||
Accepts multipart form data with an EPUB file and a JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an EPUB file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/epub-convert \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/epub-convert \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@book.epub" \
|
||||
-F 'settings={"format": "pdf"}'
|
||||
@@ -8,7 +8,7 @@ Convert Excel, OpenDocument, or CSV spreadsheets to PDF. Wide sheets may paginat
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/excel-to-pdf`
|
||||
`POST /api/v1/tools/files/excel-to-pdf`
|
||||
|
||||
Accepts multipart form data with an Excel/ODS/CSV file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a spreadsheet and it will be co
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/excel-to-pdf \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/excel-to-pdf \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@budget.xlsx"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Safely extract files from a ZIP archive. Single-file archives return the contain
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/extract-zip`
|
||||
`POST /api/v1/tools/files/extract-zip`
|
||||
|
||||
Accepts multipart form data with a ZIP file. No settings field is required.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a `.zip` file to extract.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/extract-zip \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/extract-zip \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@archive.zip"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Convert an HTML file to a styled PDF document. Remote resources (external images
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/html-to-pdf`
|
||||
`POST /api/v1/tools/files/html-to-pdf`
|
||||
|
||||
Accepts multipart form data with an HTML file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload an HTML file and it will be con
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/html-to-pdf \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/html-to-pdf \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@page.html"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Convert between JSON and XML formats in both directions. Upload a JSON file to g
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/json-xml`
|
||||
`POST /api/v1/tools/files/json-xml`
|
||||
|
||||
Accepts multipart form data with a JSON or XML file and a JSON `settings` field.
|
||||
|
||||
@@ -23,7 +23,7 @@ Accepts multipart form data with a JSON or XML file and a JSON `settings` field.
|
||||
JSON to XML:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/json-xml \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/json-xml \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@config.json" \
|
||||
-F 'settings={"pretty": true}'
|
||||
@@ -32,7 +32,7 @@ curl -X POST http://localhost:1349/api/v1/tools/json-xml \
|
||||
XML to JSON:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/json-xml \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/json-xml \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@config.xml" \
|
||||
-F 'settings={"pretty": true}'
|
||||
@@ -8,7 +8,7 @@ Convert a Markdown file to a Word document (DOCX), preserving headings, lists, c
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/markdown-to-docx`
|
||||
`POST /api/v1/tools/files/markdown-to-docx`
|
||||
|
||||
Accepts multipart form data with a Markdown file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a Markdown file and it will be
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/markdown-to-docx \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/markdown-to-docx \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@README.md"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Convert a Markdown file to a standalone HTML page. Remote images referenced in t
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/markdown-to-html`
|
||||
`POST /api/v1/tools/files/markdown-to-html`
|
||||
|
||||
Accepts multipart form data with a Markdown file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a Markdown file and it will be
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/markdown-to-html \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/markdown-to-html \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@notes.md"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Convert a Markdown file to a styled PDF document. Remote resources are disabled
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/markdown-to-pdf`
|
||||
`POST /api/v1/tools/files/markdown-to-pdf`
|
||||
|
||||
Accepts multipart form data with a Markdown file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a Markdown file and it will be
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/markdown-to-pdf \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/markdown-to-pdf \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@document.md"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Combine multiple CSV or TSV files with matching columns into a single merged fil
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/merge-csvs`
|
||||
`POST /api/v1/tools/files/merge-csvs`
|
||||
|
||||
Accepts multipart form data with two or more CSV files. No settings field is required.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload 2--20 CSV or TSV files with mat
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/merge-csvs \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/merge-csvs \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@january.csv" \
|
||||
-F "file=@february.csv" \
|
||||
+2
-2
@@ -8,7 +8,7 @@ Convert PowerPoint or OpenDocument presentations to PDF, with one slide per page
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/powerpoint-to-pdf`
|
||||
`POST /api/v1/tools/files/powerpoint-to-pdf`
|
||||
|
||||
Accepts multipart form data with a PowerPoint/ODP file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a presentation and it will be c
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/powerpoint-to-pdf \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/powerpoint-to-pdf \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@slides.pptx"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Split a large CSV or TSV file into smaller files by row count. Returns a ZIP arc
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/split-csv`
|
||||
`POST /api/v1/tools/files/split-csv`
|
||||
|
||||
Accepts multipart form data with a CSV file and a JSON `settings` field.
|
||||
|
||||
@@ -22,7 +22,7 @@ Accepts multipart form data with a CSV file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/split-csv \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/split-csv \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@large-dataset.csv" \
|
||||
-F 'settings={"rowsPerFile": 500, "keepHeader": true}'
|
||||
@@ -8,7 +8,7 @@ Convert Word documents, Markdown, HTML, or plain text files into the EPUB e-book
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/to-epub`
|
||||
`POST /api/v1/tools/files/to-epub`
|
||||
|
||||
Accepts multipart form data with a Word/Markdown/HTML/TXT file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a document and it will be conve
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/to-epub \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/to-epub \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@manuscript.docx"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Convert Word documents, OpenDocument text, RTF, or plain text files to PDF.
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/word-to-pdf`
|
||||
`POST /api/v1/tools/files/word-to-pdf`
|
||||
|
||||
Accepts multipart form data with a Word/ODT/RTF/TXT file.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. Upload a document and it will be conve
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/word-to-pdf \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/word-to-pdf \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@report.docx"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Extract repeating elements from an XML file into a flat CSV table. The tool auto
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/xml-to-csv`
|
||||
`POST /api/v1/tools/files/xml-to-csv`
|
||||
|
||||
Accepts multipart form data with an XML file. No settings field is required.
|
||||
|
||||
@@ -19,7 +19,7 @@ This tool has no configurable parameters. The repeating element is auto-detected
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/xml-to-csv \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/xml-to-csv \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@catalog.xml"
|
||||
```
|
||||
@@ -40,4 +40,4 @@ curl -X POST http://localhost:1349/api/v1/tools/xml-to-csv \
|
||||
- Only `.xml` files are accepted as input.
|
||||
- The tool scans the XML tree for the first repeating set of sibling elements and uses those as rows.
|
||||
- Each unique child element or attribute name becomes a CSV column header.
|
||||
- This is a one-way conversion. For bidirectional JSON/XML conversion, use the [JSON to XML](/tools/data/json-xml) tool.
|
||||
- This is a one-way conversion. For bidirectional JSON/XML conversion, use the [JSON to XML](/tools/files/json-xml) tool.
|
||||
@@ -8,7 +8,7 @@ Convert between YAML and JSON formats in both directions. Upload a YAML file to
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/yaml-json`
|
||||
`POST /api/v1/tools/files/yaml-json`
|
||||
|
||||
Accepts multipart form data with a YAML or JSON file. No settings field is required.
|
||||
|
||||
@@ -21,7 +21,7 @@ This tool has no configurable parameters. The conversion direction is determined
|
||||
YAML to JSON:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/yaml-json \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/yaml-json \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@config.yaml"
|
||||
```
|
||||
@@ -29,7 +29,7 @@ curl -X POST http://localhost:1349/api/v1/tools/yaml-json \
|
||||
JSON to YAML:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/yaml-json \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/files/yaml-json \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@config.json"
|
||||
```
|
||||
@@ -8,7 +8,7 @@ Comprehensive color adjustment tool combining brightness, contrast, exposure, sa
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/adjust-colors`
|
||||
`POST /api/v1/tools/image/adjust-colors`
|
||||
|
||||
Accepts multipart form data with an image file and a JSON `settings` field.
|
||||
|
||||
@@ -32,7 +32,7 @@ Accepts multipart form data with an image file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/adjust-colors \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/adjust-colors \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@photo.jpg" \
|
||||
-F 'settings={"brightness": 20, "contrast": 10, "saturation": -30, "effect": "none"}'
|
||||
@@ -41,7 +41,7 @@ curl -X POST http://localhost:1349/api/v1/tools/adjust-colors \
|
||||
Apply a warm vintage look:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/adjust-colors \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/adjust-colors \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@photo.jpg" \
|
||||
-F 'settings={"temperature": 40, "saturation": -15, "contrast": 10, "effect": "sepia"}'
|
||||
@@ -64,5 +64,5 @@ curl -X POST http://localhost:1349/api/v1/tools/adjust-colors \
|
||||
- Adjustments are applied in this order: brightness, contrast, exposure, saturation/hue, temperature/tint, sharpness, channels, effects.
|
||||
- Temperature uses a 3x3 color recombination matrix on the blue-orange and green-magenta axes.
|
||||
- Exposure maps to Sharp's gamma function (positive brightens midtones, negative darkens them).
|
||||
- This endpoint also responds at the legacy paths `/api/v1/tools/brightness-contrast`, `/api/v1/tools/saturation`, `/api/v1/tools/color-channels`, and `/api/v1/tools/color-effects`. All use the same schema.
|
||||
- This endpoint also responds at the legacy paths `/api/v1/tools/image/brightness-contrast`, `/api/v1/tools/image/saturation`, `/api/v1/tools/image/color-channels`, and `/api/v1/tools/image/color-effects`. All use the same schema.
|
||||
- Output format matches the input format. HEIC, RAW, PSD, and SVG inputs are automatically decoded before processing.
|
||||
|
||||
@@ -4,7 +4,7 @@ Expand the canvas of an image with AI-powered fill (outpainting). Extends the im
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/ai-canvas-expand`
|
||||
`POST /api/v1/tools/image/ai-canvas-expand`
|
||||
|
||||
**Processing:** Asynchronous (returns 202, poll `/api/v1/jobs/{jobId}/progress` for status via SSE)
|
||||
|
||||
@@ -28,7 +28,7 @@ At least one extend direction must be greater than 0.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/ai-canvas-expand \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/ai-canvas-expand \
|
||||
-F "file=@photo.jpg" \
|
||||
-F 'settings={"extendTop":200,"extendBottom":200,"extendLeft":100,"extendRight":100,"tier":"balanced"}'
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ Replace the background of an image with a solid color or gradient. The AI model
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/background-replace`
|
||||
`POST /api/v1/tools/image/background-replace`
|
||||
|
||||
Accepts multipart form data with an image file and a JSON `settings` field.
|
||||
|
||||
@@ -27,7 +27,7 @@ Accepts multipart form data with an image file and a JSON `settings` field.
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/background-replace \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/background-replace \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@photo.jpg" \
|
||||
-F 'settings={"backgroundType": "color", "color": "#2563eb", "feather": 2}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Generate barcode images from text input. Supports Code 128, EAN-13, UPC-A, Code
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/barcode-generate`
|
||||
`POST /api/v1/tools/image/barcode-generate`
|
||||
|
||||
Accepts an `application/json` body (not multipart). The barcode is generated from the provided text, not from an uploaded file.
|
||||
|
||||
@@ -24,7 +24,7 @@ Accepts an `application/json` body (not multipart). The barcode is generated fro
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/barcode-generate \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/barcode-generate \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "5901234123457", "type": "ean13", "scale": 4}'
|
||||
|
||||
@@ -8,7 +8,7 @@ Scan uploaded images for all types of barcodes and QR codes. Returns decoded tex
|
||||
|
||||
## API Endpoint
|
||||
|
||||
`POST /api/v1/tools/barcode-read`
|
||||
`POST /api/v1/tools/image/barcode-read`
|
||||
|
||||
Accepts multipart form data with an image file and an optional JSON `settings` field.
|
||||
|
||||
@@ -21,7 +21,7 @@ Accepts multipart form data with an image file and an optional JSON `settings` f
|
||||
## Example Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:1349/api/v1/tools/barcode-read \
|
||||
curl -X POST http://localhost:1349/api/v1/tools/image/barcode-read \
|
||||
-H "Authorization: Bearer si_your-api-key" \
|
||||
-F "file=@receipt.jpg" \
|
||||
-F 'settings={"tryHarder": true}'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user