---
schema_version: "1"
id: 415759b17be9a1f3c1978e9e5f61932e7b64e75e1db618e977d7830b66cc6425
title: Example REST Activity
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/marketing-cloud/guides/mc-app-development/example-rest-activity.md
canonical_url: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/example-rest-activity.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: c8c4f91a7ca2e5fd65156be307c042f62b98b4d5290cebd08fcd414ba9422fd0
products:
  - Marketing Cloud Engagement APIs and Programmatic Languages
  - Marketing Cloud
---
# Example REST Activity

## config.json

```json
{
  "workflowApiVersion": "1.1",
  "metaData": {
    "icon": "images/sms.png",
    "category": "message"
  },
  "type": "REST",
  "lang": {
    "en-US": {
      "name": "REST Activity (Workflow API v1.1)",
      "description": "An example REST activity using workflow API v1.1 format."
    }
  },
  "arguments": {
    "execute": {
      "inArguments": [
        {
          "emailAddress": "{{InteractionDefaults.Email}}"
        },
        {
          "phoneNumber": "{{Contact.Default.PhoneNumber}}"
        }
      ],
      "outArguments": [
        {
          "foundSignupDate": ""
        }
      ],
      "url": "https://some-endpoint.com/execute"
    }
  },
  "configurationArguments": {
    "save": {
      "url": "URI/for/your/activity/save"
    },
    "publish": {
      "url": "URI/for/your/activity/publish"
    },
    "validate": {
      "url": "URI/for/your/activity/validate"
    },
    "stop": {
      "url": "URI/for/your/activity/stop"
    }
  },
  "wizardSteps": [
    { "label": "Step 1", "key": "step1" },
    { "label": "Step 2", "key": "step2" },
    { "label": "Step 3", "key": "step3" },
    { "label": "Step 4", "key": "step4", "active": false }
  ],
  "userInterfaces": {
    "configModal": {
      "height": 200,
      "width": 300,
      "fullscreen": true
    }
  },
  "schema": {
    "arguments": {
      "execute": {
        "inArguments": [
          {
            "phoneNumber": {
              "dataType": "Phone",
              "isNullable": false,
              "direction": "in"
            }
          },
          {
            "emailAddress": {
              "dataType": "Email",
              "isNullable": false,
              "direction": "in"
            }
          }
        ],
        "outArguments": [
          {
            "foundSignupDate": {
              "dataType": "Date",
              "direction": "out",
              "access": "visible"
            }
          }
        ]
      }
    }
  }
}
```

## index.html

Every custom activity must have an index.html in the root of its endpoint.

```html
<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Custom Journey Builder Activity</title>

    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/require.js"></script>
    <script type="text/javascript">
      (function () {
        var config = {
          baseUrl: "",
        };

        var dependencies = ["customActivity"];

        require(config, dependencies);
      })();
    </script>

    <!--Styles-->
    <style type="text/css">
      body {
        padding: 20px;
        margin: 0;
      }
      .step {
        display: none;
      }
      #step1 {
        display: block;
      }
    </style>
  </head>
  <body>
    <div id="step1" class="step">
      Select your SMS message:
      <select id="select1">
        <option value="">Select an option</option>
        <option value="someMessage">Some SMS</option>
        <option value="anotherMessage">Another SMS</option>
        <option value="thirdMessage">Third SMS</option>
        <option value="unknownMessage">Unknown SMS</option>
      </select>

      <button id="toggleLastStep">Toggle Last Step</button>
    </div>
    <div id="step2" class="step">
      Here's a second page with some info on it.
    </div>
    <div id="step3" class="step">
      You chose the message:
      <div id="message"></div>
    </div>
    <div id="step4" class="step">
      Hey, here's a fourth step, just for you. Toggle this on or off from step
      1.
    </div>
  </body>
</html>
```

## customActivity.js

Postmonger is required for communication between Journey Builder and the activity.

