Skip to main content

Python SDK for the FormatEx LaTeX-to-PDF API

Project description

FormatEx Python SDK

Official Python client for the FormatEx LaTeX-to-PDF API.

Installation

pip install formatex

Requires Python ≥ 3.9.

Quick Start

from formatex import FormatExClient

with FormatExClient("fx_your_api_key") as client:
    result = client.compile(
        r"\documentclass{article}\begin{document}Hello, world!\end{document}"
    )
    # result.pdf       → bytes
    # result.engine    → "pdflatex"
    # result.duration_ms → 412
    with open("output.pdf", "wb") as f:
        f.write(result.pdf)

Compilation

Sync (immediate response)

# Choose your engine
result = client.compile(latex, engine="pdflatex")   # default
result = client.compile(latex, engine="xelatex")    # Unicode + modern fonts
result = client.compile(latex, engine="lualatex")   # Lua scripting
result = client.compile(latex, engine="latexmk")    # automatic multi-pass

# Smart compile: auto-detects the right engine + attempts auto-fix
result = client.compile_smart(latex)

# Compile directly to a file
client.compile_to_file(latex, "output.pdf")
client.compile_to_file(latex, "output.pdf", engine="xelatex")
client.compile_to_file(latex, "output.pdf", smart=True)

Async (long-running documents)

from formatex import FormatExClient

with FormatExClient("fx_your_api_key") as client:
    # Submit and get a job ID immediately
    job = client.async_compile(latex, engine="pdflatex")
    print(job.job_id, job.status)  # "abc-123", "pending"

    # Option 1: blocking wait (polls automatically)
    result = client.wait_for_job(job.job_id)
    with open("output.pdf", "wb") as f:
        f.write(result.pdf)

    # Option 2: manual polling loop
    import time
    while True:
        status = client.get_job(job.job_id)
        if status.status == "completed":
            pdf = client.get_job_pdf(job.job_id)  # one-time download
            break
        elif status.status == "failed":
            print("Failed:", status.error)
            break
        time.sleep(2)

    # Retrieve just the log
    log = client.get_job_log(job.job_id)

    # Clean up server-side (optional, PDF auto-deletes after download)
    client.delete_job(job.job_id)

Multi-File Projects

Use file_entry to attach companion files (images, .bib, .cls, etc.):

from pathlib import Path
from formatex import FormatExClient, file_entry

latex = r"""
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\includegraphics[width=\linewidth]{logo.png}
\bibliography{refs}
\end{document}
"""

with FormatExClient("fx_your_api_key") as client:
    result = client.compile(
        latex,
        engine="pdflatex",
        files=[
            file_entry("logo.png", Path("assets/logo.png")),   # auto-read from disk
            file_entry("refs.bib", Path("references.bib")),
        ],
    )
    Path("output.pdf").write_bytes(result.pdf)

file_entry(name, content) accepts:

  • Path — reads the file automatically
  • bytes — raw binary data, base64-encoded for you
  • str — already base64-encoded content passed through as-is

Lint (Static Analysis)

Run chktex without consuming compilation quota:

from formatex import FormatExClient

latex = r"""
\documentclass{article}
\begin{document}
Hello world.
\end{document}
"""

with FormatExClient("fx_your_api_key") as client:
    result = client.lint(latex)

    print(f"Valid: {result.valid}")
    print(f"Errors: {result.error_count}, Warnings: {result.warning_count}")

    for d in result.diagnostics:
        print(f"  Line {d.line}:{d.column} [{d.severity}] {d.message}")

Integrate into CI:

result = client.lint(source)
if not result.valid:
    raise SystemExit(f"LaTeX lint failed: {result.error_count} error(s)")

Convert to Word (DOCX)

with FormatExClient("fx_your_api_key") as client:
    result = client.convert(latex)
    Path("document.docx").write_bytes(result.docx)

    # Or write directly to a file
    client.convert_to_file(latex, "document.docx")

Syntax Check

Free endpoint — does not count against your quota:

check = client.check_syntax(latex)
print(check.valid, check.errors)

Usage Stats & Engines

usage = client.get_usage()
print(f"{usage.compilations_used}/{usage.compilations_limit} compilations this month")
print(f"Overage: {usage.overage}")

engines = client.list_engines()
for e in engines:
    print(e["name"], e["available"])

Error Handling

from formatex import (
    FormatExClient,
    AuthenticationError,
    CompilationError,
    RateLimitError,
    PlanLimitError,
)

with FormatExClient("fx_your_api_key") as client:
    try:
        result = client.compile(latex)
    except AuthenticationError:
        print("Invalid API key")
    except CompilationError as e:
        print(f"Compilation failed: {e}")
        print(f"Compiler log:\n{e.log}")
    except RateLimitError as e:
        print(f"Rate limited — retry after {e.retry_after}s")
    except PlanLimitError:
        print("Plan limit exceeded, upgrade at https://formatex.com/pricing")

Self-Hosted / Custom URL

client = FormatExClient("fx_key", base_url="https://latex.your-company.com")

Type Reference

All types are importable directly from formatex:

Type Description
CompileResult Sync compile result: pdf, engine, duration_ms, size_bytes, log, job_id
AsyncJob Submitted async job: job_id, status
JobResult Polled job state: job_id, status, log, duration_ms, error, success
LintResult Lint output: diagnostics, duration_ms, error_count, warning_count, valid
LintDiagnostic Single finding: line, column, severity, message, source, code
SyntaxResult Syntax check: valid, errors
ConvertResult DOCX output: docx (bytes), size_bytes
UsageStats Quota: compilations_used, compilations_limit, overage, period_start, period_end

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

formatex-1.0.0.tar.gz (16.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

formatex-1.0.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file formatex-1.0.0.tar.gz.

File metadata

  • Download URL: formatex-1.0.0.tar.gz
  • Upload date:
  • Size: 16.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0

File hashes

Hashes for formatex-1.0.0.tar.gz
Algorithm Hash digest
SHA256 20c601ae7831b735a62937575f610d588a45e6b9a037e5a6a9cea715fbf080c9
MD5 3df53fd55dac6753e9fd22cc03dc2ad8
BLAKE2b-256 eaccf405c40aa7040a746c9fd7b69f4be70503b394e86eed3e6efc3fd6aab65b

See more details on using hashes here.

File details

Details for the file formatex-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: formatex-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0

File hashes

Hashes for formatex-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e151253cd2ac0437b6bc0e6ae6934f6ec8731ccbf9719b9af631f6f864310317
MD5 1a2e0340440d779d6e12227447e1be37
BLAKE2b-256 5bf2614642a66596dc819cf480436ef286beadb5df9c3cf48c1f36d98f4091ee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page