Skip to content

Documents Generation

Overview

This page consolidates all endpoints used to generate documents from templates in the Comfly platform. Generation endpoints are available on every template controller (TemplateController, EmailTemplateController, FopTemplateController, OfficeTemplateController, ModificationTemplateController) and accept identical request/response schemas.

Refer to Template Controllers for the full CRUD surface of each controller.

Authentication

All endpoints require the X-API-KEY header for authentication.

X-API-KEY: your-api-key

Shared Schemas

These schemas are used across all generation endpoints and are documented once here.

DataParams

The base data-carrier sent with every generation or delivery request.

Field Type Required Description
data object No Key-value map of template variables (string keys, arbitrary values)
sampleUUID string (UUID) No UUID of a pre-existing sample data record to merge with the template
resourceType string (enum) No Resource type hint — used by the UUID-based CCM endpoint to resolve the template. See ResourceType

GenerationParams

Extends DataParams. Sent as the params part of every generate-document multipart request.

Field Type Required Default Description
name string No Desired output file name (used in Content-Disposition header)
outputFormat string (enum) No PDF Output format. See OutputFormat
outputMode string (enum) No RAW Controls how the response is returned. See OutputMode
data object No Inherited from DataParams
sampleUUID string (UUID) No Inherited from DataParams
resourceType string (enum) No Inherited from DataParams

Example JSON:

{
  "name": "invoice-2024-01.pdf",
  "outputFormat": "PDF",
  "outputMode": "RAW",
  "data": {
    "customerName": "Acme Corp",
    "invoiceNumber": "INV-2024-001",
    "amount": 1500.00
  },
  "sampleUUID": null,
  "resourceType": "TEMPLATE"
}

AsyncGenerationParams

Extends GenerationParams. Adds a callback hook for asynchronous generation.

Field Type Required Description
callback object No Callback configuration. See CallbackParams
name string No Inherited from GenerationParams
outputFormat string (enum) No Inherited from GenerationParams
outputMode string (enum) No Inherited from GenerationParams
data object No Inherited from DataParams
sampleUUID string (UUID) No Inherited from DataParams
resourceType string (enum) No Inherited from DataParams

CallbackParams

Used within AsyncGenerationParams to configure a webhook that Comfly calls when async generation completes.

Field Type Required Description
callbackUrl string (URL) No HTTP endpoint to call on completion
queryParams object No Map of query string parameters to append to the callback URL
headers object No Map of HTTP headers to send with the callback request

GenerationResult

Returned by synchronous generate-document when outputMode is BASE64.

Field Type Description
data byte[] Raw document bytes (present when outputMode is RAW at the HTTP level — normally not in JSON)
document string Base64-encoded document content when outputMode is BASE64
metadata object DocumentMeta — see below

DocumentMeta

Field Type Description
uid string Unique identifier for this generated document instance
name string Document name
fileName string Suggested file name (with extension)
contentType string MIME type (e.g., application/pdf)
outputMode string (enum) The OutputMode used for this response

Example GenerationResult (BASE64 mode):

{
  "data": null,
  "document": "JVBERi0xLjQKJeLjz9MKNiAwIG9iago...",
  "metadata": {
    "uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "invoice-2024-01",
    "fileName": "invoice-2024-01.pdf",
    "contentType": "application/pdf",
    "outputMode": "BASE64"
  }
}

Enum Reference

OutputFormat Enum

Value Content-Type File Extension Description
PDF application/pdf .pdf PDF document (default)
HTML text/html .html HTML document
RAW application/octet-stream .raw Raw/native binary output

OutputMode Enum

Value HTTP Response Description
RAW Binary bytes in body with content headers Document bytes streamed directly. Content-Type and Content-Disposition are set automatically.
BASE64 JSON GenerationResult body Document returned as a base64-encoded string within a JSON envelope alongside metadata.
ARCHIVE 200 OK, empty body Document is routed to the configured archive output channel. Nothing is returned in the response body.

ResourceType Enum

