Hi Creatio Community,

We're encountering a puzzling issue on a Freedom UI List Page (specifically, our Invoices_ListPage) when trying to run a business process (IWVoid_API_POST) using a custom JavaScript handler. The goal is to test the business process by explicitly passing a hardcoded InvoiceId, as requested for a specific testing scenario where the button is not on the individual record's form page.

Our Setup:

  1. The Button (Menu Item on List Page's ActionButton):

    We've added a crt.MenuItem to the ActionButton on our Invoices_ListPage. This menu item is intended for testing and is configured to trigger a custom handler:

    JSON

     

    // In viewConfigDiff of Invoices_ListPage.js
    {
        "operation": "insert",
        "name": "TargetVoidButton", //
        "values": {
            "type": "crt.MenuItem",
            "caption": "Test Void BP (Hardcoded ID)", 
            "icon": "debug-icon",
            "visible": true,
            "clicked": {
                "request": "crt.HandleButtonClickRequest",
                "params": {
                    "buttonName": "RunTargetVoidProcessHandler" 
                }
            }
        },
        "parentName": "ActionButton",
        "propertyName": "menuItems",
        "index": 3 
    }
  2. The Handler (in handlers array of Invoices_ListPage.js):

    This handler is designed to run the IWVoid_API_POST process with a specific, hardcoded InvoiceId.

    JavaScript

     

    // In handlers array of Invoices_ListPage.js
    {
        request: "crt.HandleButtonClickRequest",
        handler: async (request, next) => {
            if (request.buttonName === "RunTargetVoidProcessHandler") { 
                console.log("RunTargetVoidProcessHandler triggered.");
                Terrasoft.showInformation("Test: Running process with hardcoded ID. Check console.");
     
                const processName = "IWVoid_API_POST";
                const hardcodedInvoiceIdForTest = "3c2b6d9f-4c1e-4364-99f2-53956562b606"; 
                const parameterNameInProcess = "InvoiceId"; 
     
                console.log(`Test: Attempting to run BP '<span class="math-inline">\{processName\}' with EXPLICIT HARDCODED ID '</span>{hardcodedInvoiceIdForTest}' for parameter '${parameterNameInProcess}'.`);
     
                try {
                    const response = await request.$context.executeRequest({
                        type: "crt.RunBusinessProcessRequest",
                        params: {
                            processName: processName,
                            processParameters: {
                                [parameterNameInProcess]: hardcodedInvoiceIdForTest
                            },
                            saveAtProcessStart: false, 
                            showNotification: true 
                        }
                    });
     
                    console.log("Test: BP execution request completed. Response:", response);
     
                    if (response && response.success === true && response.processId && response.processId !== '00000000-0000-0000-0000-000000000000') {
                        const successMsg = `Test: BP '${processName}' (ID: ${response.processId}) initiated. Check Process Log.`;
                        console.log(successMsg);
                        request.$context.showInformationDialog?.(successMsg);
                    } else {
                        let errorMsg = `Test: Failed to start BP '${processName}'.`;
                        let serverDetails = (response && response.errorInfo && response.errorInfo.message) ? response.errorInfo.message : "Details unavailable or process not found (zero ID / success:false).";
                        errorMsg += ` ${serverDetails}`;
                        console.error(errorMsg, "Full response:", response);
                        request.$context.showErrorDialog?.(errorMsg);
                    }
                } catch (error) {
                    console.error(`Test: Exception for BP '${processName}':`, error);
                    let exceptionMsg = (error instanceof Error && error.message) ? error.message : "Client-side exception.";
                    if (error.errorInfo && error.errorInfo.message) {
                        exceptionMsg = error.errorInfo.message;
                    }
                    request.$context.showErrorDialog?.(`Test: Error triggering BP: ${exceptionMsg}`);
                }
                return; 
            }
            return next?.handle(request);
        }
    }

The Problem:

When we click the "Test Void BP (Hardcoded ID)" menu item, the handler triggers, and the client-side logs show the crt.RunBusinessProcessRequest is being prepared correctly with processName: "IWVoid_API_POST" and the hardcoded InvoiceId.

However, the server responds with:

{
  processId: '00000000-0000-0000-0000-000000000000', 
  processStatus: 0, 
  resultParameterValues: null, 
  executionData: null, 
  success: false, 
  errorInfo: {
    errorCode: "ItemNotFoundException",
    message: "Item process schema \"\" not found.", // Note the empty quotes for schema name
    stackTrace: null
  }
}

The key error is <strong>Item process schema "" not found.</strong>

What We've Tried:

  • Confirmed the schematic name (Code) of our business process is indeed IWVoid_API_POST.
  • Confirmed the input parameter in the BP designed to take the ID is named InvoiceId.
  • Repeatedly saved, compiled, and published the IWVoid_API_POST business process and ensured it's marked as "Active."
  • Checked the package containing the process for any errors and recompiled the package.
  • Performed thorough browser cache clearing and hard refreshes (Ctrl+F5).
  • We also have another menu item on the same list page ("VoidInvoice") that uses a declarative crt.RunBusinessProcessRequest with processRunType: "ForTheSelectedRecords" and parameterMappings: { "InvoiceId": "Id" }. When a record is selected and this menu item is clicked, it successfully starts the <strong>IWVoid_API_POST</strong> process (verified in Creatio Process Log with a non-zero instance ID). This makes the current error even more puzzling.

Our Questions for the Community:

  1. Why would the ProcessEngineService report Item process schema "" not found (with empty quotes for the schema name) when the processName: "IWVoid_API_POST" is explicitly and correctly provided in the params of crt.RunBusinessProcessRequest from our custom handler?
  2. Is there any known difference in how process names are resolved or how schemas are looked up by the server when crt.RunBusinessProcessRequest is invoked programmatically from a handler with processParameters explicitly set (using a hardcoded ID), versus when it's invoked declaratively with processRunType: "ForTheSelectedRecords" or processRunType: "ForTheSelectedPage"?
  3. Are there any deeper caching mechanisms (server-side, metadata) or specific registration steps for business process schemas that we might be missing, which could lead to this behavior only for the explicit parameter call?
  4. Has anyone encountered a similar situation where a process is findable/runnable via one SDK invocation method (declarative, context-based) but not another (programmatic handler, explicit parameters) from the same Freedom UI page type?

We are unable to access detailed server-side application logs for this specific environment at the moment, which is hampering deeper diagnosis from our end.

Any insights, suggestions, or similar experiences would be greatly appreciated!

Thank you!

Like 0

Like

1 comments

Hi Andrew,

The behavior you described where the system responds with Item process schema "" not found despite providing the correct process name can occur when certain required parameters are missing during the execution of a business process from a handler. Specifically, when using crt.RunBusinessProcessRequest from a crt.HandleButtonClickRequest handler, the backend expects additional context that is typically provided automatically during declarative invocations.

To ensure that the process schema is correctly identified and executed, it is important to explicitly include the processRunType, the recordIdProcessParameterName. These parameters provide the necessary linkage between the UI context and the process runtime.

Below is an example of a working implementation where a business process is successfully launched from a button on a Freedom UI page. The button configuration and handler explicitly define all required fields:

Button configuration:
{
 "operation": "insert",
 "name": "Button_7y0uys4",
 "values": {
   "layoutConfig": {
     "column": 1,
     "row": 2,
     "colSpan": 1,
     "rowSpan": 1
   },
   "type": "crt.Button",
   "caption": "#ResourceString(Button_7y0uys4_caption)#",
   "color": "outline",
   "disabled": false,
   "size": "large",
   "iconPosition": "only-text",
   "visible": true,
   "clicked": {
     "request": "crt.HandleButtonClickRequest",
     "params": {
       "buttonName": "RunTestProcess",
       "processName": "UsrTestProcessInvoiceAdded",
       "processRunType": "ForTheSelectedPage",
       "recordIdProcessParameterName": "InvoiceId"
     }
   }
 },
 "parentName": "SideAreaProfileContainer",
 "propertyName": "items",
 "index": 1
}

Handler logic:
{
 request: "crt.HandleButtonClickRequest",
 handler: async (request, next) => {
   if (request.buttonName === "RunTestProcess") {
     const handlerChain = sdk.HandlerChainService.instance;
     const result = await handlerChain.process({
       type: "crt.RunBusinessProcessRequest",
       processName: "UsrTestProcessInvoiceAdded",
       processRunType: "ForTheSelectedPage",
       recordIdProcessParameterName: "InvoiceId",
       $context: request.$context
     });

     if (result.success) {
       console.log("The process was successfully executed!");
     } else {
       console.log("Exception: " + (result.errorInfo?.message || "Unknown issue"));
     }

     return;
   }
   return next?.handle(request);
 }
}

Answers to your questions:

1. Why would the ProcessEngineService report Item process schema "" not found (with empty quotes for the schema name) when the processName: "IWVoid_API_POST" is explicitly and correctly provided in the params of crt.RunBusinessProcessRequest from our custom handler? 

- This usually happens if processRunType, recordIdProcessParameterName are not passed when triggering the process from a handler. These parameters are essential for correctly resolving the process schema in the runtime context.

2. Is there any known difference in how process names are resolved or how schemas are looked up by the server when crt.RunBusinessProcessRequest is invoked programmatically from a handler with processParameters explicitly set (using a hardcoded ID), versus when it's invoked declaratively with processRunType: "ForTheSelectedRecords" or processRunType: "ForTheSelectedPage"? 

- Yes. In declarative calls, Creatio automatically adds all required metadata. In programmatic calls (handlers), this metadata must be passed manually, especially processRunType and recordIdProcessParameterName.

3. Are there any deeper caching mechanisms (server-side, metadata) or specific registration steps for business process schemas that we might be missing, which could lead to this behavior only for the explicit parameter call? 

- In general, no special registration is required if the process is active and compiled. However, if the process was recently created or modified, reload the page and make sure that the changes in the process were saved.

4. Has anyone encountered a similar situation where a process is findable/runnable via one SDK invocation method (declarative, context-based) but not another (programmatic handler, explicit parameters) from the same Freedom UI page type?

- Yes, this can happen if the required context parameters are not included in the handler call. Declarative calls handle this automatically, whereas in handlers you must explicitly set them.

Show all comments

Hi community,

I have a lead form with an option of uploading of a file. How can I transfer the uploaded file to a Lead record (or record of another object) in Creatio with help of Creatio API? 

Like 0

Like

1 comments

Hello, 

below is the instruction to File management API for your referrence: 

https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/8.1/back-end-development/api-for-file-management/overview

 

Thank you for reaching out!

Show all comments

Hi.  

Has anyone connected Qlik to Creatio?

I see that Creatio has a REST API, but is that the preferred (or only) method to connect a BI tool such as Qlik?

We need to use Qlik to create reports for other teams that don't have Creatio access.

 

Thanks!

Rob

Like 0

Like

5 comments
Best reply

Given your extensive investment in Qlik and the need to integrate it with data from Creatio, we recommend using Creatio’s REST API over OData for this integration.

While both options are available, the REST API offers several key advantages:

1) Better performance: REST is more efficient and lightweight, especially when handling large datasets.

