The CxReports Java API Client provides a comprehensive, easy-to-use interface for interacting with the CxReports API. This library allows developers to preview reports, download reports as PDFs, manage workspaces, handle temporary data, perform asynchronous document exports, and execute batch job workflows with full Java 11+ support.
Features
- Authentication with API tokens and nonce tokens
- Asynchronous operations using
CompletableFuture - Preview reports by ID or type
- Download reports as PDF, HTML documents, PowerPoint slides, Excel sheets or Word documents (sync and async)
- Fetch workspaces, reports, and report types
- Temporary data storage for report export
- Background document export with status monitoring
- Job management and batch processing workflows
- Job run execution, monitoring, and delivery
- Built-in error handling and URI management
- Timezone support for date/time operations
Requirements
- Java 11 or higher
- HTTP Client with set up permissions and certificates
Installation
Add the dependency to your project:
Maven:
<dependency>
<groupId>com.cx-reports</groupId>
<artifactId>api-client</artifactId>
<version>0.1.0</version>
</dependency>import com.cxreports.api.v1.CxReportsClient;
import java.net.http.HttpClient;
import java.time.Duration;
// Create HTTP client with custom configuration
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
// Initialize the CxReports client
CxReportsClient client = new CxReportsClient(
"https://your-cxreports-server.com", // Base URL
"your-personal-access-token", // Auth Token
123, // Default Workspace ID
"DEFAULT_WS", // Default Workspace Code
"UTC", // Default Timezone
httpClient // HTTP Client
);import com.cxreports.api.v1.models.*;
// Get all reports from default workspace
Report[] allReports = client.getReportsAsync(null, null).get();
// Get reports filtered by report type
WorkspaceKey workspace = new WorkspaceKey(456); // or new WorkspaceKey("WS_CODE")
CompletableFuture<Report[]> filteredReports = client.getReportsAsync(
workspace, // Workspace (null for default)
"invoice" // Report type filter (null or blank for all types)
);Report types represent categories of reports and can be used for report discovery and UI organization.
// Get all report types from default workspace
ReportType[] reportTypes = client.getReportTypes(null).get();
// Get report types from specific workspace
WorkspaceKey workspace = new WorkspaceKey(456);
ReportType[] workspaceTypes = client.getReportTypes(workspace).get();
// Each ReportType includes:
// - code: unique identifier
// - name: human-readable name
// - description: type description
// - defaultReport: associated default report metadataThemes and report templates can be used as optional theme and template values when exporting or generating PDFs.
// Get all themes from default workspace
Theme[] themes = client.getThemes(null).get();
// Get themes from specific workspace
Theme[] workspaceThemes = client.getThemes(new WorkspaceKey(456)).get();
// Each Theme has: id (int), code (String), name (String)
// Get all report templates
ReportTemplate[] templates = client.getReportTemplates(null).get();
ReportTemplate[] workspaceTemplates = client.getReportTemplates(new WorkspaceKey("WS_CODE")).get();
// Each ReportTemplate has: id (int), code (String), name (String)var objectMapper = ObjectMapperUtility.getInstance();
String reportData = """
{
"sales": [
{ "region": "North America", "quarter": "Q1", "revenue": 1250000, "expenses": 830000 },
{ "region": "Europe", "quarter": "Q1", "revenue": 980000, "expenses": 640000 },
{ "region": "Asia", "quarter": "Q1", "revenue": 1520000, "expenses": 910000 }
],
"totals": {
"revenue": 3750000,
"expenses": 2380000,
"profit": 1370000
}
}
""";
String reportParams = """
{
"reportTitle": "Q1 Financial Overview",
"currency": "USD",
"preparedBy": "Finance Department",
"generatedOn": "2024-05-10T14:30:00Z",
"includeCharts": true
}
""";
// Convert the raw strings to JsonNodes
var dataJson = objectMapper.readTree(reportData);
var paramsJson = objectMapper.readTree(reportParams);
// Create a nonce token if generating a download link that will be accessed
// from an unauthorized client or sending a preview url to an iframe
String nonce = client.createNonceAuthToken().get().getNonce();
// The data can optionally be pushed to the server, using the tempDataService,
// where it will be stored temporarily and can be used as a datasource for the exported reports
var queryParams = new ReportQueryParams.Builder()
.params(paramsNode)
.data(dataNode)
.nonce(nonce) //optional
.theme("DARK") // optional: theme code for export styling
.template("INVOICE") // optional: report template code
.build();
// The download methods return the received HttpResponse<byte[]> and it is up to the user to process it as needed
var pdfResponse = client.downloadPdfAsync(new ReportParams(
new WorkspaceKey(33), // Workspace
new ReportKey(109), // Report template ID
queryParams
)).get();var queryParams = new ReportQueryParams.Builder()
.params(paramsNode)
.data(dataNode)
.theme("DARK") // optional
.template("INVOICE") // optional
.format(ExportFormat.HTML) // or any other supported format
...
.build();CompletableFuture<Workspace[]> workspaces = client.getWorkspacesAsync();String reportData = """
{
"sales": [
{ "region": "North America", "quarter": "Q1", "revenue": 1250000, "expenses": 830000 },
{ "region": "Europe", "quarter": "Q1", "revenue": 980000, "expenses": 640000 },
{ "region": "Asia", "quarter": "Q1", "revenue": 1520000, "expenses": 910000 }
],
"totals": {
"revenue": 3750000,
"expenses": 2380000,
"profit": 1370000
}
}
""";
var dataJson = objectMapper.readTree(reportData);
Integer tempDataId = client.pushTemporaryData(
dataNode,
OffsetDateTime.now().plusMinutes(10), // 10 minute expiration
new WorkspaceKey(33)
).get().getTempDataId();
var queryParams = new ReportQueryParams.Builder()
.params(paramsNode)
.tempDataId(tempDataId)
.build();This is recommended for larger reports which take a long time to export and can cause a connection timeout. This way, the export is being prepared in the background and once it is complete, the document can be fetched.
ExportParams supports optional theme and template (set via setters); they are sent in the request body only, not in the params dictionary.
// 1. Start the export with the configured parameters, workspace and report info
var response = client.startDocumentExport(workspaceKey, reportKey, params).get();
// 2. Check the export status
var status = client.getExportStatus(workspaceId, response.tempFileId).get();
// 3. If the status returns `completed` you can fetch the document
var documentHttpResponse = client.downloadCompletedFile(workspaceId, tempFileId).get();Jobs represent batch processing workflows that can generate multiple reports or perform automated tasks. Jobs can optionally require review before final delivery.
// Get all jobs from default workspace
Job[] jobs = client.getJobs(null).get();
// Get jobs from specific workspace
WorkspaceKey workspace = new WorkspaceKey(456);
Job[] workspaceJobs = client.getJobs(workspace).get();
// Each Job includes:
// - id: unique identifier
// - name: human-readable name
// - code: unique code identifier
// - description: job description
// - reviewRequired: whether review is needed before delivery
// - isActive: whether the job is currently active
// - lastRunTime: timestamp of the most recent executionExecute a job with custom parameters and data:
var objectMapper = ObjectMapperUtility.getInstance();
// Prepare job run parameters
String jobRunParams = """
{
"fiscalYear": 2024,
"department": "Sales",
"includeProjections": true
}
""";
String jobRunData = """
{
"employees": [
{ "id": 101, "name": "John Doe", "email": "john@example.com" },
{ "id": 102, "name": "Jane Smith", "email": "jane@example.com" }
]
}
""";
var paramsJson = objectMapper.readTree(jobRunParams);
var dataJson = objectMapper.readTree(jobRunData);
// Create job run request
JobRunRequest request = new JobRunRequest(paramsJson, dataJson);
// Start the job run
JobParams jobParams = new JobParams(
new WorkspaceKey(456), // Workspace
"MONTHLY_REPORT" // Job code or ID
);
JobRun jobRun = client.startNewJobRun(jobParams, request).get();
Integer jobRunId = jobRun.getJobRunId();Poll the job run status to track progress:
// Add job run ID to params
JobParams statusParams = new JobParams(
new WorkspaceKey(456),
"MONTHLY_REPORT",
jobRunId
);
// Check status
JobRunStatus status = client.getJobRunStatus(statusParams).get();
if (status.isFinished()) {
System.out.println("Job run completed!");
System.out.println("Status: " + status.getStatus());
System.out.println("Entries processed: " + status.getEntries().length);
} else {
System.out.println("Job run still in progress...");
}For jobs that require review, generate a consolidated document containing all job run entries:
JobParams reviewParams = new JobParams(
new WorkspaceKey(456),
"MONTHLY_REPORT",
jobRunId
);
// Generate review document (asynchronous)
AsyncReportGenerationResponse response = client.generateReviewDocument(reviewParams).get();
Integer tempFileId = response.getTemporaryFileId();
// Poll for completion
ReportExportStatusResponse exportStatus;
do {
Thread.sleep(2000); // Wait 2 seconds between checks
exportStatus = client.getExportStatus(456, tempFileId).get();
} while (!exportStatus.isCompleted());
// Download the completed review document
HttpResponse<byte[]> documentResponse = client.downloadCompletedFile(456, tempFileId).get();
byte[] documentBytes = documentResponse.body();
// Save to file
Files.write(Paths.get("review-document.pdf"), documentBytes);After reviewing and approving the job run, deliver all entries:
JobParams deliveryParams = new JobParams(
new WorkspaceKey(456),
"MONTHLY_REPORT",
jobRunId
);
Boolean delivered = client.jobRunDeliver(deliveryParams).get();
if (delivered) {
System.out.println("Job run delivered successfully!");
} else {
System.out.println("Delivery failed.");
}Here's a complete workflow combining all job operations:
// 1. List available jobs
Job[] jobs = client.getJobs(new WorkspaceKey(456)).get();
Job targetJob = Arrays.stream(jobs)
.filter(j -> j.getCode().equals("MONTHLY_REPORT"))
.findFirst()
.orElseThrow();
System.out.println("Starting job: " + targetJob.getName());
System.out.println("Review required: " + targetJob.isReviewRequired());
// 2. Start job run
JobRunRequest request = new JobRunRequest(paramsJson, dataJson);
JobParams jobParams = new JobParams(new WorkspaceKey(456), targetJob.getCode());
JobRun jobRun = client.startNewJobRun(jobParams, request).get();
// 3. Monitor progress
JobParams statusParams = new JobParams(
new WorkspaceKey(456),
targetJob.getCode(),
jobRun.getJobRunId()
);
JobRunStatus status;
do {
Thread.sleep(5000); // Poll every 5 seconds
status = client.getJobRunStatus(statusParams).get();
System.out.println("Status: " + status.getStatus());
} while (!status.isFinished());
// 4. If review is required, generate review document
if (targetJob.isReviewRequired()) {
AsyncReportGenerationResponse reviewResponse =
client.generateReviewDocument(statusParams).get();
// Wait for document generation
ReportExportStatusResponse exportStatus;
do {
Thread.sleep(2000);
exportStatus = client.getExportStatus(456, reviewResponse.getTemporaryFileId()).get();
} while (!exportStatus.isCompleted());
// Download review document
HttpResponse<byte[]> document =
client.downloadCompletedFile(456, reviewResponse.getTemporaryFileId()).get();
Files.write(Paths.get("review.pdf"), document.body());
System.out.println("Review document saved. Please review and approve.");
// After manual review and approval...
Boolean delivered = client.jobRunDeliver(statusParams).get();
System.out.println("Delivered: " + delivered);
} else {
// No review required, directly deliver
Boolean delivered = client.jobRunDeliver(statusParams).get();
System.out.println("Delivered: " + delivered);
}The CxReports API supports exporting reports in multiple formats depending on the use case.
Choose the format using the ExportFormat enum in the ReportQueryParams.
| Format | Enum Value | Typical Use Case |
|---|---|---|
ExportFormat.PDF |
Printable reports, invoices, contracts | |
| HTML | ExportFormat.HTML |
Embedding reports inside a web page or portal |
| Excel (XLSX) | ExportFormat.XLSX |
Tabular data for financials, KPIs, or further analysis |
| Word (DOCX) | ExportFormat.DOCX |
Narrative reports, proposals, documentation |
| PowerPoint | ExportFormat.PPTX |
Slide-based presentations, board reports |
For generating individual reports on-demand:
- Prepare report data and parameters
- Use
downloadPdfAsync()or other format-specific methods - Process the returned
HttpResponse<byte[]>
For generating multiple reports in a single operation:
- List available jobs with
getJobs() - Start a job run with
startNewJobRun() - Monitor progress with
getJobRunStatus() - If review is required:
- Generate review document with
generateReviewDocument() - Download and review the consolidated document
- Approve and deliver with
jobRunDeliver()
- Generate review document with
- If no review is required, directly call
jobRunDeliver()
For reports that may timeout due to size or complexity:
- Start export with
startDocumentExport() - Poll status with
getExportStatus() - Download when complete with
downloadCompletedFile()
This library is licensed under the MIT License.
For any issues or questions, contact support@cx-reports.com or visit our documentation at https://docs.cx-reports.com.