Value Renderable Description
TEMPLATE Yes HTML/document template
EMAIL_TEMPLATE Yes Email template
FOP_TEMPLATE Yes XSL-FO template
OFFICE_TEMPLATE Yes DOCX/XLSX Office template
MODIFICATION_TEMPLATE Yes Overlay/modification template
POST_PROC_TEMPLATE Yes Post-processing template
PROCESSING_TEMPLATE Yes Processing pipeline template
FOLDER No Organizational folder
IMAGE No Image asset
STYLE No CSS/stylesheet
FONT No Font resource
SAMPLE No Sample data set
SCHEMA No Data schema definition
SCRIPT No Groovy/Java script
FRAGMENT No Reusable template fragment
PAGE No Page layout resource
APPLICATION No Application resource
STATIC_DOCUMENT No Pre-generated static document

Endpoints

Generate Document (Synchronous)

POST /{base-path}/{id}/generate-document

Generates a document from the template identified by id and returns it synchronously. The response format depends on outputMode:

  • RAW — raw document bytes are streamed with appropriate Content-Type and Content-Disposition headers.
  • BASE64 — a GenerationResult JSON object is returned.
  • ARCHIVE — the document is routed to the archive output channel; the response body is empty.

Available on all template controllers:

Controller Base Path
TemplateController /api/templates
EmailTemplateController /api/email-templates
FopTemplateController /api/fop-templates
OfficeTemplateController /api/office-templates
ModificationTemplateController /api/modificationTemplates

Parameters

Name Type In Required Description
id integer (long) path Yes Template resource ID
X-API-KEY string header Yes API authentication key

Request Body

multipart/form-data:

Part Type Required Description
data file No Input data file (XML, JSON, etc.) to merge with the template
params JSON Yes GenerationParams object (see schema above)

Response

Status Description
200 OK Document bytes (RAW mode) or GenerationResult JSON (BASE64 mode)
200 OK Empty body when outputMode is ARCHIVE
404 Not Found Template with given ID does not exist

RAW mode response headers:

Content-Type: application/pdf
Content-Disposition: inline; filename=invoice-2024-01.pdf
Cache-Control: must-revalidate, post-check=0, pre-check=0

Code Examples

package main

import (
    "bytes"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "os"
)

func main() {
    var body bytes.Buffer
    writer := multipart.NewWriter(&body)

    // params part
    params := `{"name":"invoice.pdf","outputFormat":"PDF","outputMode":"RAW","data":{"customerName":"Acme Corp"}}`
    pw, _ := writer.CreateFormField("params")
    pw.Write([]byte(params))

    // data part (optional file)
    // fw, _ := writer.CreateFormFile("data", "data.xml")
    // file, _ := os.Open("data.xml")
    // io.Copy(fw, file)

    writer.Close()

    req, _ := http.NewRequest("POST",
        "https://your-comfly-instance.com/api/templates/42/generate-document", &body)
    req.Header.Set("Content-Type", writer.FormDataContentType())
    req.Header.Set("X-API-KEY", "your-api-key")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Fprintln(os.Stderr, "request error:", err)
        os.Exit(1)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        b, _ := io.ReadAll(resp.Body)
        fmt.Fprintf(os.Stderr, "error %d: %s\n", resp.StatusCode, b)
        os.Exit(1)
    }

    out, _ := os.Create("output.pdf")
    defer out.Close()
    io.Copy(out, resp.Body)
    fmt.Println("Saved to output.pdf")
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;