2) Greater flexibility: you can define exactly what data is needed and apply filtering or transformations before it's sent to Qlik.

3) While OData comes with various preconfigured options, REST allows you to easily customize the requests

OData can be used for basic, read-only access, but it's generally more rigid and less performant — especially when dealing with high-volume analytics scenarios like yours.

Have a nice day!

Hello!

 

Creatio does not officially support Qlik. The only way to integrate Qlik with Creatio is by using the Creatio OData or REST API.

 

As an alternative, we can recommend using Power BI marketplace addon: https://marketplace.creatio.com/app/microsoft-power-bi-desktop-connector-creatio

 

Have a nice day!

We have heavily invested in Qlik as our BI tool (and have hundreds of users).  Our task is to connect finance data with the sales data we have in Creatio.
We have an IT team that can set up the connection so I assume they are familiar with connectors like REST API, but would you recommend using ODate over REST API ?

Given your extensive investment in Qlik and the need to integrate it with data from Creatio, we recommend using Creatio’s REST API over OData for this integration.

While both options are available, the REST API offers several key advantages:

1) Better performance: REST is more efficient and lightweight, especially when handling large datasets.

2) Greater flexibility: you can define exactly what data is needed and apply filtering or transformations before it's sent to Qlik.

3) While OData comes with various preconfigured options, REST allows you to easily customize the requests

