Automation

Warning

This feature is currently in beta and may be subject to change. Before using it in production, please contact your Socotra representative.

Overview

The Automation Plugin allows you to implement custom business logic, create your own Socotra API endpoints, define request and response objects, and send HTTP requests to both third-party and Socotra API endpoints.

The Automation Plugin is the only plugin that can call Socotra API endpoints directly and define custom request and response objects. This allows implementing teams to address most automation, integration, and orchestration requirements directly within the core platform.

Automation Plugin code can be executed manually via API endpoints or in response to events that occur within the Socotra Insurance Suite.

We strongly recommend reviewing the Configuration SDK guide before using this feature.

Note

The Automation Plugin currently supports API calls only via the Java HttpClient. A Socotra API-specific client is planned for a future release to simplify consuming Socotra API endpoints.

Use Cases

The automation plugin supports a wide variety of use cases. Some examples include:

  • Bulk ingestion of data from CSV and other file formats

  • Generating and attaching documents such as certificates of insurance or delinquency notices

  • Updating staticData

  • Monitoring, reporting, and analytics

Configuring the Automation Plugin

The Automation Plugin can be configured in the tenant configuration using the following folder structure: socotra-config/automations/PluginName/config.json. You can also configure the automation plugin in the root-level config.json file within the socotra-config folder in the tenant configuration.

Here’s an example of the folder structure:

Automation Plugin Directory Structure

In the example above, the AttachDocument and PolicyRenewal folders refer to the names of your automation plugin implementations. You can create as many implementations as you’d like. Each implementation can contain multiple actions, which correspond to method names in your Java implementation classes.

Here’s an example of a config.json file for the AttachDocument implementation:

{
    "actions": {
        "attachCertificateOfInsurance": {
            "timeout": 3,
            "request": {
                "contactName": {
                    "displayName": "Contact Name",
                    "type": "string"
                },
                "policyNumber": {
                    "displayName": "Policy Number",
                    "type": "string"
                }
            },
            "response": {
                "result": {
                    "displayName": "Result",
                    "type": "boolean",
                    "defaultValue" : "true"
                }
            }
        },
        "attachReport": {
            "timeout": 10,
            "request": {
                "reportType": {
                    "displayName": "Report Type",
                    "type": "string"
                },
                "reportName": {
                    "displayName": "Report Name",
                    "type": "string"
                }
            },
            "response": {
                "result": {
                    "displayName": "Result",
                    "type": "boolean",
                    "defaultValue" : "true"
                }
            }
        }
    }
}

In the example above, attachCertificateOfInsurance and attachReport are the names of actions available within the AttachDocument implementation, and each action specifies fields within the request and response objects. If request or response objects are not defined, they will not be included in the method signature for a given action.

Refer to the Data Extension Types guide for a comprehensive list of field types for request and response objects. Request and response objects currently do not support the scope data type property.

Once you’ve finished making changes to your configuration, execute the refreshReferenceDatamodel Gradle task. This will generate a Java interface for each of your implementations.

Note

If your tenant configuration has never been deployed, you will first need to deploy your configuration by executing the deployConfigToTenant task at least once before you can begin executing the refreshReferenceDatamodel task.

Implementing the Automation Plugin

Create a new Java class in the src/main/java/com/socotra/deployment/customer folder using the following naming convention for the class name: PluginNameAutomationPluginImpl. You can name your class whatever you’d like, but we suggest following this naming convention. Your Java implementation classes must be contained within this folder.

Here’s an example of the AttachDocumentAutomationPluginImpl class for the AttachDocument implementation:

package com.socotra.deployment.customer;

import com.socotra.deployment.plugins.PluginExecutionContext;
import com.socotra.deployment.plugins.AutomationPluginContextData;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AttachDocumentAutomationPluginImpl implements AttachDocumentAutomationPlugin {
    private static final Logger log = LoggerFactory.getLogger(AttachDocumentAutomationPluginImpl.class);

    @Override
    public AttachDocumentAttachCertificateOfInsuranceResponse attachCertificateOfInsurance(AttachDocumentAttachCertificateOfInsuranceRequest attachDocumentAttachCertificateOfInsuranceRequest) {
        PluginExecutionContext context = PluginExecutionContext.get();
        AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();
        log.info("In AttachDocumentAutomationPluginImpl.attachCertificateOfInsurance()");
        log.info("Request fields: {} {}", attachDocumentAttachCertificateOfInsuranceRequest.contactName(), attachDocumentAttachCertificateOfInsuranceRequest.policyNumber());
        log.info("Context: {} {} {} {}", context.getRequestId(), context.getTenantLocator(), context.getBusinessAccount(), automationContext.secret());
        return new AttachDocumentAttachCertificateOfInsuranceResponse().builder().result(true).build();
    }

    @Override
    public AttachDocumentAttachReportResponse attachReport(AttachDocumentAttachReportRequest attachDocumentAttachReportRequest) {
        PluginExecutionContext context = PluginExecutionContext.get();
        AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();
        log.info("In AttachDocumentAutomationPluginImpl.attachReport()");
        log.info("Request fields: {} {}", attachDocumentAttachReportRequest.reportType(), attachDocumentAttachReportRequest.reportName());
        log.info("Context: {} {} {} {}", context.getRequestId(), context.getTenantLocator(), context.getBusinessAccount(), automationContext.secret());
        return new AttachDocumentAttachReportResponse().builder().result(true).build();
    }
}

