> You are reading the Docusign Developer Documentation. For clean Markdown of any page, append .md to the page URL.
>
> Documentation indexes by section:
> - APIs and SDKs: https://docusign.docs.buildwithfern.com/docs/llms.txt
> - Platform 101: https://docusign.docs.buildwithfern.com/platform/llms.txt
> - Extension Apps: https://docusign.docs.buildwithfern.com/extension-apps/llms.txt
> - Docusign CLI: https://docusign.docs.buildwithfern.com/docusign-cli/llms.txt
>
> Authentication (OAuth, JWT Grant, M2M): https://docusign.docs.buildwithfern.com/platform/auth
> Webhooks and Connect: https://docusign.docs.buildwithfern.com/platform/webhooks
>
> OpenAPI specifications: https://docusign.docs.buildwithfern.com/openapi.json
> MCP server: https://docusign.docs.buildwithfern.com/_mcp/server

# How to create and embed a web form instance

> Learn how to create a web form instance and embed it in your app’s HTML using the Docusign JS library.

> **Note**
>
> The Web Forms API is available in all developer accounts, but only in certain production account plans. Contact [Docusign Support](https://support.docusign.com/s/?language=en_US) or your account manager to find out whether the Web Forms API is available for your production account plan.

This topic demonstrates how to create a web form instance and embed it in your app’s HTML using the Docusign JS library. After the signer fills out the form, they will be directed to the embedded signing experience, where they will sign the document.

> **Note**
>
> Run this code example from our [Quickstart](/docs/esign-rest-api/quickstart) or launcher projects: [Bash](https://github.com/docusign/code-examples-bash), [C#](https://github.com/docusign/code-examples-csharp), [Java](https://github.com/docusign/code-examples-java), [Node.js](https://github.com/docusign/code-examples-node), [PHP](https://github.com/docusign/code-examples-php), [PowerShell](https://github.com/docusign/code-examples-powershell), [Python](https://github.com/docusign/code-examples-python), or [Ruby](https://github.com/docusign/code-examples-ruby).

## Prerequisites

Web form configurations cannot be created through the API. Therefore, before you create a web form instance, you must [create](https://support.docusign.com/s/document-item?bundleId=gmi1660583110357\&topicId=euk1665093155272.html)  and [activate](https://support.docusign.com/s/document-item?bundleId=gmi1660583110357\&topicId=iri1669070601520.html) a web form configuration in your Docusign account. If you are running this from our Quickstart or launcher projects, you will receive instructions for how to create a web form configuration by uploading a compatible JSON configuration file.

If you choose not to use our launcher projects, you can follow along with this guide by creating a web form configuration with the name “Web Form Example Template” and adding the following fields:

* A text field with the API reference name “PhoneNumber”
* A text field with the API reference name “Company”
* A text field with the API reference name “JobTitle”
* A checkbox with the API reference name “Yes”

## Required data

Running the code in this how-to requires this data:

| Data element      | Description                                                                                                                                                                                                                                                                              |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \{API_ACCOUNT_ID} | A [GUID](http://guid.one/) value that identifies your account. This value is automatically generated by Docusign for any account you create. Copy the value from the **API Account ID** field on the [Apps and Keys](https://admindemo.docusign.com/authenticate?goTo=appsAndKeys) page. |
| \{BASE_PATH}      | A string value that forms the root of the URL required to make API calls. The base path value in the example code is set to target the developer environment at https\://\<domain>/webforms/v1.1 Where \<domain> is apps-d.docusign.com/api for the developer environment.               |
| \{CLIENT_USER_ID} | A unique identifier for a user that should originate from your own system. This value can be anything your backend system will use to track and retrieve individual web form instances. Examples include employee IDs, email addresses, and surrogate key values.                        |

## Step 1. Obtain your OAuth Token

To make the API calls shown in this how-to, you need a valid OAuth access token. Docusign supports access tokens for three different recommended OAuth grant types: Public Authorization Code Grant, Confidential Authorization Code Grant, and JSON Web Token (JWT) Grant. Choose the OAuth grant type appropriate for your scenario.

Web Forms OAuth access tokens are the same ones used for our [eSignature REST API](/docs/esign-rest-api/esign101/auth), although you must request one or more Web Forms scopes to call the Web Forms API. The API calls made in this how-to require that you request the eSignature REST API `signature` scope and Docusign Web Forms–specific scopes `webforms_instance_read`, `webforms_instance_write`, and `webforms_read` when obtaining your access token.

> **Note**
>
> See [Authentication](/docs/web-forms-api/plan-integration/authentication) for guidance on your options to get an OAuth token.

![Three icons that represent the three methods a user can use to obtain an OAuth token: JSON Web Token (JWT), Public Authorization Code Grant (ACG), and Confidential Authorization Code grant](/_fern-files/_img/64f473773042ee439449a096bf7673292b1585b86a4ccc55f82ba0dda41f61a1.webp)

## Step 2. Construct your API headers

After you have a valid OAuth access token, you are ready to construct the API headers that you will pass to the API call. Construct your headers like this, but make sure to substitute your valid OAuth access token for \{ACCESS_TOKEN}.

**`Bash`**

```bash title="Bash"
declare -a Headers=('--header' "Authorization: Bearer ${ACCESS_TOKEN}" \
            '--header' "Accept: application/json" \
			'--header' "Content-Type: application/json")
```

**`C#`**

```csharp title="C#"
var docuSignClient = new DocuSignClient(basePath);
docuSignClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
```

**`Java`**

```java title="Java"
com.docusign.webforms.client.ApiClient apiClient = new com.docusign.webforms.client.ApiClient(basePath);
apiClient.addDefaultHeader(HttpHeaders.AUTHORIZATION, BEARER_AUTHENTICATION + userAccessToken);
apiClient.addAuthorization("docusignAccessCode", new com.docusign.webforms.client.auth.OAuth());
```

**`Node.js`**

```javascript title="Node.js"
const apiClient = new docusignEsign.ApiClient();
apiClient.setBasePath(args.basePath);
apiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
```

**`PHP`**

```php title="PHP"
$config = new Configuration();
$config->setHost('https://apps-d.docusign.com/api/webforms');
$config->addDefaultHeader('Authorization', 'Bearer ' . $args['ds_access_token']);
$this->apiClient = new ApiClient($config);
```

**`PowerShell`**

```text title="PowerShell"
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.add("Authorization", "Bearer $accessToken")
$headers.add("Content-Type", "application/json")
$headers.add("Accept", "application/json")
```

**`Python`**

```python title="Python"
api_client = ApiClient()
api_client.host = args["base_path"]
api_client.set_default_header(header_name="Authorization", header_value=f"Bearer {args['access_token']}")
```

**`Ruby`**

```ruby title="Ruby"
configuration = DocuSign_WebForms::Configuration.new
api_client = DocuSign_WebForms::ApiClient.new(configuration)
api_client.set_default_header('Authorization', "Bearer #{args[:access_token]}")
```

## Step 3. Get the form ID

First, get the ID of the web form configuration of which you will be creating an instance. Call the [Configurations:listForms](/docs/web-forms-api/reference/webforms/configurations/listforms) endpoint, passing the value `Web Form Example Template` to the `search` query parameter. This query parameter filters the results of the API call so that only web form configurations with the name “Web Form Example Template” are returned. Save the value of `id` from the response so that it can be used in Step 5.

**`Bash`**

```bash title="Bash"
response=$(mktemp /tmp/response-cw.XXXXXX)
Status=$(curl -w '%{http_code}' --request GET ${base_path}/accounts/${ACCOUNT_ID}/forms?search=Web%20Form%20Example%20Template \
    "${Headers[@]}" \
    --output ${response})

FORM_ID=$(cat $response | sed 's/,/\n/g' | grep id | sed 's/.*\"id\":\"//g' | sed 's/\".*//g')
```

**`C#`**

```csharp title="C#"
FormManagementApi formManagementApi = new FormManagementApi(docuSignClient);
FormManagementApi.ListFormsOptions listFormsOptions = new FormManagementApi.ListFormsOptions();
listFormsOptions.search = "Web Form Example Template";
var response = formManagementApi.ListFormsWithHttpInfo(accountId, listFormsOptions);
response.Headers.TryGetValue("X-RateLimit-Remaining", out string remaining);
response.Headers.TryGetValue("X-RateLimit-Reset", out string reset);

if (reset != null && remaining != null)
{
    DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(reset)).UtcDateTime;
    Console.WriteLine("API calls remaining: " + remaining);
    Console.WriteLine("Next Reset: " + resetDate);
}

return response.Data;
var templatesApi = new TemplatesApi(docuSignClient);
var listTemplateOptions = new TemplatesApi.ListTemplatesOptions();
listTemplateOptions.searchText = templateName;

var templates = templatesApi.ListTemplatesWithHttpInfo(accountId, listTemplateOptions);
templates.Headers.TryGetValue("X-RateLimit-Remaining", out string remaining);
templates.Headers.TryGetValue("X-RateLimit-Reset", out string reset);

if (reset != null && remaining != null)
{
    DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(reset)).UtcDateTime;
    Console.WriteLine("API calls remaining: " + remaining);
    Console.WriteLine("Next Reset: " + resetDate);
}
```

**`Java`**

```java title="Java"
		FormManagementApi formManagementApi = new FormManagementApi(apiClient);
		var option = formManagementApi.new ListFormsOptions();
		option.setSearch(search);

		ApiResponse<WebFormSummaryList> response = formManagementApi.listFormsWithHttpInfo(userAccessToken,
				option);

		Map<String, List<String>> headers = response.getHeaders();
		List<String> remaining = headers.get("X-RateLimit-Remaining");
		List<String> reset = headers.get("X-RateLimit-Reset");

		if (remaining != null & reset != null) {
			Instant resetInstant = Instant.ofEpochSecond(Long.parseLong(reset.get(0)));
			System.out.println("API calls remaining: " + remaining);
			System.out.println("Next Reset: " + resetInstant);
		}

		return response.getData();
```

**`Node.js`**

```javascript title="Node.js"
const templatesApi = new docusignEsign.TemplatesApi(apiClient);

const webFormsTemplates = await templatesApi.listTemplates(args.accountId, {
  searchText: args.templateName,
}, (error, data, response) => {
    const headers = response?.headers;

    const remaining = headers?.['x-ratelimit-remaining'];
    const reset = headers?.['x-ratelimit-reset'];

    if (remaining && reset) {
      const resetInstant = new Date(Number(reset) * 1000);

      console.log(`API calls remaining: ${remaining}`);
      console.log(`Next Reset: ${resetInstant.toISOString()}`);
    }
});

if (webFormsTemplates.data.resultSetSize > 0) {
  return webFormsTemplates.data.envelopeTemplates[0].templateId;
}
```

**`PHP`**

```php title="PHP"
public static function addTemplateIdToForm(string $fileLocation, string $templateId): void
{
    $targetString = "template-id";

    try {
        $fileContent = file_get_contents($fileLocation);
        $modifiedContent = str_replace($targetString, $templateId, $fileContent);
        file_put_contents($fileLocation, $modifiedContent);
    } catch (Exception $ex) {
        echo "An error occurred: " . $ex->getMessage();
    }
}
```

**`PowerShell`**

```text title="PowerShell"
$response = New-TemporaryFile
Invoke-RestMethod `
    -Uri "${apiUri}/accounts/${accountId}/forms?search=Web%20Form%20Example%20Template" `
    -Method 'GET ' `
    -Headers $headers `
    -OutFile $response

$formId = $(Get-Content $response | ConvertFrom-Json).items[0].id
```

**`Python`**

```python title="Python"
webforms_api = FormManagementApi(api_client)
web_forms = webforms_api.list_forms(args["account_id"], search=args["form_name"])
```

**`Ruby`**

```ruby title="Ruby"
webforms_api = DocuSign_WebForms::FormManagementApi.new(api_client)

options = DocuSign_WebForms::ListFormsOptions.new
options.search = args[:form_name]

webforms_api.list_forms(args[:account_id], options)
```

## Step 4. Construct the request body

Next, create the request body. Set the `clientUserId` to a unique value that will be used to identify the user who will fill out the form.

Use the `formValues` object to prefill fields in the web form instance. The keys in this object correspond with the API reference names of the fields in the web form configuration. You can find and edit these API reference names in the [Properties tab](https://support.docusign.com/s/document-item?bundleId=gmi1660583110357\&topicId=wor1676501633875.html) in the web forms UI. The `expirationOffset` parameter determines the amount of time in hours until the instance will expire. The form instance can be submitted and a corresponding envelope can be generated as long as the instance has not yet expired.

**`Bash`**

```bash title="Bash"
printf \
'{
    "clientUserId": "1234-5678-abcd-ijkl",
    "formValues": {
        "PhoneNumber": "555-555-5555",
        "Yes": ["Yes"],
        "Company": "Tally",
        "JobTitle": "Programmer Writer"
    },
    "expirationOffset": 24
}' >$request_data
```

**`C#`**

```csharp title="C#"
var formValues = new WebFormValues
{
    { "PhoneNumber", "555-555-5555" },
    { "Yes", new[] { "Yes" } },
    { "Company", "Tally" },
    { "JobTitle", "Programmer Writer" },
};

var options = new CreateInstanceRequestBody()
{
    ClientUserId = "1234-5678-abcd-ijkl",
    FormValues = formValues,
    ExpirationOffset = 24,
};
```

**`Java`**

```java title="Java"
		WebFormValues formValues = new WebFormValues();

		formValues.putAll(Map.of(
				"PhoneNumber", "555-555-5555",
				"Yes", new String[] { "Yes" },
				"Company", "Tally",
				"JobTitle", "Programmer Writer"));
```

**`Node.js`**

```javascript title="Node.js"
const webFormValues = {
  PhoneNumber: '555-555-5555',
  Yes: ['Yes'],
  Company: 'Tally',
  JobTitle: 'Programmer Writer',
};

const createInstanceBody = docusignWebForms.CreateInstanceRequestBody.constructFromObject({
  clientUserId: args.clientUserId,
  formValues: webFormValues,
  expirationOffset: 24,
});
```

**`PHP`**

```php title="PHP"
$formValues = new WebFormValues([
    ["PhoneNumber" => "555-555-5555"],
    ["Yes" => ["Yes"]],
    ["Company" => "Tally"],
    ["JobTitle" => "Programmer Writer"]
]);

$options = new CreateInstanceRequestBody([
    'client_user_id' => '1234-5678-abcd-ijkl',
    'form_values' => $formValues,
    'expiration_offset' => 24,
]);
```

**`PowerShell`**

```text title="PowerShell"
$json = @"
{
    "clientUserId": "1234-5678-abcd-ijkl",
    "formValues": {
        "PhoneNumber": "555-555-5555",
        "Yes": ["Yes"],
        "Company": "Tally",
        "JobTitle": "Programmer Writer"
    },
    "expirationOffset": 24
}
"@
```

**`Python`**

```python title="Python"
web_form_values = {
    "PhoneNumber": "555-555-5555",
    "Yes": ["Yes"],
    "Company": "Tally",
    "JobTitle": "Programmer Writer"
}
web_form_req_object = CreateInstanceRequestBody(
    client_user_id=args["client_user_id"],
    form_values=web_form_values,
    expiration_offset=24
)
```

**`Ruby`**

```ruby title="Ruby"
web_form_values = {
  'PhoneNumber' => '555-555-5555',
  'Yes' => ['Yes'],
  'Company' => 'Tally',
  'JobTitle' => 'Programmer Writer'
}
web_form_req_object = DocuSign_WebForms::CreateInstanceRequestBody.new({
                                                                         'clientUserId' => args[:client_user_id],
                                                                         'formValues' => web_form_values,
                                                                         'expirationOffset' => '24'
                                                                       })
```

## Step 5. Call the Web Forms API

Now that you have constructed your API headers and request body, make a POST request to the [Instances:createInstance](/docs/web-forms-api/reference/webforms/instances/createinstance) method and include the request body to create a new instance of the web form.

Here’s how you make the call, but make sure to substitute your API account ID for \{ACCOUNT_ID} and form ID for \{FORM_ID}.

**`Bash`**

```bash title="Bash"
Status=$(curl -w '%{http_code}' -i --request POST ${base_path}/accounts/${ACCOUNT_ID}/forms/${FORM_ID}/instances \
    "${Headers[@]}" \
    --data-binary @${request_data} \
    --output ${response})
```

**`C#`**

```csharp title="C#"
FormInstanceManagementApi formManagementApi = new FormInstanceManagementApi(docuSignClient);
var response = formManagementApi.CreateInstanceWithHttpInfo(accountId, formId, options);
response.Headers.TryGetValue("X-RateLimit-Remaining", out string remaining);
response.Headers.TryGetValue("X-RateLimit-Reset", out string reset);

if (reset != null && remaining != null)
{
    DateTime resetDate = DateTimeOffset.FromUnixTimeSeconds(long.Parse(reset)).UtcDateTime;
    Console.WriteLine("API calls remaining: " + remaining);
    Console.WriteLine("Next Reset: " + resetDate);
}

return response.Data;
```

**`Java`**

```java title="Java"
		FormInstanceManagementApi formManagementApi = new FormInstanceManagementApi(apiClient);
		String clientUserId = "1234-5678-abcd-ijkl";

		CreateInstanceRequestBody options = new CreateInstanceRequestBody()
				.clientUserId(clientUserId)
				.formValues(formValues)
				.expirationOffset(24);

		ApiResponse<WebFormInstance> response = formManagementApi.createInstanceWithHttpInfo(accountId, formId,
				options);

		Map<String, List<String>> headers = response.getHeaders();
		List<String> remaining = headers.get("X-RateLimit-Remaining");
		List<String> reset = headers.get("X-RateLimit-Reset");

		if (remaining != null & reset != null) {
			Instant resetInstant = Instant.ofEpochSecond(Long.parseLong(reset.get(0)));
			System.out.println("API calls remaining: " + remaining);
			System.out.println("Next Reset: " + resetInstant);
		}

		return response.getData();
```

**`Node.js`**

```javascript title="Node.js"
const formInstanceManagementApi = new docusignWebForms.FormInstanceManagementApi(apiClient);
const webForm = await formInstanceManagementApi.createInstance(createInstanceBody, args.accountId, formId, (error, data, response) => {
    const headers = response?.headers;

    const remaining = headers?.['x-ratelimit-remaining'];
    const reset = headers?.['x-ratelimit-reset'];

    if (remaining && reset) {
      const resetInstant = new Date(Number(reset) * 1000);

      console.log(`API calls remaining: ${remaining}`);
      console.log(`Next Reset: ${resetInstant.toISOString()}`);
    }
});
```

**`PHP`**

```php title="PHP"
$response = $formInstanceApi->createInstanceWithHttpInfo($accountId, $formId, $options);

$remaining = $response[2]['X-RateLimit-Remaining'] ?? null;
$reset = $response[2]['X-RateLimit-Reset'] ?? null;

if ($remaining !== null && $reset !== null) {
    $resetInstant = (new DateTime())->setTimestamp((int)$reset);
    error_log("API calls remaining: $remaining");
    error_log("Next Reset: " . $resetInstant->format(\DateTime::ATOM));
}
return $response[0];
```

**`PowerShell`**

```text title="PowerShell"
Invoke-RestMethod `
    -Uri "${apiUri}/accounts/${accountId}/forms/${formId}/instances" `
    -Method 'POST' `
    -Headers $headers `
    -Body $json `
    -OutFile $response

$responseContent = $(Get-Content $response | ConvertFrom-Json)
```

**`Python`**

```python title="Python"
webforms_api = FormInstanceManagementApi(api_client)
web_form = webforms_api.create_instance(args["account_id"], form_id, web_form_req_object)
```

**`Ruby`**

```ruby title="Ruby"
webforms_api = DocuSign_WebForms::FormInstanceManagementApi.new(api_client)
webforms_api.create_instance(args[:account_id], form_id, web_form_req_object)
```

## Expected response

If you run this code example from our Quickstart or launcher projects, you should see a JSON response similar to the code shown.

You will need to save the value of `instanceToken` to embed the form instance in your app’s HTML with the `formValues` provided previously in the API request body. Although the instance will not expire until the date and time described by the value of `tokenExpirationDateTime`, the instance *token* will expire after 5 minutes.

**`Sample response`**

```json title="Sample response"
{
  "id": "8ed02b2f-xxxx-xxxx-xxxx-9c19a4243576",
  "formUrl": "https://demo.services.docusign.net/webforms-ux/v1.0/forms/52151720xxxxxxxxxxxxe0a33d1d2c5b",
  "instanceToken": "U2Fs….OAoA==",
  "tokenExpirationDateTime": "2023-12-07T23:30:03.124Z",
  "clientUserId": "1234-5678-abcd-ijkl",
  "formId": "5a62ae76-xxxx-xxxx-xxxx-fada34afe7eb",
  "accountId": "0820f9c5-xxxx-xxxx-xxxx-8a0df87f44aa",
  "tags": [],
  "status": "INITIATED",
  "instanceMetadata": {
    "expirationDateTime": "2024-05-05T23:25:03.124Z",
    "createdDateTime": "2023-12-07T23:25:03.124Z",
    "createdBy": {
      "userId": "8cb9aa3f-xxxx-xxxx-xxxx-f6ce2e16dad1",
      "userName": "Sally Signer"
    },
    "lastModifiedDateTime": "2023-12-07T23:25:03.124Z"
  }
}
```

## Step 6. Embed the Web Form in your HTML

The best practice for embedding a web form instance in your app’s HTML is to use the Docusign JS library. The URL that will load the JS library is [https://js-d.docusign.com/bundle.js](https://js-d.docusign.com/bundle.js) for the developer environment and [https://js.docusign.com/bundle.js](https://js.docusign.com/bundle.js) for the production environment.

After the JS library has been loaded, construct the `webFormsOptions` object. The values in this object will define how the web form is rendered on the page. Set the value of the `instanceToken` parameter to the instance token returned in the response of the `CreateInstance` API call. The other optional parameters control various elements of the embedded form’s style. Use the `hideProgressBar` parameter to control whether the progress bar appears in the form. The `minHeight` parameter inside the `iFrameStyles` array determines the height of the iframe where the form is embedded.

Call `docusign.webforms`, passing the `webFormsOptions` object and the `formUrl` returned from the previous API call as parameters. Finally, mount that object in the HTML element of your choice. In this example it is mounted in a `<div>` with the `id` `docusign`.

> **Note**
>
> View the source code for this how-to on GitHub: [Bash](https://github.com/docusign/code-examples-bash/blob/master/examples/WebForms/eg001CreateInstance.sh), [C#](https://github.com/docusign/code-examples-csharp/blob/master/launcher-csharp/WebForms/Examples/CreateAndEmbedFormService.cs), [Java](https://github.com/docusign/code-examples-java/blob/master/src/main/java/com/docusign/controller/webForms/services/CreateAndEmbedFormService.java), [Node.js](https://github.com/docusign/code-examples-node/blob/master/lib/webforms/examples/createInstance.js), [PHP](https://github.com/docusign/code-examples-php/blob/master/src/Services/Examples/WebForms/CreateAndEmbedFormService.php),  [PowerShell](https://github.com/docusign/code-examples-powershell/blob/master/examples/WebForms/eg001CreateInstance.ps1), [Python](https://github.com/docusign/code-examples-python/blob/master/app/webforms/examples/eg001_create_instance.py), or [Ruby](https://github.com/docusign/code-examples-ruby/blob/master/app/services/webforms/eg001_create_instance_service.rb).

**`Bash`**

```bash title="Bash"
-->
<script src=\"https://js.docusign.com/bundle.js\"></script>
<script>
async function loadWebform() {
  const { loadDocuSign } = window.DocuSign
  const docusign = await loadDocuSign('" . $integrationKey . "');

  const webFormOptions = {
    // Optional field that can prefill values in the form. This overrides the formValues field in the API request
    prefillValues: {},
    // Used with the runtime API workflow, for private webforms this is needed to render anything
    instanceToken: '" . $instanceToken . "',
    // Controls whether the progress bar is shown or not
    hideProgressBar: false,
    // These styles get passed directly to the iframe that is rendered
    iframeStyles: {
      minHeight: \"1500px\",
    },
    // Controls the auto resize behavior of the iframe
    autoResizeHeight: true
  };

  const webFormWidget = docusign.webforms({
    url: '" . $url . "',
    options: webFormOptions,
  });

  //Basic milestones in this workflow
  webFormWidget.on(\"ready\", (event) => {
    // event = { type: \"ready\" };
    console.log(\"debug form loaded\", event);
  });

  webFormWidget.on(\"submitted\", (event) => {
    // event = { type: \"submitted\", envelopeId: \"abcd1234\" };
    console.log(\"debug form submitted\", event);
  });

  webFormWidget.on(\"signingReady\", (event) => {
    // event = { type: \"submitted\", envelopeId: \"abcd1234\" };
    console.log(\"debug form signingReady\", event);
  });

  webFormWidget.on(\"sessionEnd\", (event) => {
    // event = { type: \"sessionEnd\", sessionEndType: \"sessionTimeout\" };
    // event = {
    //   type: 'sessionEnd',
    //   sessionEndType: \"signingResult\",
    //   signingResultType: \"signing_complete\",
    //   returnUrl: \"bigcorp.com\",
    //   envelopeId: \"abcd1234\",
    // };
    // event = { type: \"sessionEnd\", sessionEndType: \"remoteSigningInitiated\", envelopeId: \"abcd1234\" };
    console.log(\"debug form signingResult\", event);
  });

  //Less commonly used events
  webFormWidget.on(\"userActivity\", (event) => {
    // event = { type: \"userActivity\", activityType: \"click\" | \"keydown\" };
    console.log(\"debug form userActivity\", event);
  });

  webFormWidget.mount(\"#docusign\");
}
loadWebform();
</script>
<!--
```

**`C#`**

```csharp title="C#"
}
<!DOCTYPE html>
<html>
  <head>
      <meta charset="UTF-8" />
    @Html.Raw("<script src='https://js.docusign.com/bundle.js'></script>")
  </head>

  <body>
    <div id="app">
      <div id="webform-customer-app-area">
            <h5 id="webforms-heading">@Html.Raw(ViewBag.Description)</h5>
        <div id="docusign" class="webform-iframe-container">
          <p>Web Form will render here</p>
        </div>
      </div>
    </div>
  </body>
</html>

<p><a href="/">@Html.Raw(ViewBag.SupportingTexts.ContinueButton)</a></p>

@Html.Raw("<script src='https://js.docusign.com/bundle.js'></script>")

<script>
async function loadWebform() {
  var instanceToken = '@ViewBag.InstanceToken'.replace(/&#x2B;/g, "+");
  const { loadDocuSign } = window.DocuSign
  const docusign = await loadDocuSign('@ViewBag.IntegrationKey');

  const webFormOptions = {
    //Used with the runtime API workflow, for private webforms this is needed to render anything
    instanceToken: instanceToken,
    //Controls whether the progress bar is shown or not
    hideProgressBar: false,
    //Right now this parameter doesn't do anything but in the future
    //it will be used to customize visual elements of the form experience
    //such as the font color and other things
    styles: {
      fontColor: "black",
    },
    //These styles get passed directly to the iframe that is rendered
    iframeStyles: {
      minHeight: "1500px",
    },
    //Controls the auto resize behavior of the iframe
    autoResizeHeight: true
  };

  const webFormWidget = docusign.webforms({
    url: "@ViewBag.Url",
    options: webFormOptions,
  });

  //Basic milestones in this workflow
  webFormWidget.on('ready', (event) => {
    // event = { type: 'ready' };
    console.log('debug form loaded', event);
  });

  webFormWidget.on('submitted', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form submitted', event);
  });

  webFormWidget.on('signingReady', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form signingReady', event);
  });

  webFormWidget.on('sessionEnd', (event) => {
    // event = { type: 'sessionEnd', sessionEndType: 'sessionTimeout' };
    // event = {
    //   type: 'sessionEnd',
    //   sessionEndType: 'signingResult',
    //   signingResultType: 'signing_complete',
    //   returnUrl: 'bigcorp.com',
    //   envelopeId: 'abcd1234',
    // };
    // event = { type: 'sessionEnd', sessionEndType: 'remoteSigningInitiated', envelopeId: 'abcd1234' };
    console.log('debug form signingResult', event);
  });

  //Less commonly used events
  webFormWidget.on('userActivity', (event) => {
    // event = { type: 'userActivity', activityType: 'click' | 'keydown' };
    console.log('debug form userActivity', event);
  });

  webFormWidget.mount("#docusign");
}

loadWebform();
</script>
@{
```

**`Java`**

```java title="Java"
-->

<script src='https://js.docusign.com/bundle.js'></script>

<script>
    async function loadWebform() {
        var instanceToken = '${instanceToken}'.replace(/&#x2B;/g, "+");
        const { loadDocuSign } = window.DocuSign
        const docusign = await loadDocuSign('${integrationKey}');

        const webFormOptions = {
            //Used with the runtime API workflow, for private webforms this is needed to render anything
            instanceToken: instanceToken,
            //Controls whether the progress bar is shown or not
            hideProgressBar: false,
            //Right now this parameter doesn't do anything but in the future
            //it will be used to customize visual elements of the form experience
            //such as the font color and other things
            styles: {
                fontColor: "black",
            },
            //These styles get passed directly to the iframe that is rendered
            iframeStyles: {
                minHeight: "1500px",
            },
            //Controls the auto resize behavior of the iframe
            autoResizeHeight: true,
            //These values are passed to the iframe URL as query params
            tracking: {
                "tracking-field": "tracking-value",
            },
            //These values are passed to the iframe URL as hash params
            hidden: {
                "hidden-field": "hidden-value",
            },
        };

        const webFormWidget = docusign.webforms({
            url: '${url}',
            options: webFormOptions,
        })

        webFormWidget.mount("#docusign");
    }

    loadWebform();
</script>

<!--
```

**`Node.js`**

```javascript title="Node.js"
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="app">
      <div id="webform-customer-app-area">
        <h5 id="webforms-heading"><%= webformsHeading %></h5>
        <div id="docusign" class="webform-iframe-container">
          <p>Web Form will render here</p>
        </div>
      </div>
    </div>
  </body>
</html>

<p><a href="/">Continue</a></p>

<script src="https://js.docusign.com/bundle.js"></script>
<script>
  async function loadWebform() {
    const { loadDocuSign } = window.DocuSign
    const docusign = await loadDocuSign('<%= integrationKey %>');
    const webFormOptions = {
      //Used with the runtime API workflow, for private webforms this is needed to render anything
      instanceToken: '<%= instanceToken %>',
      //Controls whether the progress bar is shown or not
      hideProgressBar: false,
      //Right now this parameter doesn't do anything but in the future
      //it will be used to customize visual elements of the form experience
      //such as the font color and other things
      styles: {
        fontColor: "black",
      },
      //These styles get passed directly to the iframe that is rendered
      iframeStyles: {
        minHeight: "1500px",
      },
      //Controls the auto resize behavior of the iframe
      autoResizeHeight: true,
    };
    const webFormWidget = docusign.webforms({
      url: '<%= formUrl %>',
      options: webFormOptions,
    });
    //Basic milestones in this workflow
    webFormWidget.on("ready", (event) => {
      // event = { type: "ready" };
      console.log("debug form loaded", event);
    });

    webFormWidget.on("submitted", (event) => {
      // event = { type: "submitted", envelopeId: "abcd1234" };
      console.log("debug form submitted", event);
    });

    webFormWidget.on("signingReady", (event) => {
      // event = { type: "submitted", envelopeId: "abcd1234" };
      console.log("debug form signingReady", event);
    });

    webFormWidget.on("sessionEnd", (event) => {
      // event = { type: "sessionEnd", sessionEndType: "sessionTimeout" };
      // event = {
      //   type: 'sessionEnd',
      //   sessionEndType: "signingResult",
      //   signingResultType: "signing_complete",
      //   returnUrl: "bigcorp.com",
      //   envelopeId: "abcd1234",
      // };
      // event = { type: "sessionEnd", sessionEndType: "remoteSigningInitiated", envelopeId: "abcd1234" };
      console.log("debug form signingResult", event);
    });

    //Less commonly used events
    webFormWidget.on("userActivity", (event) => {
      // event = { type: "userActivity", activityType: "click" | "keydown" };
      console.log("debug form userActivity", event);
    });

    webFormWidget.mount("#docusign");
  }
  loadWebform();
</script>
<!--
```

**`PHP`**

```php title="PHP"
-->
<script src='http://js.docusign.com/bundle.js'></script>
<script>
    async function loadWebform() {
        const { loadDocuSign } = window.DocuSign
        const docusign = await loadDocuSign('{{ integration_key }}');

        const webFormOptions = {
            // Optional field that can prefill values in the form. This overrides the formValues field in the API request
            prefillValues: {},
            // Used with the runtime API workflow, for private webforms this is needed to render anything
            instanceToken: '{{ instance_token }}',
            // Controls whether the progress bar is shown or not
            hideProgressBar: false,
            // These styles get passed directly to the iframe that is rendered
            iframeStyles: {
                minHeight: "1500px",
    },
        // Controls the auto resize behavior of the iframe
        autoResizeHeight: true
    };

        const webFormWidget = docusign.webforms({
            url: '{{ url }}',
            options: webFormOptions,
        });

        //Basic milestones in this workflow
  webFormWidget.on('ready', (event) => {
    // event = { type: 'ready' };
    console.log('debug form loaded', event);
  });

  webFormWidget.on('submitted', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form submitted', event);
  });

  webFormWidget.on('signingReady', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form signingReady', event);
  });

  webFormWidget.on('sessionEnd', (event) => {
    // event = { type: 'sessionEnd', sessionEndType: 'sessionTimeout' };
    // event = {
    //   type: 'sessionEnd',
    //   sessionEndType: 'signingResult',
    //   signingResultType: 'signing_complete',
    //   returnUrl: 'bigcorp.com',
    //   envelopeId: 'abcd1234',
    // };
    // event = { type: 'sessionEnd', sessionEndType: 'remoteSigningInitiated', envelopeId: 'abcd1234' };
    console.log('debug form signingResult', event);
  });

  //Less commonly used events
  webFormWidget.on('userActivity', (event) => {
    // event = { type: 'userActivity', activityType: 'click' | 'keydown' };
    console.log('debug form userActivity', event);
  });

        webFormWidget.mount("#docusign");
    }
    loadWebform();
</script>
<!--
```

**`PowerShell`**

```text title="PowerShell"
-->
<script src="https://js.docusign.com/bundle.js"></script>
<script>
async function loadWebform() {
const { loadDocuSign } = window.DocuSign
const docusign = await loadDocuSign('$integrationKey');

const webFormOptions = {
// Optional field that can prefill values in the form. This overrides the formValues field in the API request
prefillValues: {},
// Used with the runtime API workflow, for private webforms this is needed to render anything
instanceToken: '$instanceToken',
// Controls whether the progress bar is shown or not
hideProgressBar: false,
// These styles get passed directly to the iframe that is rendered
iframeStyles: {
  minHeight: "1500px",
},
// Controls the auto resize behavior of the iframe
autoResizeHeight: true
};

const webFormWidget = docusign.webforms({
url: '$url',
options: webFormOptions,
});

//Basic milestones in this workflow
  webFormWidget.on('ready', (event) => {
    // event = { type: 'ready' };
    console.log('debug form loaded', event);
  });

  webFormWidget.on('submitted', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form submitted', event);
  });

  webFormWidget.on('signingReady', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form signingReady', event);
  });

  webFormWidget.on('sessionEnd', (event) => {
    // event = { type: 'sessionEnd', sessionEndType: 'sessionTimeout' };
    // event = {
    //   type: 'sessionEnd',
    //   sessionEndType: 'signingResult',
    //   signingResultType: 'signing_complete',
    //   returnUrl: 'bigcorp.com',
    //   envelopeId: 'abcd1234',
    // };
    // event = { type: 'sessionEnd', sessionEndType: 'remoteSigningInitiated', envelopeId: 'abcd1234' };
    console.log('debug form signingResult', event);
  });

  //Less commonly used events
  webFormWidget.on('userActivity', (event) => {
    // event = { type: 'userActivity', activityType: 'click' | 'keydown' };
    console.log('debug form userActivity', event);
  });

webFormWidget.mount("#docusign");
}
loadWebform();
</script>
<!--
```

**`Python`**

```python title="Python"
-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div id="app">
      <div id="webform-customer-app-area">
        <h5 id="webforms-heading">{{ webforms_heading }}</h5>
        <div id="docusign" class="webform-iframe-container">
          <p>Web Form will render here</p>
        </div>
      </div>
    </div>
  </body>
</html>

<p><a href="/">Continue</a></p>

<script src="https://js.docusign.com/bundle.js"></script>
<script>
  async function loadWebform() {
    const { loadDocuSign } = window.DocuSign
    const docusign = await loadDocuSign('{{ integration_key }}');
    const webFormOptions = {
      //Used with the runtime API workflow, for private webforms this is needed to render anything
      instanceToken: '{{ instance_token }}',
      //Controls whether the progress bar is shown or not
      hideProgressBar: false,
      //Right now this parameter doesn't do anything but in the future
      //it will be used to customize visual elements of the form experience
      //such as the font color and other things
      styles: {
        fontColor: "black",
      },
      //These styles get passed directly to the iframe that is rendered
      iframeStyles: {
        minHeight: "1500px",
      },
      //Controls the auto resize behavior of the iframe
      autoResizeHeight: true
    };

    const webFormWidget = docusign.webforms({
      url: '{{ form_url }}',
      options: webFormOptions,
    });

    //Basic milestones in this workflow
  webFormWidget.on('ready', (event) => {
    // event = { type: 'ready' };
    console.log('debug form loaded', event);
  });

  webFormWidget.on('submitted', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form submitted', event);
  });

  webFormWidget.on('signingReady', (event) => {
    // event = { type: 'submitted', envelopeId: 'abcd1234' };
    console.log('debug form signingReady', event);
  });

  webFormWidget.on('sessionEnd', (event) => {
    // event = { type: 'sessionEnd', sessionEndType: 'sessionTimeout' };
    // event = {
    //   type: 'sessionEnd',
    //   sessionEndType: 'signingResult',
    //   signingResultType: 'signing_complete',
    //   returnUrl: 'bigcorp.com',
    //   envelopeId: 'abcd1234',
    // };
    // event = { type: 'sessionEnd', sessionEndType: 'remoteSigningInitiated', envelopeId: 'abcd1234' };
    console.log('debug form signingResult', event);
  });

  //Less commonly used events
  webFormWidget.on('userActivity', (event) => {
    // event = { type: 'userActivity', activityType: 'click' | 'keydown' };
    console.log('debug form userActivity', event);
  });

    webFormWidget.mount("#docusign");
  }
  loadWebform();
</script>

<!--
```

**`Ruby`**

```ruby title="Ruby"
-->

<script src="https://js.docusign.com/bundle.js"></script>
<script>
    async function loadWebform() {
        const { loadDocuSign } = window.DocuSign
        const docusign = await loadDocuSign('<%= @integration_key %>');
        const webFormOptions = {
            //Used with the runtime API workflow, for private webforms this is needed to render anything
            instanceToken: '<%= @instance_token %>',
            //Controls whether the progress bar is shown or not
            hideProgressBar: false,
            //Right now this parameter doesn't do anything but in the future
            //it will be used to customize visual elements of the form experience
            //such as the font color and other things
            styles: {
                fontColor: "black",
            },
            //These styles get passed directly to the iframe that is rendered
            iframeStyles: {
                minHeight: "1500px",
            },
            //Controls the auto resize behavior of the iframe
            autoResizeHeight: true
        };

        const webFormWidget = docusign.webforms({
            url: '<%= @form_url %>',
            options: webFormOptions,
        });

        //Basic milestones in this workflow
        webFormWidget.on('ready', (event) => {
            // event = { type: 'ready' };
            console.log('debug form loaded', event);
        });

        webFormWidget.on('submitted', (event) => {
            // event = { type: 'submitted', envelopeId: 'abcd1234' };
            console.log('debug form submitted', event);
        });

        webFormWidget.on('signingReady', (event) => {
            // event = { type: 'submitted', envelopeId: 'abcd1234' };
            console.log('debug form signingReady', event);
        });

        webFormWidget.on('sessionEnd', (event) => {
            // event = { type: 'sessionEnd', sessionEndType: 'sessionTimeout' };
            // event = {
            //   type: 'sessionEnd',
            //   sessionEndType: 'signingResult',
            //   signingResultType: 'signing_complete',
            //   returnUrl: 'bigcorp.com',
            //   envelopeId: 'abcd1234',
            // };
            // event = { type: 'sessionEnd', sessionEndType: 'remoteSigningInitiated', envelopeId: 'abcd1234' };
            console.log('debug form signingResult', event);
        });

        //Less commonly used events
        webFormWidget.on('userActivity', (event) => {
            // event = { type: 'userActivity', activityType: 'click' | 'keydown' };
            console.log('debug form userActivity', event);
        });

        webFormWidget.mount("#docusign");
    }
    loadWebform();
</script>

<!--
```

## Expected response

If you run this code example from our Quickstart or launcher projects, you should see the web form embedded in the results page of the example. After the signer fills out the form, they will be directed to the embedded signing experience.

![The web form instance embedded on a page](/_fern-files/_img/54a305e5fbdd93c3b8faf3248fb830173115650ee71fdfffd1584aaaa37a5fb1.webp)

## Next steps

* Run this code example from our [Quickstart](/docs/esign-rest-api/quickstart) or launcher projects:    [Bash](https://github.com/docusign/code-examples-bash), [C#](https://github.com/docusign/code-examples-csharp), [Java](https://github.com/docusign/code-examples-java), [Node.js](https://github.com/docusign/code-examples-node), [PHP](https://github.com/docusign/code-examples-php), [PowerShell](https://github.com/docusign/code-examples-powershell), [Python](https://github.com/docusign/code-examples-python), or [Ruby](https://github.com/docusign/code-examples-ruby).
* Learn more about [Web form instance URLs](/docs/web-forms-api/plan-integration/instance-urls).
* See [Render embedded web form instances](/docs/web-forms-api/plan-integration/render-instances).
* See how to [Go-Live](/docs/web-forms-api/go-live) with a completed app and find the base path for API calls in the production environment.