public class GenerateDocument {
    public static void main(String[] args) throws Exception {
        String boundary = UUID.randomUUID().toString();
        String params = """
                {"name":"invoice.pdf","outputFormat":"PDF","outputMode":"RAW",
                 "data":{"customerName":"Acme Corp"}}
                """;

        String body = "--" + boundary + "\r\n"
            + "Content-Disposition: form-data; name=\"params\"\r\n"
            + "Content-Type: application/json\r\n\r\n"
            + params + "\r\n"
            + "--" + boundary + "--\r\n";

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://your-comfly-instance.com/api/templates/42/generate-document"))
            .header("X-API-KEY", "your-api-key")
            .header("Content-Type", "multipart/form-data; boundary=" + boundary)
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

        HttpResponse<byte[]> response = client.send(request,
            HttpResponse.BodyHandlers.ofByteArray());

        if (response.statusCode() != 200) {
            System.err.println("Error: " + response.statusCode());
            System.exit(1);
        }

        Files.write(Path.of("output.pdf"), response.body());
        System.out.println("Saved to output.pdf");
    }
}
import requests
import sys

url = "https://your-comfly-instance.com/api/templates/42/generate-document"
headers = {"X-API-KEY": "your-api-key"}

params_json = {
    "name": "invoice.pdf",
    "outputFormat": "PDF",
    "outputMode": "RAW",
    "data": {"customerName": "Acme Corp"},
}

# Optionally include a data file:
# with open("data.xml", "rb") as f:
#     files = {"data": f, "params": (None, str(params_json), "application/json")}

files = {"params": (None, str(params_json).replace("'", '"'), "application/json")}

response = requests.post(url, headers=headers, files=files)

if response.status_code != 200:
    print(f"Error {response.status_code}: {response.text}", file=sys.stderr)
    sys.exit(1)

with open("output.pdf", "wb") as f:
    f.write(response.content)
print("Saved to output.pdf")
<?php
$templateId = 42;
$url = "https://your-comfly-instance.com/api/templates/{$templateId}/generate-document";

$params = json_encode([
    'name'         => 'invoice.pdf',
    'outputFormat' => 'PDF',
    'outputMode'   => 'RAW',
    'data'         => ['customerName' => 'Acme Corp'],
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['X-API-KEY: your-api-key'],
    CURLOPT_POSTFIELDS     => [
        'params' => new CURLStringFile($params, 'params.json', 'application/json'),
        // 'data' => new CURLFile('/path/to/data.xml', 'application/xml', 'data.xml'),
    ],
]);

$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 200) {
    fwrite(STDERR, "Error $status: $body\n");
    exit(1);
}

file_put_contents('output.pdf', $body);
echo "Saved to output.pdf\n";
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

class GenerateDocument
{
    static async Task Main()
    {
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("X-API-KEY", "your-api-key");

        var paramsJson = """
            {"name":"invoice.pdf","outputFormat":"PDF","outputMode":"RAW",
             "data":{"customerName":"Acme Corp"}}
            """;

        using var content = new MultipartFormDataContent();
        content.Add(new StringContent(paramsJson, Encoding.UTF8, "application/json"), "params");
        // content.Add(new ByteArrayContent(File.ReadAllBytes("data.xml")), "data", "data.xml");

        var response = await client.PostAsync(
            "https://your-comfly-instance.com/api/templates/42/generate-document",
            content);

        if (!response.IsSuccessStatusCode)
        {
            Console.Error.WriteLine($"Error {(int)response.StatusCode}: {await response.Content.ReadAsStringAsync()}");
            return;
        }

        await File.WriteAllBytesAsync("output.pdf", await response.Content.ReadAsByteArrayAsync());
        Console.WriteLine("Saved to output.pdf");
    }
}
require 'net/http'
require 'uri'
require 'json'

uri   = URI('https://your-comfly-instance.com/api/templates/42/generate-document')
http  = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

params_json = JSON.generate(
  name: 'invoice.pdf',
  outputFormat: 'PDF',
  outputMode: 'RAW',
  data: { customerName: 'Acme Corp' }
)

boundary = "----ComflyBoundary#{SecureRandom.hex(8)}"
body  = "--#{boundary}\r\n"
body += "Content-Disposition: form-data; name=\"params\"\r\n"
body += "Content-Type: application/json\r\n\r\n"
body += "#{params_json}\r\n"
body += "--#{boundary}--\r\n"

