Skip to content

Communications Delivery

Overview

This page consolidates all endpoints used to deliver generated documents through configured output channels in the Comfly platform. Delivery differs from generation in that the resulting document is not returned to the caller — instead, it is dispatched to an output channel (email via SMTP, file system, archive, printer, or post-processing stage).

Delivery endpoints exist in two scopes:

  1. Template-scoped delivery — accessed by template numeric ID. Available on every template controller.
  2. UUID-scoped delivery — accessed by template UUID, resolved across all resource types. Available on CcmController.

Refer to Documents Generation for generation-without-delivery endpoints and shared schema definitions.

Authentication

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

X-API-KEY: your-api-key

Shared Schemas

DeliveryParams

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

Field Type Required Description
outputChannelType string (enum) Yes Selects the output channel to deliver through. See OutputChannelType
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 use for generation
resourceType string (enum) No Resource type — required when using the UUID-based endpoint to resolve the template. See ResourceType

Example JSON:

{
  "outputChannelType": "SMTP",
  "data": {
    "recipientName": "Jane Smith",
    "invoiceNumber": "INV-2024-099"
  },
  "sampleUUID": null,
  "resourceType": "TEMPLATE"
}

Enum Reference

OutputChannelType Enum

Value Wire Value Description
FILE file Write the generated document to a configured file-system output channel
ARCHIVE archive Archive the generated document via the archive output channel
PREVIEW preview Render a preview to the configured preview output channel
SMTP SMTP Send the document as an email attachment via a configured SMTP output channel
PRINTER printer Submit the document to a configured printer output channel
POST_PROC post-proc Route the document through a post-processing stage

ResourceType Enum

Value Description
TEMPLATE HTML/document template
EMAIL_TEMPLATE Email template
FOP_TEMPLATE XSL-FO template
OFFICE_TEMPLATE DOCX/XLSX Office template
MODIFICATION_TEMPLATE Overlay/modification template
POST_PROC_TEMPLATE Post-processing template
PROCESSING_TEMPLATE Processing pipeline template
STATIC_DOCUMENT Pre-generated static document

Endpoints

Communications Delivery (by Template UUID)

POST /api/ccm/communications/{uuid}

Generates and delivers a document from the template identified by UUID. The template type is resolved automatically from resourceType in the delivery parameters, allowing a single endpoint to address any template type without knowing its numeric ID.

Parameters

Name Type In Required Description
uuid string (UUID) path Yes UUID of the template resource
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 DeliveryParams object — resourceType is required to resolve the template

Example params JSON:

{
  "outputChannelType": "FILE",
  "data": {
    "reportDate": "2024-01-31"
  },
  "sampleUUID": null,
  "resourceType": "TEMPLATE"
}

Response

Status Description
200 OK Delivery accepted. Response body is empty.
404 Not Found Template UUID not found for given resourceType

Code Examples

package main

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

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

    params := `{
        "outputChannelType": "FILE",
        "data": {"reportDate": "2024-01-31"},
        "resourceType": "TEMPLATE"
    }`
    pw, _ := writer.CreateFormField("params")
    pw.Write([]byte(params))
    writer.Close()

    uuid := "550e8400-e29b-41d4-a716-446655440000"
    req, _ := http.NewRequest("POST",
        "https://your-comfly-instance.com/api/ccm/communications/"+uuid, &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, "delivery error %d: %s\n", resp.StatusCode, b)
        os.Exit(1)
    }
    fmt.Println("Document delivered successfully")
}
import java.net.URI;
import java.net.http.*;
import java.util.UUID;

public class DeliverByUUID {
    public static void main(String[] args) throws Exception {
        String templateUUID = "550e8400-e29b-41d4-a716-446655440000";
        String boundary = UUID.randomUUID().toString();
        String params = """
            {"outputChannelType":"FILE",
             "data":{"reportDate":"2024-01-31"},
             "resourceType":"TEMPLATE"}
            """;

        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/ccm/communications/" + templateUUID))
            .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() != 200) {
            System.err.println("Delivery error " + response.statusCode());
            System.exit(1);
        }
        System.out.println("Document delivered successfully");
    }
}
import requests
import json
import sys

template_uuid = "550e8400-e29b-41d4-a716-446655440000"
url = f"https://your-comfly-instance.com/api/ccm/communications/{template_uuid}"
headers = {"X-API-KEY": "your-api-key"}

params_json = json.dumps({
    "outputChannelType": "FILE",
    "data": {"reportDate": "2024-01-31"},
    "resourceType": "TEMPLATE",
})

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

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

print("Document delivered successfully")
<?php
$uuid = '550e8400-e29b-41d4-a716-446655440000';
$url  = "https://your-comfly-instance.com/api/ccm/communications/{$uuid}";