OData can be used for basic, read-only access, but it's generally more rigid and less performant — especially when dealing with high-volume analytics scenarios like yours.

Have a nice day!

Hi.   

(I'm not the dev that's going to do this, but ...) 

If we create an OData connection with Qlik,  are there already some methods in place so that Qlik automatically sees all data and tables in Creatio?  Or do we need to build out methods to see specific data?

Or, perhaps it's worth buying a Creatio OData connector that has all this built out already?  (If there is such a thing)

Thanks
Rob

Actually, the better question around how the BI (in my case Qlik) works with the data --

When we build out the OData datasource that Qlik will connect to, we need to specify each table that should be "available" to Qlik, true?  (There is no "include all tables" I assume.)
Ideally, we want all data from all tables, then in Qlik we will do the filtering of which data is needed on each report.

Or am I way off here?  


 

Show all comments

Hello Team, 
I have Some Questions : 

1. What are the recommended approaches for API call logging in Cloud Creatio? 
2. Are there built-in tools or features I can use?
3. Can you suggest any third-party solutions or best practices? 
Any insights or experiences you can share would be greatly appreciated.

Like 0

Like

1 comments

Greetings!
 

There are a few options:

Log directly inside the handler — meaning you implement the logging yourself.


Log via a Script Task into a custom database table.