request = Net::HTTP::Post.new(uri)
request['X-API-KEY']    = 'your-api-key'
request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
request.body = body

response = http.request(request)

unless response.is_a?(Net::HTTPSuccess)
  warn "Error #{response.code}: #{response.body}"
  exit 1
end

File.binwrite('output.pdf', response.body)
puts 'Saved to output.pdf'

Generate Document (Asynchronous)

POST /{base-path}/{id}/generate-document-async

Enqueues a document generation job and returns immediately with a job ID. The generation runs in the background. If a callback URL is provided in the params, Comfly will send an HTTP request to that URL when the job finishes.

Available on the same template controllers as the synchronous endpoint.

Parameters

Name Type In Required Description
id integer (long) path Yes Template resource ID
X-API-KEY string header Yes API authentication key

Request Body

multipart/form-data:

Part Type Required Description
data file No Input data file to merge with the template
params JSON Yes AsyncGenerationParams object (see schema above)

Example params JSON:

{
  "name": "report-jan.pdf",
  "outputFormat": "PDF",
  "outputMode": "RAW",
  "data": { "reportMonth": "January 2024" },
  "callback": {
    "callbackUrl": "https://my-app.example.com/generation-complete",
    "queryParams": { "jobRef": "report-jan" },
    "headers": { "Authorization": "Bearer my-token" }
  }
}

Response

Status Description
202 Accepted Job created. Response body is the job ID (long integer).
400 Bad Request Invalid request parameters

Example response body:

1042

Code Examples

package main

import (
    "bytes"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "os"
)

func main() {
    var body bytes.Buffer
    writer := multipart.NewWriter(&body)

    params := `{
        "name":"report-jan.pdf","outputFormat":"PDF","outputMode":"RAW",
        "data":{"reportMonth":"January 2024"},
        "callback":{"callbackUrl":"https://my-app.example.com/done"}
    }`
    pw, _ := writer.CreateFormField("params")
    pw.Write([]byte(params))
    writer.Close()

    req, _ := http.NewRequest("POST",
        "https://your-comfly-instance.com/api/templates/42/generate-document-async", &body)
    req.Header.Set("Content-Type", writer.FormDataContentType())
    req.Header.Set("X-API-KEY", "your-api-key")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Fprintln(os.Stderr, "request error:", err)
        os.Exit(1)
    }
    defer resp.Body.Close()

    jobID, _ := io.ReadAll(resp.Body)
    fmt.Printf("Job ID: %s\n", jobID)
}
import java.net.URI;
import java.net.http.*;
import java.util.UUID;

public class GenerateDocumentAsync {
    public static void main(String[] args) throws Exception {
        String boundary = UUID.randomUUID().toString();
        String params = """
            {"name":"report-jan.pdf","outputFormat":"PDF","outputMode":"RAW",
             "data":{"reportMonth":"January 2024"},
             "callback":{"callbackUrl":"https://my-app.example.com/done"}}
            """;

        String body = "--" + boundary + "\r\n"
            + "Content-Disposition: form-data; name=\"params\"\r\n"
            + "Content-Type: application/json\r\n\r\n"
            + params + "\r\n"
            + "--" + boundary + "--\r\n";

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://your-comfly-instance.com/api/templates/42/generate-document-async"))
            .header("X-API-KEY", "your-api-key")
            .header("Content-Type", "multipart/form-data; boundary=" + boundary)
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

        HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());

        if (response.statusCode() != 202) {
            System.err.println("Error: " + response.statusCode());
            System.exit(1);
        }
        System.out.println("Job ID: " + response.body());
    }
}
import requests
import json
import sys

url = "https://your-comfly-instance.com/api/templates/42/generate-document-async"
headers = {"X-API-KEY": "your-api-key"}

params_json = json.dumps({
    "name": "report-jan.pdf",
    "outputFormat": "PDF",
    "outputMode": "RAW",
    "data": {"reportMonth": "January 2024"},
    "callback": {"callbackUrl": "https://my-app.example.com/done"},
})