$params = json_encode([
    'outputChannelType' => 'FILE',
    'data'              => ['reportDate' => '2024-01-31'],
    'resourceType'      => 'TEMPLATE',
]);

$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 !== 200) {
    fwrite(STDERR, "Delivery error $status: $body\n");
    exit(1);
}

echo "Document delivered successfully\n";
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

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

        var templateUUID = "550e8400-e29b-41d4-a716-446655440000";
        var paramsJson = """
            {"outputChannelType":"FILE",
             "data":{"reportDate":"2024-01-31"},
             "resourceType":"TEMPLATE"}
            """;

        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/ccm/communications/{templateUUID}",
            content);

        if (!response.IsSuccessStatusCode)
        {
            Console.Error.WriteLine($"Delivery error {(int)response.StatusCode}");
            return;
        }
        Console.WriteLine("Document delivered successfully");
    }
}
require 'net/http'
require 'uri'
require 'json'
require 'securerandom'

template_uuid = '550e8400-e29b-41d4-a716-446655440000'
uri  = URI("https://your-comfly-instance.com/api/ccm/communications/#{template_uuid}")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

params_json = JSON.generate(
  outputChannelType: 'FILE',
  data: { reportDate: '2024-01-31' },
  resourceType: 'TEMPLATE'
)

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 "Delivery error #{response.code}: #{response.body}"
  exit 1
end

puts 'Document delivered successfully'

Deliver Document (by Template ID)

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

Generates a document from the template identified by numeric id and delivers it to the output channel specified in DeliveryParams. An optional input data file may be supplied.

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 DeliveryParams object (see schema above)

Response

Status Description
200 OK Delivery accepted. Response body is empty.
400 Bad Request Generation or delivery failed. Returns ErrorResponse JSON.
404 Not Found Template with given ID does not exist

Error response body (400):

{
  "status": 400,
  "message": "SMTP output channel not configured for this template"
}

Code Examples

package main

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

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

    params := `{
        "outputChannelType": "SMTP",
        "data": {"recipientName": "Jane Smith", "invoiceNumber": "INV-2024-099"},
        "resourceType": "TEMPLATE"
    }`
    pw, _ := writer.CreateFormField("params")
    pw.Write([]byte(params))

    // Optionally attach a data 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/deliver-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, "delivery error %d: %s\n", resp.StatusCode, b)
        os.Exit(1)
    }
    fmt.Println("Document delivered successfully")
}
import java.net.URI;
import java.net.http.*;
import java.util.UUID;

public class DeliverDocument {
    public static void main(String[] args) throws Exception {
        String boundary = UUID.randomUUID().toString();
        String params = """
            {"outputChannelType":"SMTP",
             "data":{"recipientName":"Jane Smith","invoiceNumber":"INV-2024-099"},
             "resourceType":"TEMPLATE"}
            """;

        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/deliver-document"))
            .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() != 200) {
            System.err.println("Delivery error " + response.statusCode()
                + ": " + response.body());
            System.exit(1);
        }
        System.out.println("Document delivered successfully");
    }
}
import requests
import json
import sys

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

params_json = json.dumps({
    "outputChannelType": "SMTP",
    "data": {"recipientName": "Jane Smith", "invoiceNumber": "INV-2024-099"},
    "resourceType": "TEMPLATE",
})

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

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

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

print("Document delivered successfully")
<?php
$templateId = 42;
$url = "https://your-comfly-instance.com/api/templates/{$templateId}/deliver-document";

$params = json_encode([
    'outputChannelType' => 'SMTP',
    'data'              => ['recipientName' => 'Jane Smith', 'invoiceNumber' => 'INV-2024-099'],
    'resourceType'      => 'TEMPLATE',
]);

$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, "Delivery error $status: $body\n");
    exit(1);
}

echo "Document delivered successfully\n";
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

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

        var paramsJson = """
            {"outputChannelType":"SMTP",
             "data":{"recipientName":"Jane Smith","invoiceNumber":"INV-2024-099"},
             "resourceType":"TEMPLATE"}
            """;

        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/deliver-document",
            content);

        if (!response.IsSuccessStatusCode)
        {
            Console.Error.WriteLine(
                $"Delivery error {(int)response.StatusCode}: {await response.Content.ReadAsStringAsync()}");
            return;
        }
        Console.WriteLine("Document delivered successfully");
    }
}
require 'net/http'
require 'uri'
require 'json'
require 'securerandom'

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

params_json = JSON.generate(
  outputChannelType: 'SMTP',
  data: { recipientName: 'Jane Smith', invoiceNumber: 'INV-2024-099' },
  resourceType: 'TEMPLATE'
)

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 "Delivery error #{response.code}: #{response.body}"
  exit 1
end

puts 'Document delivered successfully'

Communication Delivery Properties

Communication delivery properties are named sets of delivery configuration that can be attached to communication definitions to control how documents are dispatched. They are managed through the CommunicationDeliveryPropertiesController.