Log by sending data to an external web service.


Unfortunately, we don’t have any built-in methods for this — everything needs to be implemented by the developers of the service (i.e., the API side).

Show all comments

Full requirement is 
 


Have 4 widgets and Global Area

Each Widgets calls behind the scene API with one key that is present in the global Area

Present that data in the widget

Now each widget can be consider as Page -- 

Now how easily create Page which invokes API and dispaly -- if API is returning 10 or so parameter do we need to create manually the page and have items and map items to API return value

Like 0

Like

5 comments

In order to display the result of the API call on the widget you will have to create the custom widget and implement the API call for retrieving necessary data in its source code. The key from Global area that will be used for calling the API you can send to your custom widget as a parameter. Also in custom widget configuration you will have to define "items" list that will represent the structure of the data you want to display. When the API call returns the result you will have to parse it and map to the corresponding columns in widget ViewModel.

You can find the detailed explanation and the example of custom widget implementation in the following article
https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platform/8.1/platform-customization/classic-ui/dashboard-widgets/examples/add-a-dashboard-widget

Hi thanks 

Widget is more of data view (list / form) 
Page will not have any backend data connected

Currently it's not possible to display API call result in List component on the page.

 

If you want to display API call result on the page you can add the custom attributes to your page, save the parsed response there and then bind the attributes to the labels on the page to make it visible.

 

Here is the example of the attribute:

 

viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[
...
	{
		"operation": "merge",
		"path": ["attributes"],
		"values": {
			"MyAttrubute": { "value": "" }
		}
	}
]/**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/

 

and how you can set its value using the response from API call:

 

handlers: /**SCHEMA_HANDLERS*/[
	{
		request: "crt.HandleViewModelResumeRequest",
		handler: async (request, next) =&gt; {
			await next?.handle(request);       
			const url = 'https://open.er-api.com/v6/latest/USD';
			fetch(url).then(response =&gt; {
   				if (!response.ok) {
					return Promise.reject('Failed to load data: ' + response.statusText);
				}
 				return response.json();
			}).then(data =&gt; {
				request.$context.MyAttrubute = 'Rates: '+ JSON.stringify(data.rates);
			}).catch(error =&gt; {
				console.error('Error:', error);
			});
		}
	}
]/**SCHEMA_HANDLERS*/

 

 