files = {"params": (None, params_json, "application/json")}
response = requests.post(url, headers=headers, files=files)

if response.status_code != 202:
    print(f"Error {response.status_code}: {response.text}", file=sys.stderr)
    sys.exit(1)

print(f"Job ID: {response.text}")
<?php
$url = "https://your-comfly-instance.com/api/templates/42/generate-document-async";

$params = json_encode([
    'name'         => 'report-jan.pdf',
    'outputFormat' => 'PDF',
    'outputMode'   => 'RAW',
    'data'         => ['reportMonth' => 'January 2024'],
    'callback'     => ['callbackUrl' => 'https://my-app.example.com/done'],
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['X-API-KEY: your-api-key'],
    CURLOPT_POSTFIELDS     => [
        'params' => new CURLStringFile($params, 'params.json', 'application/json'),
    ],
]);

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 202) {
    fwrite(STDERR, "Error $status: $body\n");
    exit(1);
}

echo "Job ID: $body\n";
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

class GenerateDocumentAsync
{
    static async Task Main()
    {
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("X-API-KEY", "your-api-key");

        var paramsJson = """
            {"name":"report-jan.pdf","outputFormat":"PDF","outputMode":"RAW",
             "data":{"reportMonth":"January 2024"},
             "callback":{"callbackUrl":"https://my-app.example.com/done"}}
            """;

        using var content = new MultipartFormDataContent();
        content.Add(new StringContent(paramsJson, Encoding.UTF8, "application/json"), "params");

        var response = await client.PostAsync(
            "https://your-comfly-instance.com/api/templates/42/generate-document-async",
            content);

        if (!response.IsSuccessStatusCode)
        {
            Console.Error.WriteLine($"Error {(int)response.StatusCode}");
            return;
        }

        var jobId = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"Job ID: {jobId}");
    }
}
require 'net/http'
require 'uri'
require 'json'
require 'securerandom'

uri   = URI('https://your-comfly-instance.com/api/templates/42/generate-document-async')
http  = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

params_json = JSON.generate(
  name: 'report-jan.pdf',
  outputFormat: 'PDF',
  outputMode: 'RAW',
  data: { reportMonth: 'January 2024' },
  callback: { callbackUrl: 'https://my-app.example.com/done' }
)

boundary = "----ComflyBoundary#{SecureRandom.hex(8)}"
body  = "--#{boundary}\r\n"
body += "Content-Disposition: form-data; name=\"params\"\r\n"
body += "Content-Type: application/json\r\n\r\n"
body += "#{params_json}\r\n"
body += "--#{boundary}--\r\n"

request = Net::HTTP::Post.new(uri)
request['X-API-KEY']    = 'your-api-key'
request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
request.body = body

response = http.request(request)

unless response.code == '202'
  warn "Error #{response.code}: #{response.body}"
  exit 1
end

puts "Job ID: #{response.body}"

Preview Document (PDF)

GET /{base-path}/{id}/preview/{dummyFileName}

Generates a PDF preview of the template using optional sample data or an input channel config. The {dummyFileName} path segment is cosmetic — browsers use it to suggest a save-as file name but it does not affect processing.

Note

This endpoint is intended for UI previews. For production document generation use generate-document instead.

Parameters

Name Type In Required Description
id integer (long) path Yes Template resource ID
dummyFileName string path Yes Cosmetic file name (e.g., preview.pdf) — not used in processing
dataId integer (long) query No ID of a sample record to use for generation
inputChannelConfigId integer (long) query No ID of an input channel config to use
setThumbnail boolean query No When true, updates the template's stored thumbnail with the preview result (default false)
X-API-KEY string header Yes API authentication key

Response

Status Description
200 OK PDF bytes with Content-Type: application/pdf and inline Content-Disposition
204 No Content Template rendered an empty document
404 Not Found Template not found

Response headers (200):

Content-Type: application/pdf
Content-Disposition: inline; filename=InvoiceTemplate
Cache-Control: must-revalidate, post-check=0, pre-check=0

