---
category: [Administration & Integrations, Platform and Product Extensions, Platform and Product Extensions/Integrations, Administration & Integrations/Custom Integrations & Apps, Platform and Product Extensions/Workday Extend]
keyword: [Extend, Presentation Components, UI components]
nav: wcp_docs
parent_url: /wcp_docs/
title: >- 
  Concept: Submitting Data
layout: subsection
---

## <a id="section_submittingData"></a>Submitting Data to an Outbound Endpoint

Outbound endpoints are REST APIs that add, update, or delete data. When the user clicks <b>OK</b> on an edit page, Presentation Components construct the JSON request body from the widget values and submit it to an outbound endpoint.

Define outbound endpoints in the `outboundData{outboundEndPoints[]}` section of the PMD. Specify these required fields for each outbound endpoint in `outboundEndPoints[]`:

-   `url` - The relative REST API URL. The default HTTP method of an outbound endpoint is POST. To override the default, specify the `httpMethod` attribute.
-   `baseUrlType` - Specify a `dataProvider` key defined in the AMD.
-   `name` - Enables you to reference the outbound endpoint when you bind a field to a tag value.
-   `authType` - Specify the authType `id`, which is defined in `authTypes[]` in the Site Metadata (SMD). Workday REST APIs use `SSO`, which is the default authentication type.


Notes:

-   Presentation Components impose a 24-second timeout on each endpoint on a page. Individual endpoints exceeding the 24-second limit return a timeout error. In addition to the endpoint limit, Presentation Components also impose a 60-second timeout on a request. A request can include initial page loads, page submissions, and remote validations. (A single request can call multiple endpoints.) All of these operations must complete within 60 seconds. Otherwise the page returns a timeout error. This measure protects the Workday tenant from poor performance. To avoid the request timeout, consider limiting the number of endpoints and ensure that you call performant endpoints on each page.
-   If you have multiple outbound endpoints, Presentation Components invoke them as ordered in `outboundEndPoints[]`. You can set the `exclude` attribute of an outbound endpoint to invoke it conditionally. Example: Set `exclude` to a binding that evaluates whether the user has entered required data.
-   Only the <b>OK</b> or equivalent button on an edit page can call outbound endpoints. A PMD script with the `invoke` method can't call outbound endpoints. However, you can use the `invoke` method to call a deferred inbound endpoint, which can be an Orchestration that performs additional processing.
-   You can construct or manipulate the request body using the `onSend` event on the outbound endpoint. See the `onSend` event on [Reference: PMD Scripting Events](/wcp_docs/tgy1581495452394.html).
-   To construct the request body of a multipart outbound endpoint, see [Submitting Multipart Data](/wcp_docs/rmd1572291186381.html#section-submitting-multipart-data).


This sample `outboundData` contains endpoints that update and delete a payroll input for a specific donation.

```
"outboundData": {
  "outboundEndPoints": [
    {
      "name": "updatePayInput",
      "baseUrlType": "workday-payroll",
      "url": "<% 'payrollInputs/' + queryParams.donationId %>",
      "httpMethod": "PATCH",
      "authType": "sso",
      "exclude": "<% !payInput.usedInCompletedResult %>",
      "_comment": "If the donation has triggered a deduction, we will update the payInput with a new endDate."
    },
    {
      "name": "deletePayInput",
      "baseUrlType": "workday-payroll",
      "url": "<% 'payrollInputs/' + queryParams.donationId %>",
      "httpMethod": "DELETE",
      "authType": "sso",
      "exclude": "<% payInput.usedInCompletedResult %>",
      "_comment": "If the donation has never triggered a deduction, we will delete it."
    }
  ],
  "responseErrorDetail": {
    "errorSummary": "<% error %>",
    "errors": "<% errors.map(item => { item.error }); %>"
  }
}
```

The `updatePayInput` and `deletePayInput` URLs use:

-   The `donationId` query parameter sent from a button task reference.
-   The `exclude` attribute to determine whether or not to invoke the endpoint. The `usedInCompletedResult` field is a boolean from the `payInput` inbound endpoint.
-   The same `responseErrorDetail`, which returns any error from the outbound endpoint in a page error message.


The `valueOutBinding` attribute of a tag binds the widget value to a field in the outbound data. The `valueOutBinding` uses the format `outboundEndpointName.fieldPath`. The combination of all `valueOutBinding` data on the edit page forms the JSON request body sent to the specified outbound endpoint.

This sample `hidden` tag sends its value, which is today's date, to the `endDate` field in the request body of the `updatePayInput` outbound endpoint.

```
{
  "type": "hidden",
  "id": "endDate",
  "value": "<% date:getTodaysDate(null) %>",
  "valueOutBinding": "updatePayInput.endDate"
}
```

If the `endDate` hidden tag is the only widget with a valueOutBinding on the edit page, the request body contains only the `endDate` field. This sample JSON data displays the request body submitted to `updatePayInput`:

```
{
  "endDate": "2021-02-24"
}
```

If you want to send outbound values from a widget with multiple components (such as a currency or date), use the `valuesOut[]` attribute of the tag. The `valuesOut[]` attribute binds widget and related values to multiple fields in the outbound data. Each item in `valuesOut[]` contains the `valueOutBinding` attribute, which binds the value to a field using the format `outboundEndpointName.fieldPath`. Example:

```
{
  "type": "currency",
  "id": "minDonationAmount",
  "label": "Minimum donation amount",
  "currencyCode": "<% site.appProperties.defaultCurrency %>",
  "valuesOut": [
    {
      "valueOutBinding": "charity.minDonationAmount.value",
      "value": "<% self.value %>"
    },
    {
      "valueOutBinding": "charity.minDonationAmount.currency",
      "value": "<% site.appProperties.defaultCurrency %>"
    }
  ]
}
```

The `values[]` attribute of an outbound endpoint enables you to specify multiple widget values and outbound fields within the `values[]` array. Instead of specifying the `valueOutBinding` attribute separately on different tags on the edit page, you can specify all values and their outbound fields in the `values[]` of the outbound endpoint. Example: The `values[]` in this sample outbound endpoint removes the need to specify the `valueOutBinding` attribute in the <i>name</i> and <i>minAmount</i> tags:

```
"outboundEndPoints": [
 {
   "name": "charity",
   "baseUrlType": "app",
   "url": "charities",
   "httpMethod": "POST",
   "authType": "sso",
   "values": [
      {
         "outboundPath": "name",
         "value": "<% name.value %>"
      },
      {
         "outboundPath": "minDonationAmount.value",
         "value": "<% minAmount.value %>"
      },
      {
         "outboundPath": "minDonationAmount.currency",
         "value": "<% site.appProperties.defaultCurrency %>"
      }
   ]
 },
 . . .
]
```

In the example, since we define all outbound data in the `values[]` of the `charity` outbound endpoint, the request body looks something like:

```
{
    "name": "My Charity",
    "minDonationAmount": 
    {
        "currency": "USD",
        "value": "50"
    }
}
```

## <a id="section_submittingList"></a>Submitting a Data Collection

The request body of an outbound endpoint oftentimes contains a data collection or a list of records. To bind an outbound field within a list in a `valueOutBinding`, specify the list [] notation in the field path. Example:

```
"valueOutBinding": "outboundEndpointName.listName[].fieldPath
```

To demonstrate, let's use the `POST /requisitions` REST API, which requires the `requisitionLines[]` list. This sample request body for the `requisitions` outbound endpoint includes the required `requisitionLines[]`:

```
{
    "requester": {
      "id": "6839ef3499451034845a167636e204c5"
    }, 
    "requisitionLines": [    
    {
        "item": {
          "id": "7d63bab5065910313a84b4a1b6f204cc"
        },
        "quantity": "3",
        "memo": "Doughnut boxes"
    }
          
  ]
}
```

Assume that the requester and item `id` fields come from a `sampleRequisition` inbound endpoint. On this sample PMD, the user can only update the quantity and memo on `text` widgets. The `id` fields are on the `hidden` tags.

```
{
  "type": "fieldSet",
  "label": "Submit a Breakfast Requisition",
  "children": [
    {
      "type" : "hidden",
      "id": "requesterHidden",
      "label" : "Requester ID",
      "value" : "<% sampleRequisition.requester.id %>",
      "valueOutBinding" : "submitRequisition.requester.id"
    },
    {
      "type" : "hidden",
      "id": "itemHidden",
      "label" : "Item ID",
      "value" : "<% sampleRequisition.requisitionLines[0].item.id %>",
      "valueOutBinding" : "submitRequisition.requisitionLines[0].item.id"
    },
    {
      "type" : "text",
      "id": "quantityText",
      "label" : "Quantity",
      "valueOutBinding" : "submitRequisition.requisitionLines[0].quantity"
    },
    {
      "type" : "text",
      "id": "memoText",
      "label" : "Memo",
      "valueOutBinding" : "submitRequisition.requisitionLines[0].memo"
    }
  ]
}
```

Because the outbound endpoint requires the requester and item `id` fields, specify the `valueOutBinding` attributes on the `hidden` tags to include their values in the request body. The `valueOutBinding` on the `text` tags will send the values entered by the user. The sample request submits only 1 requisition line, so it binds the fields in the first list item. Example:

```
"valueOutBinding" : "submitRequisition.requisitionLines[0].memo"
```

If you're submitting a data collection from a grid, set the `isArrayOutBinding` attribute of the grid to true to submit all rows as 1 outbound array. For details and an example, see "Submitting Data as an Array" on the [grid](/wcp_docs/zmz1518211268000.html) tag documentation.

For more examples of specifying `valueOutBinding` values for data collections, see [Reference: valueOutBinding Samples](/wcp_docs/gdp1572582523300.html).

## <a id="section_submittingMultiple"></a>Submitting Multiple Outbound Data

`valuesOut[]` can contain multiple `valueOutBinding` attributes that enable you to:

-   Send the tag value to multiple outbound fields.

    This sample `hidden` sends the text value to both `internalMemo` and `memo` fields to the same outbound endpoint:

    ```
    {
      "type" : "text",
      "id": "memoText",
      "label" : "Memo",
      "valuesOut": [
        {
          "value": "<% memoText.value %>",
          "valueOutBinding": "submitRequisition.internalMemo"
        },
        {
          "value": "<% memoText.value %>",
          "valueOutBinding": "submitRequisition.requisitionLines[0].memo"
        }
      ]
    }
    ```

-   Send the tag value to multiple outbound endpoints.

    This sample `richText` sends the description to the `charity` and `createCharityEvent` endpoints:

    ```
    {
      "type": "richText",
      "id": "description",
      "label": "Description",
      "valuesOut": [
        {
          "value": "<% description.value %>",
          "valueOutBinding": "charity.description"
        },
        {
          "value": "<% description.value %>",
          "valueOutBinding": "createCharityEvent.description"
        }
      ],
      "validations": [
        {
          "regex": "^.{0,1000}",
          "errorMessage": "Maximum character count (including markup) reached: 1000"
        }
      ]
    }
    ```

-   Send multiple parts of the tag value as separate `valueOutBinding` values.

    This sample `date` sends the month and year of the date value into separate outbound fields:

    ```
    {
      "type": "date",
      "id": "dateId",
      "label": "Enter a date",
      "valuesOut": [
        {
          "value": "<% string:toString(date:month(dateId.value)) %>",
          "valueOutBinding": "outboundTest.dateMonth"
        },
        {
          "value": "<% string:toString(date:year(dateId.value)) %>",
          "valueOutBinding": "outboundTest.dateYear"
        }
      ]
    }
    ```

-   Modify the outbound value without changing the actual value.

    This sample `checkbox` sends an outbound integer from the boolean value of the check box:

    ```
    {
      "type" : "checkBox",
      "label" : "Select this checkbox to vote YES. Your vote counts!",
      "id" : "checkBoxId",
      "valuesOut": [
        {
          "value": "<% converter:booleanAsInt(payInput.usedInCompletedResult) %>",
          "valueOutBinding": "outboundTest.voteCount"
        }
      ]
    }
    ```



## <a id="section_submittingAnotherEndpoint"></a>Submitting Data from Another Endpoint

The `values[]` attribute of an outbound endpoint enables you to include the request body on the outbound endpoint itself instead of binding outbound values from the tags. You can also use `values[]` on an outbound endpoint to submit data from another endpoint. To use `values[]` on an outbound endpoint, specify:

```
"values": [
  {
    "value": "<% someData %>",
    "outboundPath": "someOutboundFieldPath"
  }
]
```

These sample outbound endpoints submit outbound data based on data from another endpoint.

```
{
  "name": "charity",
  "baseUrlType": "app",
  "url": "charities",
  "httpMethod": "POST",
  "authType": "sso",
  "values": [
    {
      "outboundPath": "createdBy.id",
      "value": "<% worker.id %>"
    },
    {
      "outboundPath": "image.id",
      "value": "<% (!empty(charityImage.id)) ? charityImage.id : null %>"
    }
  ]
},
{
  "name": "createCharityEvent",
  "baseUrlType": "app",
  "url": "createCharityEvents",
  "httpMethod": "POST",
  "authType": "sso",
  "values": [
    {
      "outboundPath": "businessProcessTarget.id",
      "value": "<% charity.id %>"
    }
  ]
}
```

The `outboundPath` attribute specifies the field path in the request body sent with the outbound endpoint. The sample `charity` outbound endpoint sends the `id` from the `worker` endpoint to the `createdBy.id` field in the request body. It also sends the `id` from the `charityImage` endpoint to the `image.id` field in the request body. The `image.id` field is null if `charityImage.id` is empty.

Similarly, the `createCharityEvent` outbound endpoint sends the `id` from the `charity` endpoint to the `businessProcessTarget.id` outbound field.

<b>Note:</b> If you use multiple outbound endpoints, note that if an endpoint fails, any updates from preceding outbound requests won't roll back.

## <a id="section-submitting-multipart-data"></a>Submitting Multipart Data

An outbound endpoint might require a multipart request body, which is a series of form-data parts separated by MIME boundaries. To convert your outbound data into a multipart request, specify this `valueOutBinding` format:

```
<outboundEndpointName>:<formDataName>:<jsonFieldName>
```

Where:

-   <i>outboundEndpointName</i> - The `name` of the outbound endpoint, as defined in `outboundEndPoints[]`.
-   <i>formDataName</i> - The `name` of the form-data part, which is a JSON map representation of an object in the outbound request.
-   <i>jsonFieldName</i> - The name of the JSON field inside the form-data part. If the JSON object has nested fields, include the field path. Example: <i>myField.subField1.subField2</i>


When the user clicks <b>OK</b> to submit the page, it sends the `value` on each widget with `valueOutBinding` to the specified JSON field within the corresponding form-data part.

The `valueOutBinding` on these sample widgets specify a multipart endpoint with 2 parts, `mainAddressPart` and `secondaryAddressPart`.

```
{
  "type" : "text",
  "label" : "Primary Address",
  "value" : "6200 Stoneridge Mall Rd",
  "valueOutBinding" : "multiPartEndPoint:mainAddressPart:address"
},
{
  "type" : "text",
  "label" : "City",
  "value" : "Pleasanton",
  "valueOutBinding" : "multiPartEndPoint:mainAddressPart:city"
},
{
  "type" : "text",
  "label" : "State",
  "value" : "California",
  "valueOutBinding" : "multiPartEndPoint:mainAddressPart:state"
},
{
  "type" : "text",
  "label" : "Country",
  "value" : "USA",
  "valueOutBinding" : "multiPartEndPoint:mainAddressPart:country"
},
{
  "type" : "text",
  "label" : "Secondary Address",
  "value" : "Kings, Building, 152, Church St, Smithfield",
  "valueOutBinding" : "multiPartEndPoint:secondaryAddressPart:address"
},
{
  "type" : "text",
  "label" : "City",
  "value" : "Dublin",
  "valueOutBinding" : "multiPartEndPoint:secondaryAddressPart:city"
},
{
  "type" : "text",
  "label" : "Country",
  "value" : "Ireland",
  "valueOutBinding" : "multiPartEndPoint:secondaryAddressPart:country"
}
```

The resulting multipart outbound data:

```
--boundary
Content-Disposition: form-data; name="mainAddressPart"
{
   "country":"USA",
   "address":"6200 Stoneridge Mall Rd",
   "city":"Pleasanton",
   "state":"California"
}
--boundary
Content-Disposition: form-data; name="secondaryAddressPart"
{
   "country":"Ireland",
   "address":"Kings, Building, 152, Church St, Smithfield",
   "city":"Dublin"
}
--boundary--
```

To manipulate the JSON data of the multipart request before sending it to the outbound endpont, you can use the `onMultiPartSend` event by modifying `self.data`. The `onMultiPartSend` event handler can:

-   Create a JSON part by adding to `self.data` a <key, value> pair where the value is either a map or array.
-   Modify a JSON part by setting `self.data.<formPartName>.<jsonFieldName>` to the new value.
-   Remove JSON parts by reconstructing `self.data` without those parts.


<b>Note:</b> The name of the form-data can't be `metadata`.

This sample multipart endpoint uses the `onMultiPartSend` event to:

-   Update the <i>mainAddressPart</i> and <i>secondaryAddressPart</i> parts.
-   Add a <i>futureLocationsPart</i> part.


```
"outboundData" : {
  "outboundEndPoints" : [ 
    {
      "name" : "multiPartEndPoint",
      "baseUrlType": "testServer",
      "url": "/post",
      "updateUrl": "null",
      "authType": "NoAuth",
      "onMultiPartSend": "<%

        self.data.mainAddressPart.zipCode = '94588';
        self.data.secondaryAddressPart.address = 'this was modified!';
        self.data.secondaryAddressPart.state = 'this does not apply here';

        var futureLocations = [];
        futureLocations = ['New York', 'Chicago', 'Tokyo'];
        self.data.add('futureLocationPart', futureLocations);

        self.data
      %>"
    } 
  ]
}
```

The modified multipart outbound data:

```
--boundary
Content-Disposition: form-data; name="mainAddressPart"
{
   "country":"USA",
   "address":"6200 Stoneridge Mall Rd",
   "city":"Pleasanton",
   "state":"California",
   "zipCode":"94588"
}
--boundary
Content-Disposition: form-data; name="secondaryAddressPart"
{
   "country":"Ireland",
   "address":"this was modified!",
   "city":"Dublin",
   "state":"this does not apply here"
}
--boundary
Content-Disposition: form-data; name="futureLocationPart"
[
   "New York",
   "Chicago",
   "Tokyo"
]
--boundary--
```

## <a id="section-submitting-multipart-data-with-attachments"></a>Submitting Multipart Data with Attachments

Submitting attachments through the `fileUploader` widget is a common use case for multipart outbound endpoints. Specify the name of the outbound endpoint in the `valueOutBinding` attribute on the `fileUploader`. The format of `valueOutBinding` depends on the type of outbound endpoint.

<table><thead><tr><th>Type of outbound endpoint</th><th>valueOutBinding format on fileUploader</th></tr></thead><tbody><tr><td>Workday REST API attachment</td><td><i>outboundEndpointName</i> <p>If the Workday REST API endpoint submits attachments only, specify just the name of the outbound endpoint.</p></td></tr><tr><td>Workday multipart REST API (attachment and JSON data)</td><td><i>outboundEndpointName:filePartName</i> <p>If the Workday REST API endpoint submits both attachments and JSON data, specify the multipart format of <code>valueOutBinding</code>, where <i>filePartName</i> identifies the file attachment part of the multipart request.</p></td></tr><tr><td>Model attachment object REST API</td><td><i>outboundEndpointName:defaultCollectionName</i> <p><i>defaultCollectionName</i> is the <code>name</code> of the <code>defaultCollection</code> in the model definition of the attachment object.</p></td></tr><tr><td>Third-party multipart REST API</td><td><i>outboundEndpointName:filePartName</i> <p><i>filePartName</i> is the name of the part containing the files.</p></td></tr></tbody></table><br/>

For details, see these sections in [Concept: fileUploader](/wcp_docs/ttn1652370891576.html):

-   Uploading Files.
-   Uploading Files as Attachment Objects.
-   Uploading Files with Third-Party Multipart Requests.


## <a id="section_ywy_dz1_y5b"></a>Submitting Unchanged Data

If a user submits an edit page without modifying any data, Extend doesn't submit the PUT outbound endpoints on the page. To submit unchanged data, set the `allowPutForUnchangedData` attribute of the outbound endpoint to true. This can be important when you construct a JSON request body within an `onSend` or `onMultiPartSend` event handler.

Example:

```
"outboundEndPoints": [
      {
        "name": "updateEvent",
        "baseUrlType": "app",
        "url": "<% 'events/' + event.id %>",
        "authType": "sso",
        "httpMethod": "PUT",
        "allowPutForUnchangedData": true,
        "onSend": "<% self.data.description = description.value;
                   self.data.put('createdBy',{'id': event.createdBy.id});
                   console.info(json:asJSON(self.data)); 
                   return self.data; %>"
      },
...
]
```

## <a id="section_customizeEditButtons"></a>Customizing the Edit Page Buttons

An edit page displays the <b>OK</b> and <b>Cancel</b> buttons at the bottom of the page. When the user clicks <b>OK</b>, the page submits all outbound endpoints with outbound data, and navigates to another page. When the user clicks <b>Cancel</b>, the page doesn't submit any outbound endpoint and navigates to the previous page. If the canceled page is part of a flow, flow variables from the previous page are persisted.

To hide the edit page buttons conditionally, set the `standardEditButtonsHidden` attribute of the `presentation` tag. This sample hides the <b>OK</b> and <b>Cancel</b> buttons if the current worker isn't a manager:

```
"standardEditButtonsHidden": "<% !currentWorker.isManager %>"
```

To define the next page when the user clicks <b>OK</b>, configure a flow definition in the App Metadata (AMD). For details, see [Concept: Page Flows](/wcp_docs/zji1528861641063.html).

To override the default <b>OK</b> button and add more buttons, use the `editButtonBar` tag. The `editButtonBar` can include only buttons that submit data like the <b>OK</b> button. You can't use `editButtonBar` to customize the <b>Cancel</b> button. Just like with the <b>OK</b> button, configure the flow definitions in the AMD to define the page navigation with the custom buttons in the `editButtonBar`.

This sample `editButtonBar` includes a `dropdownEditButton`:

```
{
  "type": "editButtonBar",
  "editButtons": [
    {
      "type": "dropdownEditButton",
      "id": "acceptButton",
      "buttonType": "PRIMARY",
      "dropDown": {
        "id": "accept",
        "type": "dropdown",
        "label": "Accept",
        "instanceList": [
            {
                "id": "1",
                "descriptor": "Accept Completely"
            },
            {
                "id": "2",
                "descriptor": "Accept with Conditions"
            }
        ]
      }
    }
  ]
}
```

You can add drop-down options on the `instanceList` of the `dropdownEditButton`. To persist the value that the user selected, you can pass it as a flow variable using the `id` of the `dropDown` tag. Example:

```
{
    "name" : "transitionOutboundVars",
    "type":"outboundVariable",
    "variableScope": "flow",
    "values":[
        {
          "outboundPath": "accept",
          "value": "<% accept.value[0] %>"
        }
    ]
}
```

To override the default <b>Cancel</b> navigation, use the `cancelOverride` attribute of the `presentation` tag. The `cancelOverride` attribute supports `parameters` and `parameterBindings` to pass query parameters to the target task.

This sample navigates to the `home` page when the user clicks <b>Cancel</b>:

```
"cancelOverride": {
  "taskId": "home"
}
```

### Related Information

[Concept: Displaying Data](/wcp_docs/qau1572291138966.html)

[Reference: valueOutBinding Samples](/wcp_docs/gdp1572582523300.html)

[App Catalog: Charitable Donations](/app-catalog/charitableDonations)

[App Catalog: PMD Scripting](/app-catalog/pmdScripting)