Also you can find some useful information in these articles:

https://customerfx.com/article/using-custom-attributes-on-a-creatio-freedom-ui-page/

https://customerfx.com/article/binding-data-to-labels-on-a-page-in-crea…

THANKS -- wish there is way to invoke a business process with UI page value passed as parameters 

One question for the above method with handler the API call will be made from the client end -- wanted it to be done from server end (this way we can whitelist creatio iP range and only allow calls from those servers only)

 

Show all comments

I need to import the tables into Power BI. I've tried using the 'Connector' and I've also tried using the API. And yes, I did everything according to the documentation.

 

When trying to use the 'Connector', I used the "Creatio.GetBigData" instruction, which according to the documentation is appropriate for obtaining large tables. However, it doesn't work, because it keeps giving me a credential error and constantly asking me to enter my credentials. And if my credentials are accepted, it takes many hours to import a table. This connector doesn't work at least for importing large tables. And let's face it, in 99% of cases the tables are large with much... much more than 20 thousand rows. In other words, this connector doesn't work for 99% of cases.

 

When trying to use the API, the same thing happens, because I can't import a table with more than 20 thousand records at once, and when trying to use pagination to import a few records at a time, the process takes me several hours to completely import a single table. This is not productive, it is tiring and takes up a lot of my time to do something that should be simple.

 

I am being charged to bring CRM data into Power BI, please can someone help me?

Like 0

Like

1 comments

Hi Raí,

The GetBigData and GetBigTopData functions were created as a workaround for the limitation of 20k records imposed by OData when attempting to download table data. The actual function used for data retrieval is GetData.


These functions enable you to download a snapshot of the table, bypassing the 20k record restriction. However, it's still necessary to apply a filter that ensures fewer than 20k records are retrieved in the process.

As a solution, we recommend using a regular database backup. After obtaining a copy of the database, you can restore it locally and configure Power BI to connect to this local DB copy. This approach will be much faster, more convenient, and ultimately easier for you.

Regarding the "credential error", I'd recommend you delete all connections from "Data source settings" menu. It might reset all previously entered credentials.

Show all comments

Hello,

 

I am trying to upload files as you would do manually in the browser, but using an API. When dragging and dropping a file into the attachments tabs of any section, I see in the browser that Creatio performs a POST request to its FileApiService with a format like the following example:

 

The endpoint is https://my-creatio-site.creatio.com/0/rest/FileApiService/UploadFile and the file content is passed in the request body.

 

In order to simulate this behavior, I am sending 2 requests:

 

  1. A POST request to create the file id allocating space in the File table:

  2. A POST request to https://my-creatio-site.creatio.com/0/rest/FileApiService/UploadFile using the file information to upload the actual file.

 

However as you can see, the 2nd request fails in my app with the following error:

{
  "errorInfo": {
    "errorCode": "InvalidFileSizeException",
    "message": "No se puede analizar el tamaño del archivo.",
    "stackTrace": "   at Terrasoft.Configuration.FileUpload.FileUploadInfo.get_TotalFileLength()\r\n   at Terrasoft.Configuration.FileUpload.FileUploader.UploadFile(IFileUploadConfig fileUploadInfoConfig)\r\n   at Terrasoft.Configuration.FileUpload.FileUploader.UploadFile(IFileUploadInfo fileUploadInfo, Boolean isSetCustomColumns)\r\n   at Terrasoft.Configuration.FileApiService.UploadFile(Stream fileContent)"
  },
  "success": false,
  "nextPrcElReady": false,
  "queryId": null,
  "responseStatus": {
    "ErrorCode": "InvalidFileSizeException",
    "Message": "No se puede analizar el tamaño del archivo.",
    "StackTrace": "   at Terrasoft.Configuration.FileUpload.FileUploadInfo.get_TotalFileLength()\r\n   at Terrasoft.Configuration.FileUpload.FileUploader.UploadFile(IFileUploadConfig fileUploadInfoConfig)\r\n   at Terrasoft.Configuration.FileUpload.FileUploader.UploadFile(IFileUploadInfo fileUploadInfo, Boolean isSetCustomColumns)\r\n   at Terrasoft.Configuration.FileApiService.UploadFile(Stream fileContent)",
    "Errors": null,
    "Meta": null
  },
  "rowsAffected": -1
}

 

