Skip to content

Conversions

Conversions are async — every POST /v1/conversions returns immediately with status: 'queued', and you poll GET /v1/conversions/{id} until status is completed, failed, or cancelled. Required scope: convert:write.

GET /v1/formats

Returns the tier-filtered preset matrix. Same data the web UI consumes; useful for building a form or validating presets client-side.

bash
curl -H "Authorization: Bearer ff_live_…" \
     https://fileforge-api.obrahaus.com/v1/formats

Shape (abbreviated):

jsonc
{
  "formats": {
    "image/png": {
      "jpg": {
        "worker": "image",
        "freeAllowed": true,
        "presets": [
          { "id": "web",      "label": "Web (q=82)",         "params": { "quality": 82 } },
          { "id": "high",     "label": "High quality (q=92)", "params": { "quality": 92 } },
          { "id": "lossless", "label": "Lossless / max",      "params": { "quality": 100 } }
        ],
        "options": [
          { "key": "width",     "label": "Width (px)",  "type": "integer", "min": 1, "max": 30000, "group": "Resize" },
          { "key": "rotate",    "label": "Rotate",      "type": "enum", "values": ["0","90","180","270"] },
          { "key": "grayscale", "label": "Grayscale",   "type": "boolean", "group": "Color" },
          { "key": "quality",   "label": "Quality",     "type": "integer", "min": 1, "max": 100 }
        ]
      }
    }
  }
}

Each target entry also carries an options array describing the tunable conversion options valid for it, already filtered to your tier (free keys never see Pro-only options). The supported target formats include images (png, jpg, webp, gif, tiff, avif, and ico favicons), audio (mp3, wav, ogg, opus, flac, aac, m4a), video, documents, and archives (zip, 7z, tar, tar.gz, tar.bz2) — see the full auto-generated formats matrix.

A source can also target its own format (e.g. pngpng, pdfpdf) to apply the optional settings without changing format. PDFs and documents additionally offer a zip target that renders the selected pages to images (PNG/JPG) and returns them as a single ZIP — its options include image_format, dpi, jpeg_quality, grayscale, and page_range.

POST /v1/conversions

Enqueues a single conversion. The input_file_id must point at a file you already finalized.

bash
curl -X POST \
  -H "Authorization: Bearer ff_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "input_file_id": "9f6c...8e",
    "target_format": "pdf",
    "preset": { "id": "standard" }
  }' \
  https://fileforge-api.obrahaus.com/v1/conversions

Response (202 Accepted):

json
{
  "id": "5b3e...11",
  "status": "queued",
  "worker_type": "document",
  "target_format": "pdf",
  "preset": { "id": "standard", "params": {} }
}

Valid (target_format, preset.id) pairs are listed under each entry of GET /v1/formats. There is no universal "default" preset — every worker exposes a small named set (e.g. web / high / lossless for images, standard / linearize for PDF, low / web / high / very-high for lossy audio). Always read the matrix before constructing the request.

preserve_metadata: true is allowed for Pro/Max only; free returns 403. target_format must be allowed for the source MIME at your tier (see errors).

Conversion options

Beyond the preset, a conversion accepts an optional options object — a server-validated set of typed knobs (resize, rotate, trim, page-range, password, …). These are not raw tool flags: every option is declared and bounds-checked server-side, and any unknown key, out-of-range value, or inapplicable/Pro-gated option is rejected before the job is enqueued.

bash
curl -X POST \
  -H "Authorization: Bearer ff_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "input_file_id": "9f6c...8e",
    "target_format": "ico",
    "preset": { "id": "standard" },
    "options": { "sizes": "16,32,48" }
  }' \
  https://fileforge-api.obrahaus.com/v1/conversions

Common options by family (see the per-target list in GET /v1/formats and the full reference):

FamilyOptions
Imagewidth, height, fit, rotate, flip, flop, grayscale, quality, dpi, and sizes (favicon/ICO)
Audiochannels (mono/stereo), normalize, trim_start, trim_end
Videofps, mute, rotate, trim_start, trim_end
Document (PDF)page_range, password (Pro — encrypts the PDF)
Archive (zip/7z)password (Pro — AES-256 encrypted archive)

Validation responses: unknown key → 400 unknown_option; bad value → 400 invalid_value; option not valid for the target → 400 not_applicable; Pro-only option on a free key → 403 pro_option. The 202 response echoes the non-secret options it accepted; password options are never echoed or logged. The same options object is accepted per item on POST /v1/conversions/bulk.

Prefer to let an AI agent do this? The MCP server wraps all of this in a single convert_file tool — no REST calls needed.

POST /v1/conversions/bulk

Submit up to tier.bulk_max conversions at once (Pro: 20; Max: 100). Every item burns one conversion-rate token, so a 20-item batch from a fresh window will be accepted but follow-up calls in the same minute will rate-limit.

bash
curl -X POST \
  -H "Authorization: Bearer ff_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "input_file_id": "...a", "target_format": "pdf", "preset": { "id": "standard" } },
      { "input_file_id": "...b", "target_format": "pdf", "preset": { "id": "standard" } }
    ]
  }' \
  https://fileforge-api.obrahaus.com/v1/conversions/bulk

Response:

json
{
  "bulk_id": "f1a0...77",
  "total": 2,
  "items": [
    { "conversion_id": "...", "input_file_id": "...a", "target_format": "pdf" },
    { "conversion_id": "...", "input_file_id": "...b", "target_format": "pdf" }
  ]
}

There's no aggregate GET /v1/conversions/bulk/:id on the public API in the v1.0.0 beta — poll each conversion_id independently. The aggregate endpoint exists on the App API for the web UI's bulk-grid view; if you need it on the public API, open an issue.

GET /v1/conversions/{id}

Status snapshot + a fresh presigned download URL when complete.

jsonc
{
  "id": "5b3e...11",
  "status": "completed",            // queued | scanning | processing | completed | failed | cancelled
  "progress_pct": 100,
  "worker_type": "document",
  "source_format": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "target_format": "pdf",
  "attempt_count": 1,
  "error_code": null,
  "error_message": null,
  "queued_at": "2026-05-07T12:34:56Z",
  "started_at": "2026-05-07T12:34:58Z",
  "completed_at": "2026-05-07T12:35:04Z",
  "duration_ms": 6112,
  "output": {
    "file_id": "...",
    "download_url": "https://minio.lan/...?X-Amz-Signature=...",
    "expires_in": 300
  }
}

Poll every 1–2 seconds while status is non-terminal. The download_url in the response is regenerated on every call and lives for 5 minutes.

GET /v1/conversions/{id}/output

Convenience: 302-redirects to a fresh presigned download URL. Lets you curl -L straight to the bytes without parsing JSON.

bash
curl -L -H "Authorization: Bearer ff_live_…" \
     -o budget.pdf \
     https://fileforge-api.obrahaus.com/v1/conversions/5b3e...11/output

Returns 400 not_ready if the conversion isn't completed yet. Returns 404 if the conversion doesn't belong to your account.

Built solo on dedicated metal.