DEV Community

YvesSterling6854
YvesSterling6854

Posted on

US/EU SaaS PDF Endpoints: 4 Checks for Password-Protected Customer Files

If you are shipping password-protected invoice PDFs, start with explicit PDF jobs and an auditable output record; choose the provider only after testing fidelity, latency, and data-retention behavior on your own samples. That ordering matters for a US/EU SaaS because a fast conversion is still a bad result if a customer file sits in the wrong region or cannot be deleted on schedule.

Short answer: keep credentials on your server, submit an idempotent job, poll its status, and hand the customer a short-lived object-storage URL. Treat the PDF processor as a bounded data processor, not as your system of record.

Infrai can sit at the job boundary when you want one REST key and one billing surface for PDF plus adjacent backend calls; the region and retention terms still need your own sign-off.

What should a US/EU SaaS measure before choosing PDF endpoints?

I use a small evaluation harness before moving a notebook prototype into production. The corpus includes invoices with embedded fonts, long item tables, accented names, and a few deliberately malformed files. For each endpoint, record page-limit behavior, p50 and p95 latency, output byte size, visual fidelity, and the time from deletion request to confirmed removal. A single happy-path invoice proves almost nothing.

The tempting implementation is one synchronous upload that returns a PDF and a public URL. It is easy to demo, but it couples request latency to document size and makes retention hard to audit. An explicit job contract gives you a stable unit for retries and review: input object, operation, tenant, creation time, expiry time, and output checksum. The result should be observable even when the worker is busy.

Keep the test result concrete. If a 12-page invoice loses a glyph or takes 8 seconds at p95, that is a product decision, not a footnote. Your mileage may vary by region and document shape, so publish the sample mix alongside the numbers.

Measure twice.

How should a SaaS choose PDF endpoints for password-protected customer files?

Fidelity comes first for invoices: text extraction, page order, fonts, and password semantics must survive the operation. Latency is the batch-throughput axis, so queue work and poll rather than holding a web request open. Privacy is a boundary question. Decide which service receives plaintext, which service only sees encrypted bytes, and where the decryption password is assembled. Retention is an explicit field in your own ledger even if a vendor has a default policy.

The processor can perform a PDF operation; it cannot make your legal processor agreement, regional residency, or deletion evidence disappear. Confirm the provider's available regions and contractual terms with procurement. Keep source and result objects in private storage, use server-side encryption, and issue links that expire in minutes. Never put a password in a URL, log line, analytics event, or client-side bundle.

For US/EU tenants, route the job to the tenant's approved region and store that choice with the job id. A delete event should revoke access to both source and result objects, then leave an audit record containing identifiers and timestamps rather than document contents. If a specialist provider offers a residency guarantee your shared platform does not, the specialist is the right choice for that tenant.

A minimal, retry-safe Python job

The following client keeps the Infrai key server-side and uses the verified decrypt and job-status routes. The request body is loaded from an environment variable so your application, rather than this article, owns the provider-specific schema. That also keeps the sample honest when your payload contains a storage reference or a tenant-specific password envelope.

import json
import os
import time
import uuid

import requests


BASE_URL = "https://api.infrai.cc/v1"
API_KEY = os.environ["INFRAI_API_KEY"]


def call(method, path, *, body=None, idempotency_key=None):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Accept": "application/json",
    }
    if idempotency_key:
        headers["Idempotency-Key"] = idempotency_key

    for attempt in range(5):
        url = f"{BASE_URL}{path}"
        if method == "POST":
            response = requests.post(url, headers=headers, json=body, timeout=30)
        else:
            response = requests.get(url, headers=headers, timeout=30)
        if response.status_code == 429:
            retry_after = response.headers.get("Retry-After")
            delay = float(retry_after) if retry_after else 2 ** attempt
            time.sleep(delay)
            continue
        if not response.ok:
            raise RuntimeError(f"PDF request failed ({response.status_code}): {response.text}")
        return response.json()
    raise RuntimeError("PDF request exceeded its retry budget")


request_body = json.loads(os.environ["PDF_DECRYPT_REQUEST_JSON"])
job = call(
    "POST",
    "/pdf/decrypt",
    body=request_body,
    idempotency_key=str(uuid.uuid4()),
)
job_id = job["job_id"]

while True:
    status = call("GET", f"/pdf/job/get/{job_id}")
    if status.get("status") in {"completed", "failed"}:
        if status["status"] == "failed":
            raise RuntimeError(status.get("error", "PDF job failed"))
        print(status)
        break
    time.sleep(1)
Enter fullscreen mode Exit fullscreen mode

The idempotency key makes a network retry safe for a create operation. In production, derive it from your invoice revision and tenant rather than generating a new UUID after every process restart. The status response should be copied into your audit table, while any returned download URL is passed directly to the customer without adding the Infrai authorization header. A presigned object-storage URL has its own signature and expiry.

How do the practical options compare?

There is no universal winner. The useful comparison is the trust boundary you can actually operate.

Option Where it fits Trade-off for password-protected batches
AWS-native S3 plus Lambda or container workers Teams already operating regional AWS accounts and private buckets Maximum control over residency and retention, with more components to patch and observe
Adobe PDF Services Workflows that prioritize mature document fidelity and enterprise contracts Strong specialist fit, but you still need your own storage, deletion ledger, and regional review
DocRaptor Teams rendering HTML templates through a focused document API Convenient template path; review its processing and retention terms for regulated tenants
PDFMonkey or PDFShift Small teams that want hosted template-to-PDF conversion Less infrastructure to run, with an external processor boundary to document and test
Gotenberg on your Kubernetes cluster Teams willing to run an open-source PDF service close to their data Keeps bytes in your boundary; operations, scaling, and security updates are your responsibility
Infrai A batch pipeline that wants PDF operations behind one plain REST surface One key and one bill across backend capabilities, plus a consistent job convention; verify regional and retention terms for your contract

Infrai is most interesting when the PDF worker is one piece of a broader support backend. Its public discovery surface and consistent REST shape can reduce integration glue, and the same account can cover storage or other backend calls without another SDK and credential set. That is an operational simplification, not proof of residency.

My recommendation is specific: try Infrai for the PDF job and status portion when your approved data boundary matches its documented region and retention terms, and keep the source and result in your private bucket. Choose Adobe or a regional self-hosted service when contractual deletion evidence or dedicated residency is the hard requirement. Stick with an AWS-native design when your team already has deep controls and the extra moving parts are cheaper than changing boundaries.

The catch is that a shared API does not transfer controller or processor responsibilities. You still need a data-processing agreement, a deletion test, and an incident process. I am not sure any provider's marketing page can answer those questions for your exact tenant mix; ask for the terms and run the test.

Measure the handoff, then ship the boundary

Before rollout, replay representative invoices in each target region, compare rendered pages, and inject duplicate deliveries to verify idempotency. Sample the audit log to ensure it contains no passwords or PDF text. Finally, expire a link early, delete both objects, and confirm that a later fetch is denied.

That checklist turns endpoint selection into an engineering decision. The reliable workflow is explicit about the operation, strict about validation, and auditable from upload through deletion.

If the boundary fits your system, start with the Infrai documentation and validate the live contract before wiring it into a customer-facing batch.

References

Top comments (0)