I already ensured that the file size passed in both requests is exactly the same always (in this example is 584833 bytes) but I don't know what causes the error.

 

I already checked the following community posts but couldn't find any help:

 

 

Note: I tested these requests in many Creatio websites, all of them with version 8.2.0 

 

Regards.

Like 0

Like

2 comments

Hello again,

 

I just found a different community post:

https://community.creatio.com/questions/get-error-403-denied-when-uploading-file-filepiservice

 

After following the steps explained by @Ryan Farley I was able to upload files properly. My problem was that I was missing the following request headers:

 

  • Content-Range = bytes 0-{size in bytes - 1}/{size in bytes}
  • Content-Type = "application/octet-stream"

 

Thank you very much!

Glad you found the older post and have it working now!

Show all comments

Hi everyone,

I'm working with Creatio CRM and need to trigger an approval process via API. I have a custom object called EpbSolicitudes, and each request has a unique ID (e.g., 1e80cd00-2cf4-4ecc-a61c-511d7afa3568).
 

My goal is to invoke the approval action programmatically using an API call. Specifically, I want to:

  1. Approve a request via API (either updating the status or calling a process).
  2. Ensure that the approval follows the same workflow as if it were done manually.
  3. Optionally, trigger a BPMN process if needed.
     

I've explored the OData 4 API and DataService API, but I'm unsure of the best approach to handle approvals.

  • Should I update the "NextStep" field in EpbSolicitudes using OData?
  • Is there a built-in API method to invoke the approval process?
  • Can I start an approval process via ProcessEngineService API?

If anyone has experience with automating approvals in Creatio via API, I would appreciate any guidance or examples.
 

Thanks in advance! 🚀

Like 0

Like

1 comments

Hello,

 

If your approval is created using a business process, you can trigger the business process using the ProcessEngineService.svc service https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platfor…

Show all comments

Hi Creatio Community,

 

I'm currently working with batch operations in Creatio and have successfully tested some requests that are working fine.

 

I have a question regarding inserting column values that reference other tables by their respective columns. Specifically, I need to perform operations on a large number of columns and data, which could be time-consuming if I have to manually map the IDs based on their codes.

 

Is there a more efficient way to handle this?

 

Here’s an example of a request I’m working with:

{
	"requests": [
	{
		"method": "POST",
		"atomicityGroup": "g1",
		"url": "City",
		"id": "t3",
		"body": {
			"Name": "TestName",
            "Country.Code": "USA"
		},
		"headers": {
			"Content-Type": "application/json;odata=verbose",
			"Accept": "application/json;odata=verbose",
			"Prefer": "continue-on-error"
		}
	}
	]
}
Like 1

Like

1 comments

Hello,

Creating operations on a large number of columns and data, which could be time-consuming, may lead to performance problems in the future. Please try to avoid big batch operations so as not to face the situation of 100% server CPU utilization.

As a workaround:

  1. You may create a custom Web service and pass the needed data to it.
  2. Create a business process that proceeds with needed data modifications

 

Show all comments

The client wants to use Consimple messenger connector for Creatio to send SMS within campaigns, but wants us to expose an API so they can connect their system with Consimple.

Do you know how I can do that?

Like 0

Like

3 comments

Hello,
It's necessary to contact Consimple to address this functionality. 
Consimple messenger connector for Creatio | Creatio Marketplace

It is already in the system with simple, do you know how I can configure it now, I have not found documentation

Hello,

 

We kindly recommend contacting the developer of the marketplace application at office@consimple.com. They will be able to provide you with detailed insights about the mechanism.

Show all comments