Tutorial: Flow External Services for Salesforce Admins
Tags: salesforce, database, api, tutorial
Published: 2020-01-30 14:21:51

---
title: "Tutorial: Flow External Services for Salesforce Admins"
description:  "Another GIF-filled magic trick"
published: true
tags: salesforce,databases,api,tutorial
cover_image: https://katiekodes.com/images/header-flowexternal-20200130.png
canonical_url: https://katiekodes.com/flow-external-services/
---

Who remembers my [#GIFSquad](https://twitter.com/hashtag/gifsquad)-friendly [Salesforce Flow project from last summer, teaching Apex-Defined Data Types](https://katiekodes.com/flow-apex-defined-data-types/#flow-action)?  I just learned that you can build the same project in Flow _**without**_ writing any Apex code!

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-02-arrow-architecture.png)

![screenshot](https://katiekodes.com/images/screenshot-flowapexdefined-20-run.png)

We'll build the same Flow as before, but with _**almost no code**_.

## Business purpose

I picked this technique up from Liz Skaates, a senior product manager at Salesforce, during the [Spring '20 Admin Preview video](https://www.salesforce.com/video/8176624/), so check it out if you haven't yet.

On a desktop, navigate to "Critical Updates & External Services" and start at 2:08.  On mobile, jump to 17:45.

> **In the real world**, Liz suggests using this to integrate Salesforce with serious 3rd-party "APIs" like from Slack, the enterprise chat room company.
> 
> For example, she points out that you could post a message containing relevant Salesforce data to a Slack chat room every time a certain type of business process happens within your Salesforce org.

* **Q:**  Want to see how she does that?
* **A:**  Watch her in the release video -- she has a powerful demo.  ðŸ’ªðŸ¼

_(Pssst -- other Flowtastic Spring '20 release videos:  [Flow for 90 minutes](https://www.salesforce.com/video/8176628/), [Dev w/ 12 minutes of Flow](https://www.salesforce.com/video/8176623/).)_

## Disclaimer

Disclaimer:  As I said, this is **almost** no-code.

* **_Technically_**, you have to copy and paste a snippet of code, provided by a 3rd party _(like Slack)_.
* **_But_** it's no more complicated than grabbing the snippet of HTML code that YouTube makes available when you click "Embed this video."

The code you'll be copying and pasting is called a "schema."  A "schema" specifies to your flow how the 3rd-party "API" you're using wants to be talked to, and how it will respond.

In that way, it functions like the Apex-Defined Data Types and Apex Invocable Action code we hand-wrote [in the original post](https://katiekodes.com/flow-apex-defined-data-types/#flow-action).  The difference is that this time, we don't have to write it.

* _(If the 3rd-party company forgot to write a schema, it **is** possible to write one yourself.  That's what I had to do for the YesNo silly GIF service so that you could follow along in this tutorial.  It might take a developer's comfort with code, though, to write it in a way that is [compatible with Salesforce External Services](https://trailhead.salesforce.com/en/content/learn/modules/external-services/define-a-schema-for-an-external-service).)_

For all practical purposes -- particularly with real-world "APIs" from major companies -- what you're about to read is **no-code**.

---

## TL, DR

**External Services** use a small amount of "copy-and-paste" **code that someone else wrote** to let admins building Flows create **business logic that talks to non-Salesforce computers over the internet**.

Keep reading to try it yourself with an amusing side project.

---

## Silly GIFs

As before, it sure would be nice if we could leverage _amazing code other people have put on the internet_ to do something fun with a Flow, right?

### About YesNo

We'll leverage a really fun "API" on the internet called "YesNo."

According to its [documentation](https://yesno.wtf/#api), an [HTTP `GET` request](https://katiekodes.com/http-intro/#2---method) to `https://yesno.wtf/api` will [respond](https://katiekodes.com/http-intro/#3---body) with plain text formatted according to the [JSON](https://katiekodes.com/intro-xml-json-6/) standard indicating:

1. A random yes/no/maybe answer, labeled "`answer`"
2. A true/false indicating whether we forced the answer to a specific yes/no/maybe value, labeled "`forced`"
3. The URL to a random GIF expressing the yes/no/maybe emotion returned, labeled "`image`"

Here's an example:

```json
{"answer":"no","forced":false,"image":"https://yesno.wtf/assets/no/27-8befe9bcaeb66f865dd3ecdcf8821f51.gif"}
```

YesNo has _dozens_, if not _hundreds_, of silly GIFs, so it's endless fun hitting "refresh."

> **Note:**  Want a little extra geekiness when you're done with this project?
> 
> * [Learn what an API is](https://katiekodes.com/introduction-salesforce-rest-apis/#3--call-a-3rd-partys-endpoint-living-outside-salesforce) _(in this case, we're talking about the 3rd option)_.
> * [Learn about the "request-response" structure of the HTTP(s) protocol](https://katiekodes.com/http-intro) that makes "APIs" work.
> * [Earn the Trailhead badge](https://trailhead.salesforce.com/en/content/learn/modules/external-services?trail_id=force_com_admin_intermediate)

### Let's build a flow

We'll incorporate this data into a **Screen Flow** that looks different every time we run it.

This time, instead of asking YesNo for a silly GIF by incorporating an "**Apex Action**" into our Flow, we'll do it by incorporating an "**External Service Action**" into our Flow.

#### Security

First, we need to tell Salesforce that it's safe to talk to 3rd-party resources starting with `https://yesno.wtf`.

1. Outside of Flow Builder, in Salesforce **Setup**, search for and visit "**Named Credentials**."
2. Click "**New Named Credential**."
3. Enter something useful like `YesNo` into "**Label**" and "**Name**."
4. Enter `https://yesno.wtf` in "**URL**."
5. Leave "**Certificate**" blank.
6. Choose "`Anonymous`" for "**Identity Type**."
	* _(YesNo's "API" doesn't require you to log into it to use it.)_
7. Choose "`No Authentication`" for "**Authentication Protocol**."
	* _(YesNo's "API" doesn't require you to log into it to use it.)_
8. Leave "**Generate Authorization Header**" un-checked.
	* _(YesNo's "API" doesn't require you to log into it to use it.)_
9. Leave "**Allow Merge Fields in HTTP Header**" and "**Allow Merge Fields in HTTP Body**" un-checked.
10. Click "**Save**."

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-04-named-credential.png)

**Warning:**  In theory, one day YesNo could be taken over by hackers and start delivering viruses instead of fun GIFs.

You might want to **delete** this entry from your **Named Credentials** after you're done playing so you don't forget you put it here.

#### Behind-the-scenes data processing

Second, we need to teach Salesforce [how YesNo works](#about-yesno) _(that is, we need to teach it that the "[body](https://katiekodes.com/http-intro/#3---body)" of a YesNo "[response](https://katiekodes.com/http-intro/#responses)" is made up of 3 parts:  "`answer`," "`forced`," and "`image`")_.

1. Outside of Flow Builder, in Salesforce **Setup**, search for and visit "**External Services**."
2. Click "**Add an External Service**."
3. Enter something useful like `YesNo` into "**External Service Name**."
4. Pick the Named Credential you just set up, by the "Name" value you gave it, in "**Select a Named Credential**."
5. In the gray box at the bottom of the editor, change the radio box to use the "**Service Schema Complete JSON**" option.
6. In the text area below "**Service Schema Complete JSON**", paste the following "schema" code, then click "**Save**," and if further prompted, click "**Done**:"
	_(As mentioned before, this code is what teaches your Flow how YesNo works.)_

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-05-external-service.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-06-external-service-done.png)

```json
{
  "swagger": "2.0",
  "info": {
    "description": "This is a sample server YesNo server.  You can find out more about     Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  Katie Kodes wrote it.",
    "version": "99.9.9",
    "title": "YesNo"
  },
  "host": "yesno.wtf",
  "tags": [
    {
      "name": "api",
      "description": "The only endpoint YesNo offers",
      "externalDocs": {
        "description": "Find out more",
        "url": "https://yesno.wtf/#api"
      }
    }
  ],
  "schemes": [
    "https"
  ],
  "paths": {
    "/api": {
      "get": {
        "tags": [
          "api"
        ],
        "summary": "Seek a random yes, no, or maybe",
        "operationId": "seekAnswer",
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "force",
            "in": "query",
            "description": "Use this to force one of the 3 valid answers",
            "required": false,
            "type": "string",
            "enum": [
              "yes",
              "no",
              "maybe"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "$ref": "#/definitions/YesNoMaybe"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "YesNoMaybe": {
      "type": "object",
      "required": [
        "answer",
        "forced",
        "image"
      ],
      "properties": {
        "answer": {
          "type": "string",
          "description": "yes, no, or maybe",
          "example": "yes",
          "enum": [
            "yes",
            "no",
            "maybe"
          ]
        },
        "forced": {
          "type": "boolean",
          "description": "Did you force the answer with a query parameter?",
          "example": false
        },
        "image": {
          "type": "string",
          "description": "The URL to a random GIF of a celebrity expressing the answer",
          "example": "https://yesno.wtf/assets/no/13-755222c98795431aa2e7d453ab1e75a1.gif"
        }
      }
    }
  },
  "externalDocs": {
    "description": "Find out more about YesNo",
    "url": "https://yesno.wtf/#api"
  }
}
```

> **Note:**  Sometimes, a 3rd-party "API" will provide you the convenience of hosting a URL with their "schema" code published within, rather than making you copy and paste code.  That's what the "**Service Schema Relative URL**" option is for, as opposed to the "**Service Schema Complete JSON**" option, in the External Service definition screen.

**Warning:**  Again, in theory, one day YesNo could be taken over by hackers and start delivering viruses instead of fun GIFs.

You might want to **delete** this entry from your **External Services** after you're done playing so you don't forget you put it here.

#### Flow action

Third ... we're ready to start building our Flow.

1. Back in Flow Builder, start with a new **Screen Flow** so you have a clean design area with nothing but a "Start" node.
	* _If you already had Flow Builder open before you built out the Named Credential and the External Service, you might need to close and re-open it._
2. Click **Toolbox -> Elements** and drag an "**Action**" onto the flow builder.
3. Click into the "**Search All actions...**" box and start typing "`Yes`."  As the search results narrow down, choose "`seekAnswer`." _(It has a subtitle of `externalService-YesNo.seekAnswer`.)_
	* **Q:**  Why "`seekAnswer`?"
	* **A:**  Because that's what I named it in the copy-paste "schema" code I gave you above, and now you're stuck with it.  ðŸ˜œ
4. Give the Action a "**Label**" of "Ask The Internet Yes or No" and let Salesforce generate an "**API Name**" _(it will be "`Ask_The_Internet_Yes_or_No`")_.
5. In the lower portion of the Action definition area, under "**Set Input Values**," make sure that "`force`" has its toggle-switch _(at right)_ turned **off** _(grayed out, not blue, and slid to the left, and reading "**Don't Include**")_.
6. Leave "**Manually assign variables (advanced)**" un-checked.  You don't need it.
7. Click "Done."

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-10-new-action.png)

#### Text template

To make our image link show up as an actual image, we have to wrap it in a little bit of HTML.  For that, we need a **Text Template**.

1. Click **Toolbox -> Manager -> New Resource**
2. Drop down "**Resource Type**" and choose "**Text Template**"
3. Give it a nice "**API name**" like `viewable_gif`
4. In "**Body**," drop down the "down-arrow" picklist indicator **to the right of** the "**Insert a resource...**" box and change from "Rich Text" to "**Plain Text**."
5. In "Text Template," in the big text-editor area **below** "**Insert a resource...**," type `<img src="{!Ask_The_Internet_Yes_or_No.200.image}">`
6. Click "Done" 

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-14-new-text-template-picklist.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-15-new-text-template-picklist.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-16-new-text-template-picklist.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-17-new-text-template-picklist.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-18-new-text-template-picklist.png)

#### Screen
1. Click **Toolbox -> Elements** and drag a "**Screen**" onto the flow builder.
2. Give the "**Screen Properties**" a "**Label**" of "`GIF Squad Heaven`" and let Salesforce generate an "API Name."
3. Drag a "Text"-typed "**Screen Component**" onto the screen and give it a "**Label**" of "`Mood`."  Let Salesforce generate an "API Name."
4. Click the box below "**Default Value**," scroll down into the "**Actions**," click `Outputs from Ask_The_Internet_Yes_or_No`, click `2001, and click "answer."  Salesforce will populate the box with `{!Ask_The_Internet_Yes_or_No.200.answer}`.
5. Drag a "Display Text"-typed "Screen Component" onto the screen and give it a good API name like `the_gif`.
6. Click the "Insert a resource..." box and, under "Text Templates," choose `viewable_gif`.  Salesforce will populate the box with `{!viewable_gif}`.
7. Click "Done."

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-25-screen-text.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-26-screen-text.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-27-screen-text.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-28-screen-text.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-30-screen-image.png)



#### Watch the fireworks

1. In the flow builder, add arrow connectors flowing from `Start` to the `Ask The Internet Yes or No` action and onward to the `GIF Squad Heaven` screen.
2. Click "Save"
3. Click "Run"
4. Refresh the page that pops up a few times until you're satisfied that your Flow is randomly picking a GIF every time you run it.

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-32-link-run.png)

![screenshot](https://katiekodes.com/images/screenshot-flowapexdefined-18-run.png)

![screenshot](https://katiekodes.com/images/screenshot-flowapexdefined-19-run.png)

![screenshot](https://katiekodes.com/images/screenshot-flowapexdefined-20-run.png)

---

## Silly GIFs -- choose your own answer

Fun, right?

![GIF of Kamala Harris dancing](https://media.giphy.com/media/PgzSQB84aSzmvwWTmk/giphy.gif)

But I mentioned earlier that YesNo allows you to "force" a specific yes/no/maybe answer.

Let's have some fun and try that.

For simplicity's sake, we'll hand-type a specific answer into the Flow, but of course in the real world, you could use data out of your Salesforce org or the value of a variable from within your Flow.

### Edit the Flow Action

1. Click **Toolbox -> Manager**, scroll to **Elements -> Actions**, and click `Ask_The_Internet_Yes_or_No` to bring it up for editing.  _(Alternatively, double-click the icon for the action in your Flow Builder panel.)_
2. In the lower portion of the Action definition area, under "**Set Input Values**," make sure that "`force`" has its toggle-switch _(at right)_ turned **on** _(blue, slid to the right, and reading "**Include**")_.
3. In the "**Enter value or search resources...**" box beneath the word "`force`," type "`maybe`" in all lower-case letters.
4. Click "Done"

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-40-edit-action.png)

### Watch the fireworks

1. In the flow builder, click "Save" to save the latest version of your flow.
2. Click "Run"
3. Refresh the page that pops up a few times until you're satisfied that your Flow is randomly picking a GIF associated with the word "**maybe**" every time you run it.

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-32-link-run.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-43-maybe.png)

![screenshot](https://katiekodes.com/images/screenshots/screenshot-flow-ext-services-2020-01/screenshot-flow-external-services-44-maybe.png)

[Let me know](https://twitter.com/katiekodes/) -- did you get it to work??

![GIF from Kim's Convenience](https://media.giphy.com/media/1YdaQRsI2AMDTSfpgk/giphy.gif)



---

![](https://katiekodes.com/images/shoppingbags.jpg)

## Takeaway

**External Services** make an **Admin's** life easier when trying to **talk to a 3rd-party service over the internet** in a **Flow**.

**Warning:**  Don't go crazy with this functionality without researching good **security** practices.

* Putting things from strangers' "APIs" into the web pages your Salesforce users will be looking at is a bit like accepting candy from a stranger.
* Sending strangers' "APIs" your Salesforce data is a bit like giving a stranger your credit card number.

There are a lot of principles that go into good security practices, but here are two to get you started:
1. Only use "API" URLs that start with "`httpS`," not plain-old "`http`."
2. Only use "APIs" from companies you trust ... which includes trusting their ability to protect themselves from getting hacked.
	* In a real org, as fun as it is, YesNo is probably a little too small-time to trust.