# Python -------------------------------------------------------------------------------- title: "Introduction" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.322Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/introduction/" service: "All Services" related: - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) - Java SDK (/en/sdk/java/v1/overview/) - Node.js SDK (/en/sdk/nodejs/v2/overview/) - Python SDK (/en/sdk/python/v1/overview/) -------------------------------------------------------------------------------- # Invoice Notifier ### Introduction In a fast-paced business environment, timely customer onboarding plays a key role in ensuring customer satisfaction. However, Customer Success teams often face delays due to a lack of real-time payment updates from billing applications. This tutorial demonstrates how you can use **Catalyst Signals** to bridge this gap and automate communication between decoupled systems. You will build an event-driven solution that listens to invoice updates from **Zoho Books**, filters the events based on payment status, and compiles a summary of paid invoices every hour. This summary will then be sent to a **Catalyst Event Function**, which will forward the report to your **Zoho Cliq** channel. The event automation uses components from the following Catalyst Services: **Catalyst Signals**: * **Publisher**: A primary source of events where they are generated when any action or change occurs in an application. * **Rules**: It is a statement that guides the ingestion of incoming events from Publisher to Target. **Catalyst Serverless**: * **Event Function**: It is an asynchronous task function that is associated with Catalyst Signals. An Event function is created to execute a task or a set of tasks on the occurrence of a specified event. We will use the Catalyst web console and the Catalyst Command Line Interface (CLI) to build this application. You will be given the code for the files to be included in the function components in this tutorial. You will just need to copy the code given here and paste it into the appropriate files as directed. ### Event Flow The architecture of the event flow in this use case is outlined below: - A customer makes a payment, **triggering an invoice update** in Zoho Books. This event is published to Catalyst Signals. - Signals applies a **filter** to include only invoices marked as *Paid*. The filtered event data is then transformed and batched. - **Every hour**, the **batched events** are delivered to a Catalyst Event Function. The function further processes the event data and sends as a **report to a Zoho Cliq channel**. <br /> -------------------------------------------------------------------------------- title: "Prerequisites" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.322Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/prerequisites/" service: "All Services" related: - CLI Command Reference (/en/cli/v1/cli-command-reference/) - Install CLI (/en/getting-started/installing-catalyst-cli/) - Login CLI (/en/cli/v1/login/login-from-cli/) - Zoho Books Organization Profile (https://www.zoho.com/in/books/help/settings/organization-profile.html) - Zoho Cliq Channels (https://www.zoho.com/cliq/help/channels/create-channel.html) - Zoho Cliq Bots (https://www.zoho.com/cliq/help/platform/managing-bots.html) -------------------------------------------------------------------------------- # Prerequisites Before you begin building the Invoice Notifier, you must have the following prerequisites installed on your system: ### 1. Catalyst CLI Catalyst CLI contains a host of tools that enable you to initialize, develop, test, and deploy the components of your application from your local machine. We will be working with Catalyst CLI in this tutorial. You must perform the following actions: 1. Install Catalyst CLI: Catalyst CLI is installed through NPM so you must have both NPM and Node.js installed beforehand. Refer to the **Install Catalyst CLI help page** for details on the pre-requisites and the steps to install it. 2. Login Catalyst CLI: After installation, you must authenticate the CLI with your Catalyst account before using it. Refer to the **CLI Login help page** for the steps to login from Catalyst CLI and the various options available for it. ### 2. Any IDE tool for Node.js and client code development Use any IDE that supports Python development like Visual Studio Code, IntelliJ, or Eclipse to work on the event function. If you are a Visual Studio Code IDE user, you can install the Catalyst Tools extension, and use your IDE itself in place of the CLI. You can find more details about the Catalyst VS Code extension from this help section. ### 3. Zoho Books for Invoice Management Create an organization in Zoho Books to maintain customer payment records in the form of invoices. Note: You can also integrate any third-party tools for invoice generation. However, if you choose to do so, you will need to configure a custom publisher in Catalyst Signals for the external application and update the rule accordingly. ### 4. Zoho Cliq for Team Notifications Create an organization in Zoho Cliq to act as internal communication platform for your Customer Success Team. Within this organization, - Create a Channel for updating invoice status of onboarding customers. Follow the steps given in the How to create a channel in Zoho Cliq help page for guidance. - Create and associate a bot to the channel so it can automatically post messages regarding the invoice updates. Refer to the Managing Bots and Bot Channel Participation help resources for guidance. For this tutorial, you don’t need to add or edit any handlers for the bot. Ensure that the required channel participation permissions are configured correctly while creating the bot, as shown in the image below. Note: You can also integrate any third-party tools for internal team communication. However, if you choose to do so, you will need to update the event function accordingly to route notifications to the appropriate communication channel. -------------------------------------------------------------------------------- title: "Create a Project" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.323Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/create-project/" service: "All Services" related: - Catalyst Console (/en/getting-started/catalyst-projects/) -------------------------------------------------------------------------------- # Create a Project Let’s create a Catalyst project from the Catalyst console. 1. Log in to the Catalyst console and click **Create New Project**. <br/> 2. Enter the project’s name as "**InvoiceNotifier**" in the pop-up window, and click **Create**. <br/> Your project will be created then opened. You can access the project later, by clicking **Access Project**. -------------------------------------------------------------------------------- title: "Add Publisher" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.323Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/configure-publisher/" service: "All Services" related: - Publishers (/en/signals/help/publishers/key-aspects/) -------------------------------------------------------------------------------- # Add Publisher Let us start by setting up a **Publisher** in the *InvoiceNotifier* project. This Publisher will listen for **Invoice Updated** events from **Zoho Books** and forward them to **Catalyst Signals**. Follow these steps to configure the Publisher: 1. Navigate to the **Catalyst Signals** section in the Catalyst Console and click **Start Exploring**. <br/> 2. Go to **Publishers** and click **Create Publisher**. <br/> 3. From the list of available Zoho Services, select **Zoho Books**. <br/> 4. You will be taken to a configuration page. Fill in the required details: - Set the **Publisher Name** and **API Name** as Zylker. - Select the desired Zoho Books org from the **Organization** dropdown. It will list only the organizations linked to the same email address you use to access the Catalyst Console. <br/> 5. Enable **Event Ordering** to ensure that events are delivered in the same order they are received. <br/> 6. Click **Save** to complete Setup and **Authorize** to use data from Zoho Books. <br/> Your Zoho Books Publisher is now ready to send invoice events to Catalyst Signals. -------------------------------------------------------------------------------- title: "Initialize the Project from CLI" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.323Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/initialize-project/" service: "All Services" related: - Initialize CLI Resources (/en/cli/v1/initialize-resources/introduction/) - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) -------------------------------------------------------------------------------- # Initialize the Project from the CLI You can now begin working on your Catalyst project from the CLI. The first step is to initialize the project in an empty directory. This will be the home directory of your project and all of the project files will be saved in it. You can learn more about this from the Project Directory Structure help page. You can learn about initializing a project in detail from the CLI help documentation. For this InvoiceNotifier, we will initialize an Event Function, which will contain the logic of the action that is required to occur once the event happens and a Basic web app as the client component. The event function will be initialized in the Python platform. However, you can also initialize it in the Java or Node JS platforms. Note: Ensure that you enter the function's package name or class name exactly as instructed, because the application's code contains the same name. 1. Create a folder for the project on your local machine and navigate to it from the terminal. 2. Initialize a project by executing the following command from that directory: catalyst init 3. Navigate using the arrow keys and select your preferred portal and press the Enter key. If you have no other organizations associated with the account, then the default one will be selected automatically. <br/> You can find out more about Catalyst's multi-org portal feature from this help document. 4. The CLI will now ask you to associate a Catalyst project with the directory. Associate it with the project that we created earlier from the console. Select *InvoiceNotifier* from the list and press Enter. <br/> 5. Select **Functions** using the space-bar, then press the **Enter** key to initialize. <br/> 6. The CLI will initiate the function setup. Select **Event** as the function type. <br/> 7. Select the latest runtime **Python** as the programming environment and Press **Enter**. <br/> 8. Enter **Cliq_Notifier** as the package name, "main.py" as the entry point, and press **Enter**. Alternatively, you can press **Enter** without entering inputs to fill in the default values. <br/> The Catalyst initialization is now complete. The project directory is now set up with the functions directory along with configuration files and dependencies. The project directory also contains the catalyst.json configuration file and a hidden .catalystrc file. The structure of your project directory should now appear as shown below: -------------------------------------------------------------------------------- title: "Register the Client" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.324Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/register-client/" service: "All Services" related: - Catalyst API Documentation (/en/api/introduction/overview-and-prerequisites/#OverviewandPrerequisites) -------------------------------------------------------------------------------- # Register the Client Application in Zoho API Console To enable secure and authorized communication between Catalyst and Zoho Cliq, you must register your client application in the Zoho API Console. This step is necessary to generate OAuth credentials that will be embedded in the Event Function code. By registering the client, you will receive the following: * Client ID: A unique identifier assigned to your registered application. * Client Secret: A confidential key used along with the Client ID to authenticate the client. We will use these credentials to generate the following OAuth tokens: * Grant Token (code): A temporary token generated using the Client ID and Client Secret in the API console. This is used to fetch the Refresh Token. * Refresh Token: A persistent token used to request new Access Tokens when the previous ones expire. We will generate this in the REST API client in the next step. * Access Token: A temporary token that authorizes Zoho Cliq API calls. You do not need to manually generate this, as it will be automatically handled using the Refresh Token during runtime. The Client ID, Client Secret, and Refresh Token are added to the Event Function code. They enable Catalyst to programmatically perform actions (like posting messages) in your Zoho Cliq channel. The function will use the Refresh Token to continuously retrieve fresh Access Tokens, ensuring uninterrupted connectivity between Catalyst and Cliq. To register the client application in Zoho API console: 1. Go to the Zoho API Console and click Get Started or Add Client. <br/> 2. Choose Self Client as the client type. Since both the Catalyst and the Cliq accounts are configured in the same organization, a Self Client can be used for this application. <br/> 3. In the popup, click Create to register your client. The API console will generate and display the Client ID and Client Secret values for the registered client. <br/> 4. Now, click the Generate Code tab to generate the Grant Token. - In the **Scope** field, enter: ZohoCliq.Webhooks.CREATE - Add a **Description** for the scope. - Set a **Time Duration** for the Grant Token. 5. Click Create. Once created, the Grant Token (code) will be displayed. Copy the generated Client ID, Client Secret, and Grant Token, and keep them ready. We will use these values in the upcoming step to generate the Refresh Token and configure the function files in the project. -------------------------------------------------------------------------------- title: "Generate the refresh token" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.324Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/refresh-token/" service: "All Services" related: - Catalyst API Documentation (/en/api/introduction/overview-and-prerequisites/#OverviewandPrerequisites) -------------------------------------------------------------------------------- # Generate Refresh Token Before configuring the function and client components, you need to generate a **Refresh Token**, which will be included in the function code to authorize interactions with Zoho Cliq. You can use any REST API client to perform this step. In this tutorial, we’ll walk you through the process using the Postman API platform. 1. Open your API client and create a new POST request to the following URL: * Request URL: https://<span></span>accounts.zoho.com/oauth/v2/token * Request Method: POST 2. Add the following keys and values as query parameters in your request: * code: The Grant Token or the value of code obtained during the client registration in the API console * client\_id: The Client ID that was generated during the client registration * client\_secret: The Client Secret that was generated during the client registration * grant\_type: authorization\_code (Provide this literal string as the value) 3. Send the request with the above parameters to the specified request URL. If the request is successful, you will receive a response that includes: access\_token, refresh\_token, api\_domain, token\_type, expires\_in. We only require the Refresh Token. A screenshot of this step using Postman is provided below to guide you through the request and response. 4. Copy the refresh\_token value from the response received. You’ll use this in the function code in the next step of the tutorial. -------------------------------------------------------------------------------- title: "Configure the Event function" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.325Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/configure-function/" service: "All Services" related: - Event Functions (/en/serverless/help/functions/event-functions/) - Functions Directory Structure (/en/cli/v1/project-directory-structure/functions-directory) -------------------------------------------------------------------------------- # Configure the Event Function Let us now configure the event function Cliq_Notifier, which automatically sends a message to a Zoho Cliq channel. This message will include the invoice details of new customers who have successfully completed their payment. The function will be executed when it is triggered by Catalyst Signals. The functions directory, functions/Cliq_Notifier contains: - The main.py main function file - The catalyst-config.json configuration file - The requirements.txt file to mention any external libraries that you might add. You will be adding code in the main.py file. Our function will require requests library and Catalyst SDK as dependencies for its efficient functioning. To install them, navigate to the function's directory (functions/Cliq_Notifier) and create a lib folder. Execute the following command from the lib folder: pip3 install requests zcatalyst-sdk -t . This will install the dependencies. Note: Please go through the code in this section to make sure you fully understand it. Copy the python code and paste it in main.py in the functions/Cliq_Notifier directory of your project, and save the file. You can use any IDE of your choice to work with the application's files. import sys sys.path.insert(0, 'lib') import logging import traceback import requests import zcatalyst_sdk logger = logging.getLogger() zbooksdomain = "{{YOUR_ZBOOKS_DOMAIN}}"; #Enter your ZohoBooks Domain based on your region zbooksorg = "{{YOUR_ZBOOKS_ORGANIZATION_ID}}" #Enter your ZohoBooks Organization Id zcliqdomain = "{{YOUR_ZCLIQ_DOMAIN}}"; #Enter your ZohoCliq Domain based on your region zcliq_channel_unique_name = "{{YOUR_CHANNEL_UNIQUE_NAME}}" #Enter the unique name of the channel where updates should be posted zcliq_bot_unique_name = "{{YOUR_BOT_UNIQUE_NAME}}" #Enter the unique name of the bot that will post the messages zaccountsdomain = "{{YOUR_ZACCOUNTS_DOMAIN}}" #Enter your ZohoAccounts Domain based on your region def handler(event, context): try: data = extract_invoice_data(event) rows = transform_invoice_data(data) request_body = prepare_cliq_request(rows) access_token = get_access_token() send_to_cliq(request_body, access_token) logger.info("Message pushed to channel successfully") context.close_with_success() except Exception as e: logger.error("An unexpected error occurred:\n%s", traceback.format_exc()) context.close_with_failure() def extract_invoice_data(event): event_payload = event.get_raw_data() data = event_payload.get("data") rows = [invoice for invoices in data for invoice in invoices] return rows def transform_invoice_data(rows): for row in rows: invoice_id = row.get("Invoice Id") row["Link"] = f"https://{zbooksdomain}/app/{zbooksorg}#/invoices/{invoice_id}" del row["Invoice Id"] return rows def prepare_cliq_request(rows): request_body = { "slides": [{ "type": "table", "data": { "headers": ["Customer", "Invoice Number", "Amount", "Paid On", "Link"], "rows": rows } }], "text": "Here are the invoices marked as Paid in the last hour:" } return request_body def get_access_token(): app = zcatalyst_sdk.initialize() connector_config = { "CliqConnector": { "client_id": "{{YOUR_CLIENT_ID}}", #Enter your Client ID "client_secret": "{{YOUR_CLIENT_SECRET}}", #Enter your Client Secret "auth_url": f"https://{zaccountsdomain}/oauth/v2/token", "refresh_url": f"https://{zaccountsdomain}/oauth/v2/token", "refresh_token": "{{YOUR_REFRESH_TOKEN}}" #Enter your Refresh Token } } connector = app.connection(connector_config).get_connector("CliqConnector") access_token = connector.get_access_token() return access_token def send_to_cliq(payload, access_token): cliq_channel_url = f"https://{zcliqdomain}/api/v2/channelsbyname/{zcliq_channel_unique_name}/message?bot_unique_name={zcliq_bot_unique_name}" headers = { "Content-Type": "application/json", "Authorization": f"Zoho-oauthtoken {access_token}" } response = requests.post(cliq_channel_url, headers=headers, json=payload) response.raise_for_status() Note: After you copy and paste the code into your function file, make sure to update the following placeholders with actual values, as indicated by the inline comments: - **Zoho Books Domain (line 11)**: Enter the domain corresponding to your **Zoho Books** organization, based on your region. Example: books.zoho.com, books.zoho.eu, or books.zoho.in - **Zoho Books Organization ID (line 12)**: Provide the unique Organization ID of your Zoho Books account. - **Zoho Cliq Domain (line 14)**: Specify the domain of your Zoho Cliq organization, based on your region. Example: cliq.zoho.com, cliq.zoho.eu - **Unique Name of your Zoho Cliq Channel (line 15)**: Enter the unique name of the Zoho Cliq channel where the paid invoice updates should be posted. - **Unique Name of your Zoho Cliq Bot (line 16)**: Provide the unique name of the Zoho Cliq bot that has been added to the above channel. - **Zoho Accounts Domain (line 18)**: Mention the Zoho Accounts domain used to log into Catalyst, Zoho Books, and Zoho Cliq. Example: accounts.zoho.com, accounts.zoho.in - **Client ID (line 70)**: Paste the Client ID obtained during client registration in Step 4. - **Cient Secret (line 71)**: Paste the corresponding Client Secret generated in Step 4. - **Refresh Token (line 74)**: Provide the Refresh Token you generated in Step 5 using your API client tool. The Event function is now configured. -------------------------------------------------------------------------------- title: "Deploy the Project" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.325Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/deploy-project/" service: "All Services" related: - Deploy CLI Resources (/en/cli/v1/deploy-resources/introduction/) - Web Client Hosting (/en/cloud-scale/help/web-client-hosting/introduction) -------------------------------------------------------------------------------- # Deploy the Project To deploy your Catalyst project from the CLI, run the following command in your terminal from your project directory: catalyst deploy The event function is now deployed to the console. -------------------------------------------------------------------------------- title: "Create a Rule" description: "Create an Event Driven Architecture to automate invoice updates from Zoho Books to Zoho Cliq using Event Functions and Catalyst Signals." last_updated: "2026-09-09T11:06:26.325Z" source: "https://docs.catalyst.zoho.com/en/tutorials/invoice-notifier/python/create-rule/" service: "All Services" related: - Publishers (/en/signals/help/publishers/key-aspects/) - Targets (/en/signals/help/targets/key-aspects/) - Rules (/en/signals/help/rules/key-aspects/) - Events (/en/signals/help/events/key-aspects/) - Event Functions (/en/serverless/help/functions/event-functions/) -------------------------------------------------------------------------------- # Create a Rule Now that the Publisher and the Event Function are configured, let us define how the events should be processed and delivered by setting up a Rule. Follow these steps to create the Rule: 1. In the Developer Console, select your project: *InvoiceNotifier*. 2. Go to **Catalyst Signals** and click on **Rules** in the left navigation. <br/> 3. Click **Add Rule**, then provide a name and description for your rule. <br/> ### Define Event Source 4. Under Source, click **Choose Event**, and select the Zoho Books Publisher you added earlier. 5. From the list of available events, choose *Customer Payment Created*, then click **Done**. <br/> ### Define Event Filter 6. In the Filter section, click the **edit icon** and choose **Events matching certain conditions**. <br/> 7. Create a filter condition to include only events where the invoice status is **Paid**: - In the Path dropdown, select the JSON path that corresponds to the **payment_status** field. - Define the condition to match Paid. 8. Click **Save** to apply the filter. <br/> ### Configure Target Settings 9. Click **Choose Target** and give your target a name. 10. Under **Consumer Type**, select the Event Function we created earlier using the CLI. 11. Set the **Dispatch Policy** to **Batch by Interval**: - Choose an interval of *one hour*. - Set the Retry Count to *five*. <br/> ### Transform the Payload 12. In the **Target Input** section, choose **Transform**. 13. From the default event payload of the *Customer Payment Created* event, select only the required data and structure them as shown below. { "data" : [ [ { "Customer" : "test", "Invoice Number" : "Customer opening balance", "Amount" : "₹3,24,244.00", "Paid On" : "31/10/2023", "Invoice Id" : "275557000000158181" } ] ] } { "data" : $.events.forEach((event)-> event.data.payment.invoices.forEach((invoice)-> { "Customer" : event.data.payment.customer_name, "Invoice Number" : invoice.invoice_number, "Amount" : invoice.total_formatted, "Paid On" : event.data.payment.date_formatted, "Invoice Id" : invoice.invoice_id } ) ) } Paste this structure into the template compiler to extract the required fields and click **Generate Output**. Check out the Even Body Transformation help guide to learn how to customize event payloads in detail. 14. Save the target configurations, then click **Save** again to finalize the rule. Now, whenever a customer completes a payment, the corresponding invoice in Zoho Books is updated. This update triggers an event that is processed every hour in Catalyst Signals and automatically sends a summarized message to the Zoho Cliq channel.