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:
- Template-scoped delivery — accessed by template numeric ID. Available on every template controller.
- 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.
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):
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());
}
}
<?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/json — CommunicationDeliveryPropertiesForm:
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Unique name for the delivery property set |
description |
string | No | Human-readable description |
Example request:
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:
- The
outputChannelTypefield inDeliveryParamsselects the channel category. - The template is examined for a configured output channel of that type.
- If found, the document is generated (optionally merging
dataorsampleUUID) and dispatched to the channel. - 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: