Hi community,
We’re working on a web integration between Epicor and a web-based CRM, and we’re wondering if it’s possible to develop and run the Print Preview function using the REST API.
Our goal is to generate the PDFs and display them in additional browser tabs from the CRM
Your toughts?
klincecum
(Kevin Lincecum)
June 16, 2025, 7:09pm
2
Probably, but would you mind explaining that more?
Randy
(Randy Stulce)
June 16, 2025, 7:10pm
3
What is going to be “printing” these reports Epicor or your CRM? If Epicor, have you done a trace to see what BO and methods it calls?
Sure! We’re integrating a web-based CRM with Epicor using the REST API. As part of the process, we want to trigger the Print Preview functionality for reports or forms (like invoices, orders, etc.) directly through the API.
The goal is to generate the PDF output that Epicor usually produces when you click “Print Preview” inside the system, and then display that PDF in a new browser tab on the CRM side.
Is there a way to call that specific print/preview action or retrieve the PDF through a REST endpoint?
klincecum
(Kevin Lincecum)
June 16, 2025, 7:23pm
6
The gist is, you call the rundirect endpoint for that report, and add some identifying info to the tasknote.
You retrieve it after it is finished. You can return it a myriad of ways.
Best option is to make a function that does it, and returns the payload as a base64 string.
Excellent! Let’s try that to see how it works, I’ll let you know about the progress
klincecum
(Kevin Lincecum)
June 16, 2025, 7:59pm
8
Here is you a good start.
ofloresgrim.efxj (4.3 KB)
//Simple Example Sales Order Ack
byte[] reportPDF = null;
CallService<Erp.Contracts.SalesOrderAckSvcContract>(soa =>
{
string taskNote = Guid.NewGuid().ToString(); //Magic
Erp.Tablesets.SalesOrderAckTableset salesOrderAckTS = soa.GetNewParameters();
Erp.Tablesets.SalesOrderAckParamRow paramRow = salesOrderAckTS.SalesOrderAckParam.First();
paramRow.OrderNum = soNum;
paramRow.AgentID = "SystemTaskAgent";
paramRow.AutoAction = "SSRSGENERATE";
paramRow.ReportStyleNum = reportStyleNum;
paramRow.TaskNote = taskNote;
soa.RunDirect(salesOrderAckTS);
//Query Syntax
reportPDF = (from sysRpt in Db.SysRptLst
join sysTask in Db.SysTask on
new {sysRpt.Company, sysRpt.SysTaskNum} equals
new {sysTask.Company, sysTask.SysTaskNum}
where
sysTask.TaskNote == taskNote
select
sysRpt.RptData).FirstOrDefault();
/*
//Method Syntax
reportPDF = Db.SysRptLst
.Join(Db.SysTask,
sysRpt => new { sysRpt.Company, sysRpt.SysTaskNum },
sysTask => new { sysTask.Company, sysTask.SysTaskNum },
(sysRpt, sysTask) => new { sysRpt, sysTask })
.Where(x => x.sysTask.TaskNote == taskNote)
.Select(x => x.sysRpt.RptData)
.FirstOrDefault();
*/
});
if(reportPDF != null)
{
//pdfB64 = Convert.ToBase64String(reportPDF).Substring(0, 50); //Debug only (return 50 characters)
pdfB64 = Convert.ToBase64String(reportPDF);
}
cormsby
(Chris Ormsby)
March 17, 2026, 3:16pm
9
Affirming that klinecums solution is the way to go as of 3/26, especially for cloud. Epicors built in endpoints that seem like they would facilitate this, specifically GetReports, appear to have some security built in that requires you to actually be logged into the environment or the calls bounce externally.
I am working on job travelers but it’s basically the same situation.
klincecum
(Kevin Lincecum)
March 17, 2026, 3:30pm
10
I have a slightly different method I can post later.
klincecum
(Kevin Lincecum)
March 17, 2026, 4:25pm
11
You can do it entirely with the Business Objects if you’d like.
byte[] reportPDF = null;
string taskNote = Guid.NewGuid().ToString(); //Magic
CallService<Erp.Contracts.SalesOrderAckSvcContract>(soa =>
{
Erp.Tablesets.SalesOrderAckTableset salesOrderAckTS = soa.GetNewParameters();
Erp.Tablesets.SalesOrderAckParamRow paramRow = salesOrderAckTS.SalesOrderAckParam.First();
paramRow.OrderNum = soNum;
paramRow.AgentID = "SystemTaskAgent";
paramRow.AutoAction = "SSRSGENERATE";
paramRow.ReportStyleNum = reportStyleNum;
paramRow.TaskNote = taskNote;
soa.RunDirect(salesOrderAckTS);
});
long sysTaskNum = 0;
CallService<Ice.Contracts.SysTaskSvcContract>( st =>
{
sysTaskNum = st.GetList( $"TaskNote = '{taskNote}'", 0, 0, out _ ).SysTaskList.FirstOrDefault().SysTaskNum;
});
CallService<Ice.Contracts.ReportMonitorSvcContract>( rm =>
{
var rptSysRowID = rm.GetList( $"SysTaskNum = {sysTaskNum}", 0, 0, out _ ).SysRptLstList.FirstOrDefault().SysRowID;
reportPDF = rm.GetReportBytes(rptSysRowID);
});
if(reportPDF != null)
{
//pdfB64 = Convert.ToBase64String(reportPDF).Substring(0, 50); //Debug only (return 50 characters)
pdfB64 = Convert.ToBase64String(reportPDF);
}
GabeFranco
(Gabriel Franco)
March 17, 2026, 5:17pm
12
I used the little bookmark icon for the first time ever for your post!