Base path: /api/communicationDeliveryProperties

List Delivery Properties

GET /api/communicationDeliveryProperties

Returns a paginated list of all communication delivery property sets.

Parameters

Name Type In Required Description
X-API-KEY string header Yes API authentication key
page integer query No Page number (0-based, default 0)
size integer query No Page size (default 10)
sort string query No Sort field and direction, e.g. name,asc

Response

Status Description
200 OK Paginated list of CommunicationDeliveryPropertiesDto

Example response:

{
  "content": [
    {
      "id": 1,
      "name": "Default Email Delivery",
      "description": "Standard SMTP delivery via primary mail server"
    }
  ],
  "totalElements": 4,
  "totalPages": 1,
  "size": 10,
  "number": 0
}

Code Examples

package main

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

func main() {
    req, _ := http.NewRequest("GET",
        "https://your-comfly-instance.com/api/communicationDeliveryProperties?page=0&size=10", 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()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}
import java.net.URI;
import java.net.http.*;

public class ListDeliveryProperties {
    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/communicationDeliveryProperties?page=0&size=10"))
            .header("X-API-KEY", "your-api-key")
            .GET()
            .build();

        HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
    }
}
import requests

url = "https://your-comfly-instance.com/api/communicationDeliveryProperties"
headers = {"X-API-KEY": "your-api-key"}
params = {"page": 0, "size": 10}

response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
print(response.json())
<?php
$url = 'https://your-comfly-instance.com/api/communicationDeliveryProperties?page=0&size=10';

$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);

echo $body;
using System;
using System.Net.Http;
using System.Threading.Tasks;

class ListDeliveryProperties
{
    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/communicationDeliveryProperties?page=0&size=10");
        response.EnsureSuccessStatusCode();
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}
require 'net/http'
require 'uri'

uri = URI('https://your-comfly-instance.com/api/communicationDeliveryProperties')
uri.query = 'page=0&size=10'

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)
puts response.body

Get Delivery Properties by ID

GET /api/communicationDeliveryProperties/{id}

Returns a single delivery property set by ID.

Parameters

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

Response

Status Description
200 OK CommunicationDeliveryPropertiesDto
404 Not Found Properties not found

Example response:

{
  "id": 1,
  "name": "Default Email Delivery",
  "description": "Standard SMTP delivery via primary mail server"
}

Create Delivery Properties

POST /api/communicationDeliveryProperties

Creates a new delivery property set.

Parameters

Name Type In Required Description
X-API-KEY string header Yes API authentication key

Request Body

application/jsonCommunicationDeliveryPropertiesForm:

Field Type Required Description
name string Yes Unique name for the delivery property set
description string No Human-readable description

Example request:

{
  "name": "Archive Only",
  "description": "Routes documents to the archive channel without SMTP"
}

Response

Status Description
200 OK ValidationResultDto with the saved resource on success
200 OK ValidationResultDto with validation errors on failure

Success response:

{
  "valid": true,
  "resource": {
    "id": 5,
    "name": "Archive Only",
    "description": "Routes documents to the archive channel without SMTP"
  },
  "errors": []
}

Update Delivery Properties

PUT /api/communicationDeliveryProperties/{id}

Updates an existing delivery property set.

Parameters

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

Request Body

application/json — same schema as Create, with id included in the body (must match the path parameter).

Response

Status Description
200 OK ValidationResultDto with updated resource
400 Bad Request Path id does not match body id

Delete Delivery Properties

DELETE /api/communicationDeliveryProperties/{id}

Permanently deletes the delivery property set.

Parameters

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

Response

Status Description
200 OK Deleted successfully
404 Not Found Properties not found

How Output Channel Selection Works

When a deliver-document request is received, Comfly resolves the output channel as follows:

  1. The outputChannelType field in DeliveryParams selects the channel category.
  2. The template is examined for a configured output channel of that type.
  3. If found, the document is generated (optionally merging data or sampleUUID) and dispatched to the channel.
  4. If the channel is not configured for the template, an error is returned.

Output channels themselves are configured and linked to templates via the channel controllers:

Resource Base Path Description
Output Channel /api/outputChannels Channel definitions (type, connection settings)
Output Channel Config /api/outputChannelConfigs Per-template channel configuration
Output Channel Communication /api/outputChannelCommunications Links output channels to communication definitions

See the Channel Controllers reference for full CRUD documentation of these resources.


Error Responses

Status Cause
200 OK Delivery accepted (no body)
400 Bad Request Generation or delivery failure (e.g., misconfigured channel, data binding error). Returns ErrorResponse JSON.
401 Unauthorized Missing or invalid X-API-KEY
404 Not Found Template not found

Error body:

{
  "status": 400,
  "message": "Output channel SMTP is not configured for template 42"
}