Code Examples

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    url := "https://your-comfly-instance.com/api/templates/42/preview/preview.pdf?setThumbnail=false"

    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Set("X-API-KEY", "your-api-key")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Fprintln(os.Stderr, "request error:", err)
        os.Exit(1)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        b, _ := io.ReadAll(resp.Body)
        fmt.Fprintf(os.Stderr, "error %d: %s\n", resp.StatusCode, b)
        os.Exit(1)
    }

    out, _ := os.Create("preview.pdf")
    defer out.Close()
    io.Copy(out, resp.Body)
    fmt.Println("Preview saved to preview.pdf")
}
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;

public class PreviewDocument {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(
                "https://your-comfly-instance.com/api/templates/42/preview/preview.pdf?setThumbnail=false"))
            .header("X-API-KEY", "your-api-key")
            .GET()
            .build();

        HttpResponse<byte[]> response = client.send(request,
            HttpResponse.BodyHandlers.ofByteArray());

        if (response.statusCode() != 200) {
            System.err.println("Error: " + response.statusCode());
            System.exit(1);
        }

        Files.write(Path.of("preview.pdf"), response.body());
        System.out.println("Preview saved to preview.pdf");
    }
}
import requests
import sys

url = "https://your-comfly-instance.com/api/templates/42/preview/preview.pdf"
params = {"setThumbnail": "false"}
headers = {"X-API-KEY": "your-api-key"}

response = requests.get(url, headers=headers, params=params)

if response.status_code != 200:
    print(f"Error {response.status_code}: {response.text}", file=sys.stderr)
    sys.exit(1)

with open("preview.pdf", "wb") as f:
    f.write(response.content)
print("Preview saved to preview.pdf")
<?php
$id  = 42;
$url = "https://your-comfly-instance.com/api/templates/{$id}/preview/preview.pdf?setThumbnail=false";

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['X-API-KEY: your-api-key'],
]);

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 200) {
    fwrite(STDERR, "Error $status: $body\n");
    exit(1);
}

file_put_contents('preview.pdf', $body);
echo "Preview saved to preview.pdf\n";
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

class PreviewDocument
{
    static async Task Main()
    {
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Add("X-API-KEY", "your-api-key");

        var response = await client.GetAsync(
            "https://your-comfly-instance.com/api/templates/42/preview/preview.pdf?setThumbnail=false");

        if (!response.IsSuccessStatusCode)
        {
            Console.Error.WriteLine($"Error {(int)response.StatusCode}");
            return;
        }

        await File.WriteAllBytesAsync("preview.pdf",
            await response.Content.ReadAsByteArrayAsync());
        Console.WriteLine("Preview saved to preview.pdf");
    }
}
require 'net/http'
require 'uri'

uri = URI('https://your-comfly-instance.com/api/templates/42/preview/preview.pdf')
uri.query = 'setThumbnail=false'

http    = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
request['X-API-KEY'] = 'your-api-key'

response = http.request(request)

unless response.is_a?(Net::HTTPSuccess)
  warn "Error #{response.code}: #{response.body}"
  exit 1
end

File.binwrite('preview.pdf', response.body)
puts 'Preview saved to preview.pdf'

Response Behavior Summary

outputMode outputFormat Response Status Response Body Content-Type
RAW PDF 200 Binary PDF bytes application/pdf
RAW HTML 200 Binary HTML bytes text/html
RAW RAW 200 Binary bytes (native) application/octet-stream
BASE64 any 200 GenerationResult JSON application/json
ARCHIVE any 200 Empty body

Error Responses

Generation endpoints return standard error JSON on failure:

{
  "status": 400,
  "message": "Template 42 not found or cannot be rendered"
}
Status Cause
400 Bad Request Invalid params, unsupported output format, or generation failure
401 Unauthorized Missing or invalid X-API-KEY
404 Not Found Template ID does not exist
204 No Content Preview returned empty document (preview endpoint only)