```javascript
define(["postmonger"], function (Postmonger) {
  "use strict";

  var connection = new Postmonger.Session();
  var payload = {};
  var lastStepEnabled = false;
  var steps = [
    // initialize to the same value as what's set in config.json for consistency
    { label: "Step 1", key: "step1" },
    { label: "Step 2", key: "step2" },
    { label: "Step 3", key: "step3" },
    { label: "Step 4", key: "step4", active: false },
  ];
  var currentStep = steps[0].key;

  $(window).ready(onRender);

  connection.on("initActivity", initialize);
  connection.on("requestedTokens", onGetTokens);
  connection.on("requestedEndpoints", onGetEndpoints);

  connection.on("clickedNext", onClickedNext);
  connection.on("clickedBack", onClickedBack);
  connection.on("gotoStep", onGotoStep);

  function onRender() {
    // JB will respond the first time 'ready' is called with 'initActivity'
    connection.trigger("ready");

    connection.trigger("requestTokens");
    connection.trigger("requestEndpoints");

    // Disable the next button if a value isn't selected
    $("#select1").change(function () {
      var message = getMessage();
      connection.trigger("updateButton", {
        button: "next",
        enabled: Boolean(message),
      });

      $("#message").html(message);
    });

    // Toggle step 4 active/inactive
    // If inactive, wizard hides it and skips over it during navigation
    $("#toggleLastStep").click(function () {
      lastStepEnabled = !lastStepEnabled; // toggle status
      steps[3].active = !steps[3].active; // toggle active

      connection.trigger("updateSteps", steps);
    });
  }

  function initialize(data) {
    if (data) {
      payload = data;
    }

    var message;
    var hasInArguments = Boolean(
      payload["arguments"] &&
        payload["arguments"].execute &&
        payload["arguments"].execute.inArguments &&
        payload["arguments"].execute.inArguments.length > 0
    );

    var inArguments = hasInArguments
      ? payload["arguments"].execute.inArguments
      : {};

    $.each(inArguments, function (index, inArgument) {
      $.each(inArgument, function (key, val) {
        if (key === "message") {
          message = val;
        }
      });
    });

    // If there is no message selected, disable the next button
    if (!message) {
      showStep(null, 1);
      connection.trigger("updateButton", { button: "next", enabled: false });
      // If there is a message, skip to the summary step
    } else {
      $("#select1")
        .find("option[value=" + message + "]")
        .attr("selected", "selected");
      $("#message").html(message);
      showStep(null, 3);
    }
  }

  function onGetTokens(tokens) {
    // Response: tokens = { token: <legacy token>, fuel2token: <fuel api token> }
    // console.log(tokens);
  }

  function onGetEndpoints(endpoints) {
    // Response: endpoints = { restHost: <url> } i.e. "rest.s1.qa1.exacttarget.com"
    // console.log(endpoints);
  }

  function onClickedNext() {
    if (
      (currentStep.key === "step3" && steps[3].active === false) ||
      currentStep.key === "step4"
    ) {
      save();
    } else {
      connection.trigger("nextStep");
    }
  }

  function onClickedBack() {
    connection.trigger("prevStep");
  }

  function onGotoStep(step) {
    showStep(step);
    connection.trigger("ready");
  }

  function showStep(step, stepIndex) {
    if (stepIndex && !step) {
      step = steps[stepIndex - 1];
    }

    currentStep = step;

    $(".step").hide();

    switch (currentStep.key) {
      case "step1":
        $("#step1").show();
        connection.trigger("updateButton", {
          button: "next",
          enabled: Boolean(getMessage()),
        });
        connection.trigger("updateButton", {
          button: "back",
          visible: false,
        });
        break;
      case "step2":
        $("#step2").show();
        connection.trigger("updateButton", {
          button: "back",
          visible: true,
        });
        connection.trigger("updateButton", {
          button: "next",
          text: "next",
          visible: true,
        });
        break;
      case "step3":
        $("#step3").show();
        connection.trigger("updateButton", {
          button: "back",
          visible: true,
        });
        if (lastStepEnabled) {
          connection.trigger("updateButton", {
            button: "next",
            text: "next",
            visible: true,
          });
        } else {
          connection.trigger("updateButton", {
            button: "next",
            text: "done",
            visible: true,
          });
        }
        break;
      case "step4":
        $("#step4").show();
        break;
    }
  }

  function save() {
    var name = $("#select1").find("option:selected").html();
    var value = getMessage();

    // 'payload' is initialized on 'initActivity' above.
    // Journey Builder sends an initial payload with defaults
    // set by this activity's config.json file.  Any property
    // may be overridden as desired.
    payload.name = name;

    payload["arguments"].execute.inArguments = [{ message: value }];

    payload["metaData"].isConfigured = true;

    connection.trigger("updateActivity", payload);
  }

  function getMessage() {
    return $("#select1").find("option:selected").attr("value").trim();
  }
});
```

## Sample Request

Sample POST data sent to `https://some-endpoint.com/execute`.

```js
{
        "inArguments": [
                {
                    "emailAddress": "{{InteractionDefaults.Email}}"
                },
                {
                    "phoneNumber": "{{Contact.Default.PhoneNumber}}"
                }
            ],
        "outArguments": [],
        "activityObjectID": "1234abcd-56ef-78gh-90ij-9876klmn5432",
        "journeyId": "1234abcd-56ef-78gh-90ij-9876klmn5432",
        "activityId": "1234abcd-56ef-78gh-90ij-9876klmn5432",
        "definitionInstanceId": "1234abcd-56ef-78gh-90ij-9876klmn5432",
        "activityInstanceId": "1234abcd-56ef-78gh-90ij-9876klmn5432",
        "keyValue": "someContactKeyHere",
        "mode": 0
}
```

## Sample Response

Sample 200 OK response expected from the server.

```js
{
        "foundSignupDate": "2016-03-10"
}
```

## Related Items

- [Build Custom Activities and Events](https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/creating-activities.md)
