Integrate External Services using Lightning Flow

As you know there are various ways of invoking the external APIs or Services. In Almost all integration techniques, we need a bit of code. In this post we are going to discuss how integration to external systems from Salesforce can be accomplished without writing code. This is a complete declarative approch of doing callouts from Salesforce.

Use Case:

Let’s assume there is a external Order management application.

Scenario 1: When a customer contacts call center agent to inquire about his/her order, the agent will fetch the order status from this external service and inform the customer. Scenario 2: When agent/back office user updates the order status to “Ready to be Delivered” in SFDC, integration process will update the Order status in External application.

Steps to be followed to achieve this:

  1. Schema Definition of External Service
  2. Create Named Credential
  3. Register External Service
  4. Use External Service in Flow

Schema Definition for External Service

Schema the specification of the rest based API of the External Services Provider. It includes :

  1. Logical structure of endpoints
  2. Authentication Parameters
  3. HTTP method name such as GET, POST
  4. Request and Response body
  5. Error/Exception information.

 Interagent hyper-schema using JSON or Swagger Open API 2.0 can be used to create or update schema

Here, I have used https://app.mocklab.io/ as the external API server to mock the Schema and APIs. Both the Schema and APIs are hosted in this mock server. Below code block is the schema definition which is accessible via https://milan.mocklab.io/orders/schema. You can create your own account in mocklab and use it (14 days trial period). If you want to use some existing schema definition, you can use https://petstore.swagger.io/v2/swagger.json

{
  "swagger": "2.0",
  "host": "milan.mocklab.io",
  "basePath": "/",
  "info": {
    "version": "1.0",
    "title": "External Service for OrderManagement",
    "description": "### External Service for Order Management",
    "x-vcap-service-name": "OrderManagementRestServices"
  },
  "securityDefinitions": {
    "basicAuth": {
      "type": "basic"
    }
  },
  "security": [
    {
      "basicAuth": []
    }
  ],
  "tags": [
    {
      "name": "OrderManagementRestServices"
    }
  ],
  "paths": {
    "/orders/{orderNumber}": {
      "get": {
        "operationId": "getOrder",
        "summary": "Retrieves an Order",
        "description": "Retrieves the Order with specific order number",
        "consumes": [
          "text/plain"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "orderNumber",
            "in": "path",
            "required": true,
            "type": "string",
            "description": "OrderNumber of the order"
          }
        ],
        "responses": {
          "200": {
            "description": "The response when system finds an Order with given orderNumber",
            "schema": {
              "$ref": "#/definitions/orderDetails"
            }
          },
          "400": {
            "description": "Error response if the order number parameter is less than minimum characters",
            "schema": {
              "$ref": "#/definitions/errorModel"
            }
          },
          "404": {
            "description": "Error response if the order is not supported by service or order is not found",
            "schema": {
              "$ref": "#/definitions/errorModel"
            }
          }
        }
      },
      "put": {
        "operationId": "updateOrder",
        "summary": "Updates an Order",
        "description": "Updates the Order with specified status",
        "consumes": [
          "text/plain"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "orderNumber",
            "in": "path",
            "required": true,
            "type": "string",
            "description": "OrderNumber of the Order"
          },
          {
            "name": "orderStatus",
            "in": "query",
            "required": true,
            "type": "string",
            "description": "The status of order"
          }
        ],
        "responses": {
          "200": {
            "description": "The response when system finds an Order with given orderNumber",
            "schema": {
              "$ref": "#/definitions/orderDetails"
            }
          },
          "400": {
            "description": "Error response if the order number parameter is less than minimum characters",
            "schema": {
              "$ref": "#/definitions/errorModel"
            }
          },
          "404": {
            "description": "Error response if the order is not supported by service or order is not found",
            "schema": {
              "$ref": "#/definitions/errorModel"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "orderDetails": {
      "required": [
        "orderNumber",
        "status",
        "shippingMethod",
        "expectedDeliveryDate"
      ],
      "properties": {
        "orderNumber": {
          "type": "string",
          "description": "Order Number"
        },
        "status": {
          "type": "string",
          "description": "Order Status"
        },
        "shippingMethod": {
          "type": "string",
          "description": "Shipping Method"
        },
        "expectedDeliveryDate": {
          "type": "string",
          "description": "Expected Delivery Date"
        }
      }
    },
    "errorModel": {
      "required": [
        "errorCode",
        "errorMessage"
      ],
      "properties": {
        "errorCode": {
          "type": "string",
          "description": "A service-specific error code."
        },
        "errorMessage": {
          "type": "string",
          "description": "A service-specific error code."
        }
      }
    }
  }
}

Create Named Credential

The Url of the Named credential is the host which is mentioned in the schema. No Authentication is selected in this example, but in real implentations the authentication protocol needs to be selected based on what the External Service Provider supports.

Register External Service.

While registering External service, two important information to be filled in.
a) Named Credential. The one created in the above step.
b) Either Service schema relative url or Complete JSON need to be given in order to create APEX actions. Here in my example, I have given relative URL which is “/orders/schema”.
Upon Save, Apex actions will be generated. Screenshot is given below.

Invocation of External Service from Flow.

Two flows are created for the two tasks listed below.
  1. Fetch Order Status.
  2. Update Order Status
While creating flow most important element to consider is Action element. While creating new Action either we can filter by Category or Type.
If Category is selected, it will show the external service name Ex. OrderManagementService, then the next step to select the apex actions. Ex. getOrder or updateOrder.
If we filter by Type then navigation will be like this. Type -> External Service -> Select the Apex Action.
Please see the video recording of these flows how it works.I have used Screen flow(User Initiated) but Auto lunched flow can also be used depending on the use case.
Flow Recording

Thank you for visitng our blog, pleave leave your feedback/questions in the comment section.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.