The example above demonstrates how to access request fields, PluginExecutionContext data, and AutomationPluginContextData data. Response objects can be created using the builder pattern.

The request and response classes are generated automatically using the following naming conventions: PluginNameActionNameRequest and PluginNameActionNameResponse.

HTTP requests can be performed using the Java HttpClient. Refer to the Plugins Overview for more information.

Once you’ve finished making changes to your implementations, execute the deployConfigToTenant Gradle task. This will generate an API endpoint for each action defined in your implementations.

Creating an Event-Driven Automation Plugin

Automation plugins can be configured to execute in response to events that occur within the Socotra Insurance Suite. Only one implementation can be configured as event-driven.

To designate an implementation as event-driven, add the following field to your automation plugin configuration.

For example:

{
    "enableWebhooks": true
}

Execute the refreshReferenceDatamodel Gradle task to update the interface for your implementation.

Override the handleWebhookEvent method in your implementation.

For example:

@Override
 public void handleWebhookEvent() {
     PluginExecutionContext context = PluginExecutionContext.get();
     AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();
     log.info("In AttachDocumentAutomationPluginImpl.handleWebhookEvent()");
     log.info("context: {} {} {} {}", context.getRequestId(), context.getTenantLocator(), context.getBusinessAccount(), automationContext.secret());
     log.info("context: {}", automationContext.eventData());
 }

Event-driven actions cannot have request and response objects. Context data can be retrieved from the PluginExecutionContext and AutomationPluginContextData classes.

Lastly, call the Create Webhook API endpoint to create a webhook for your event-driven action setting the useAutomationPlugin flag to true.

Here’s an example request:

{
    "name": "Attach Document Webhook",
    "useAutomationPlugin": true,
    "enabled": true,
    "eventTypes": [
        "policy.account.create",
        "policy.account.update",
        "policy.account.validate",
        "policy.quote.create",
        "policy.quote.update",
        "policy.quote.validate",
        "policy.quote.price",
        "policy.quote.underwrite",
        "policy.quote.accept",
        "policy.quote.refuse",
        "policy.quote.discard",
        "policy.quote.manualunderwrite",
        "policy.quote.reset",
        "policy.quote.issue"
    ],
    "failureHandling": {
        "removeAlertEndpoint": false,
        "alertEndpoint": {
            "url": "https://webhook.develop.socotra.com/cf276a2e-f48d-449d-9279-a1faf24ba51a",
            "headers": {
                "single": 0
            }
        },
        "triggers": [
            "4xx",
            "5xx",
            "timeout"
        ],
        "retryStrategy": {
            "type": "linear",
            "interval": 1000,
            "attempts": 3
        },
        "divert": false,
        "suspend": false
    }
}

Unlike a regular webhook, this webhook does not send a request to an external API endpoint. It executes the handleWebhookEvent action instead.

Executing the Automation Plugin

After deploying your implementations, execute your automation plugin actions by sending a GET or POST request to the API endpoints generated using the following naming convention: plugin/{tenantLocator}/automation/{pluginName}/{actionName}.

In general, it doesn’t matter whether you send a GET request or a POST request. The only difference between these request methods is that GET requests require a response object to be defined.

Here’s an example of a JSON request object for the attachReport action:

{
    "reportType": "Regulatory",
    "reportName": "GDPR Compliance"
}

Configuring Secrets

By default, the token that was used to send a request to an automation plugin API endpoint will be available in the accessToken field within the AutomationPluginContextData class.

Additional secrets can be included in the AutomationPluginContextData class by adding the following field to an automation plugin configuration:

{
    "secret": "ExternalService"
}

In the example above, ExternalService refers to the name of a SecretRef key that must be specified in the tenant configuration, as well as the name of a folder located in socotra-config/secrets within the tenant configuration, which contains the following config.json file:

{
    "items": {
        "url": {
            "dataType": "string"
        },
        "apiToken": {
            "dataType": "string"
        },
        "timeOutSeconds": {
            "dataType": "int"
        }
    }
}

Execute the refreshReferenceDatamodel Gradle task to generate the Java class containing your secrets.

The url, apiToken, and timeOutSeconds fields can now be accessed through the AutomationPluginContextData class:

PluginExecutionContext context = PluginExecutionContext.get();
        AutomationPluginContextData automationContext = context.getAutomationPluginContext().orElseThrow();

var mapper = AbstractDeploymentFactory.defaultMapper();
ExternalService externalService = mapper.convertValue(automationContext.secret().get(), ExternalService.class);

The values for these fields can be set using the Secrets API.

Error Handling

By default, if an exception is encountered while executing an automation plugin, an HTTP status code of 500 will be returned. You can return specific HTTP status codes and error messages by throwing an AutomationPluginException:

throw new AutomationPluginException(500, "Error Message");

Refer to the Webhooks guide for information on defining error-handling strategies for webhooks.

Logging

The Logging API can be used to view the history of automation plugin executions. For executions triggered via API requests, the pluginType will be displayed as automationHttp. For executions triggered via webhooks, the pluginType will be displayed as automationWebhook.

See Also