> 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 set tab values in a template

> Demonstrates how to create and prefill tabs on a template using the Docusign eSignature REST API

This topic demonstrates how to set tab values in a template using the Docusign eSignature REST API.

> **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).

## 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>/restapi Where \<domain> is demo.docusign.net for the developer environment and is the result of the GetUserInfo call in production. |
| \{CLIENT_USER_ID}      | A string value that serves as an identifier of an individual signer throughout the signing process. The combination of this value, the signer's name, and the signer's email is used to uniquely identify them.                                                                                                        |
| Documents to be signed | You must provide at least one document to be signed. Document used in this how-to:- [DOCX file](https://github.com/docusign/code-examples-java/blob/master/src/main/resources/World_Wide_Corp_Battle_Plan_Trafalgar.docx)                                                                                              |
| \{RECIPIENT_ID}        | A unique string value that you assign to identify each recipient. This value assigns tabs on a per-[recipient](/docs/esign-rest-api/esign101/concepts/recipients) basis.                                                                                                                                               |
| Redirect URI           | A URL to which the user will be forwarded after authentication. The value for this URL must exactly match one of those pre-registered for the [integration key](/platform/configure-app#integration-key) in your Docusign account. See [redirect URI](/platform/configure-app#redirect-uri) for details.               |
| \{SIGNER_EMAIL}        | A string value for the email address associated with your account.                                                                                                                                                                                                                                                     |
| \{SIGNER_NAME}         | A string value for the full name of the signer.                                                                                                                                                                                                                                                                        |
| \{TEMPLATE_ID}         | A [GUID](http://guid.one/) value that identifies a Docusign [template](/docs/esign-rest-api/esign101/concepts/templates) that is used to create a Docusign [envelope](/docs/esign-rest-api/esign101/concepts/envelopes). This value is automatically generated by Docusign when the template is created.               |

## 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.

> **Note**
>
> See [Confidential Authorization Code Grant](/platform/auth/authcode#confidential-authorization-code-grant) for guidance on your options to get an Confidential Authorization Code Grant  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"
ApiClient apiClient = createApiClient(session.getBasePath(), user.getAccessToken());
```

**`Node.js`**

```javascript title="Node.js"
let dsApiClient = new docusign.ApiClient();
dsApiClient.setBasePath(args.basePath);
dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
```

**`PHP`**

```php title="PHP"
$config = new Configuration();
$config->setHost($args['base_path']);
$config->addDefaultHeader('Authorization', 'Bearer ' . $args['ds_access_token']);
$this->apiClient = new ApiClient($config);
```

**`PowerShell`**

```text title="PowerShell"
$headers = @{
    'Authorization' = "Bearer $accessToken";
    'Content-Type'  = "application/json";
  }
```

**`Python`**

```python title="Python"
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
```

**`Ruby`**

```ruby title="Ruby"
configuration = DocuSign_eSign::Configuration.new
configuration.host = args[:base_path]
api_client = DocuSign_eSign::ApiClient.new configuration

api_client.default_headers['Authorization'] = "Bearer #{args[:access_token]}"
```

## Step 3: Create tabs and custom fields

This how-to uses a [template generated previously](/docs/esign-rest-api/how-to/create-template)  that defines a few different data tab field types. Create tab objects that match the corresponding tab label to link a newly created tab to an existing template tab.

Set a document ID and page number if you have multiple tabs that need to be set across one or more signing groups. Once ready, bundle all of your created tabs together into a tab object and attach that tab object onto the template role.

**`Bash`**

```bash title="Bash"
declare -A text_custom_fields
text_custom_fields["name"]="app metadata item"
text_custom_fields["required"]="false"
text_custom_fields["show"]="true"
text_custom_fields["value"]="1234567"

declare -A checkbox_tabs
checkbox_tabs["selected1"]="true"
checkbox_tabs["tabLabel1"]="ckAuthorization"
checkbox_tabs["selected2"]="true"
checkbox_tabs["tabLabel2"]="ckAgreement"

declare -A list_tabs
list_tabs["documentId"]="1"
list_tabs["pageNumber"]="1"
list_tabs["tabLabel"]="list"
list_tabs["value"]="green"

declare -A radio_tabs
radio_tabs["selected"]="true"
radio_tabs["value"]="white"

declare -A text_tabs
text_tabs["tabLabel"]="text"
text_tabs["value"]="Jabberywocky!"
```

**`C#`**

```csharp title="C#"
// Set the values for the fields in the template
// List item
List colorPicker = new List
{
    Value = "green",
    DocumentId = "1",
    PageNumber = "1",
    TabLabel = "list",
};

// Checkboxes
Checkbox ckAuthorization = new Checkbox
{
    TabLabel = "ckAuthorization",
    Selected = "true",
};
Checkbox ckAgreement = new Checkbox
{
    TabLabel = "ckAgreement",
    Selected = "true",
};

RadioGroup radioGroup = new RadioGroup
{
    GroupName = "radio1",

    // You only need to provide the readio entry for the entry you're selecting
    Radios = new List<Radio> { new Radio { Value = "white", Selected = "true" } },
};

Text includedOnTemplate = new Text
{
    TabLabel = "text",
    Value = "Jabberywocky!",
};

// We can also add a new tab (field) to the ones already in the template
Text addedField = new Text
{
    DocumentId = "1",
    PageNumber = "1",
    XPosition = "280",
    YPosition = "172",
    Font = "helvetica",
    FontSize = "size14",
    TabLabel = "added text field",
    Height = "23",
    Width = "84",
    Required = "false",
    Bold = "true",
    Value = signerName,
    Locked = "false",
    TabId = "name",
};

// Add the tabs model (including the SignHere tab) to the signer.
// The Tabs object wants arrays of the different field/tab types
// Tabs are set per recipient/signer
Tabs tabs = new Tabs
{
    CheckboxTabs = new List<Checkbox> { ckAuthorization, ckAgreement },
    RadioGroupTabs = new List<RadioGroup> { radioGroup },
    TextTabs = new List<Text> { includedOnTemplate, addedField },
    ListTabs = new List<List> { colorPicker },
};

// Create a signer recipient to sign the document, identified by name and email
// We're setting the parameters via the object creation
TemplateRole signer = new TemplateRole
{
    Email = signerEmail,
    Name = signerName,
    RoleName = "signer",
    ClientUserId = signerClientId, // Change the signer to be embedded
    Tabs = tabs, // Set tab values
};

TemplateRole cc = new TemplateRole
{
    Email = ccEmail,
    Name = ccName,
    RoleName = "cc",
};

// Create an envelope custom field to save our application's
// data about the envelope
TextCustomField customField = new TextCustomField
{
    Name = "app metadata item",
    Required = "false",
    Show = "true", // Yes, include in the CoC
    Value = "1234567",
};

CustomFields cf = new CustomFields
{
    TextCustomFields = new List<TextCustomField> { customField },
};
```

**`Java`**

```java title="Java"
List list1 = new List();
list1.setValue("green");
list1.setDocumentId("1");
list1.setPageNumber("1");
list1.setTabLabel("list");

// Checkboxes
Checkbox ck1 = new Checkbox();
ck1.setTabLabel("ckAuthorization");
ck1.setSelected("true");

Checkbox ck2 = new Checkbox();
ck2.setTabLabel("ckAgreement");
ck2.setSelected("true");

Radio radio = new Radio();
radio.setValue("white");
radio.setSelected("true");

RadioGroup rg = new RadioGroup();
rg.setGroupName("radio1");
rg.setRadios(Collections.singletonList(radio));

Text txt = new Text();
txt.setTabLabel("text");
txt.setValue("Jabberywocky!");

// We can also add a new tab (field) to the ones already in the template:

Text txtExtra = new Text();
txtExtra.setDocumentId("1");
txtExtra.setPageNumber("1");
txtExtra.setXPosition("280");
txtExtra.setYPosition("172");
txtExtra.setFont("helvetica");
txtExtra.setFontSize("size14");
txtExtra.setTabLabel("added text field");
txtExtra.setHeight("23");
txtExtra.setWidth("84");
txtExtra.setRequired("false");
txtExtra.setBold("true");
txtExtra.setValue(signerName);
txtExtra.setLocked("false");
txtExtra.setTabId("name");

// Add the tabs model (including the SignHere tab) to the signer.
// The Tabs object wants arrays of the different field/tab types
// Tabs are set per recipient / signer

Tabs tabs = new Tabs();

tabs.setTextTabs(Arrays.asList(txt, txtExtra));
tabs.setRadioGroupTabs(Collections.singletonList(rg));
tabs.setCheckboxTabs(Arrays.asList(ck1, ck2));
tabs.setListTabs(Collections.singletonList(list1));

// create a signer recipient to sign the document, identified by name and email
// We're setting the parameters via the object creation
TemplateRole signer = new TemplateRole();
signer.setEmail(signerEmail);
signer.setName(signerName);
// Setting the client_user_id marks the signer as embedded
signer.setClientUserId(clientUserId);
signer.setRoleName("signer");
signer.setTabs(tabs);

TemplateRole cc = new TemplateRole();
cc.setEmail(ccEmail);
cc.setName(ccName);
cc.setRoleName("cc");

// Create an envelope custom field to save our application"s
// Data about the envelope
TextCustomField customField = new TextCustomField();
customField.setName("app metadata item");
customField.setValue("1234567");
customField.setRequired("false");
customField.show("true"); // Yes, include in the CoC

CustomFields cf = new CustomFields();
cf.setTextCustomFields(Collections.singletonList(customField));
```

**`Node.js`**

```javascript title="Node.js"
let list1 = docusign.List.constructFromObject({
  value: 'green',
  documentId: '1',
  pageNumber: '1',
  tabLabel: 'list',
});

// Checkboxes
let check1 = docusign.Checkbox.constructFromObject({
    tabLabel: 'ckAuthorization',
    selected: 'true',
  });
  let check3 = docusign.Checkbox.constructFromObject({
    tabLabel: 'ckAgreement',
    selected: 'true',
  });
// The NOde.js SDK has a bug so it cannot create a Number tab at this time.
// number1 = docusign.Number.constructFromObject({
//    tabLabel: "numbersOnly", value: '54321'});
let radioGroup = docusign.RadioGroup.constructFromObject({
  groupName: 'radio1',
  // You only need to provide the radio entry for the entry you're selecting
  radios: [
    docusign.Radio.constructFromObject({ value: 'white', selected: 'true' }),
  ],
});
let text = docusign.Text.constructFromObject({
  tabLabel: 'text',
  value: 'Jabberwocky!',
});

// We can also add a new tab (field) to the ones already in the template:
let textExtra = docusign.Text.constructFromObject({
  document_id: '1',
  page_number: '1',
  x_position: '280',
  y_position: '172',
  font: 'helvetica',
  font_size: 'size14',
  tab_label: 'added text field',
  height: '23',
  width: '84',
  required: 'false',
  bold: 'true',
  value: args.signerName,
  locked: 'false',
  tab_id: 'name',
});

// Pull together the existing and new tabs in a Tabs object:
let tabs = docusign.Tabs.constructFromObject({
  checkboxTabs: [check1, check3], // numberTabs: [number1],
  radioGroupTabs: [radioGroup],
  textTabs: [text, textExtra],
  listTabs: [list1],
});
// Create the template role elements to connect the signer and cc recipients
// to the template
let signer = docusign.TemplateRole.constructFromObject({
  email: args.signerEmail,
  name: args.signerName,
  roleName: 'signer',
  clientUserId: args.signerClientId, // change the signer to be embedded
  tabs: tabs, // Set tab values
});
// Create a cc template role.
let cc = docusign.TemplateRole.constructFromObject({
  email: args.ccEmail,
  name: args.ccName,
  roleName: 'cc',
});
// Add the TemplateRole objects to the envelope object
envelopeDefinition.templateRoles = [signer, cc];
// Create an envelope custom field to save the our application's
// data about the envelope
let customField = docusign.TextCustomField.constructFromObject({
    name: 'app metadata item',
    required: 'false',
    show: 'true', // Yes, include in the CoC
    value: '1234567',
  });
  let customFields = docusign.CustomFields.constructFromObject({
    textCustomFields: [customField],
  });
envelopeDefinition.customFields = customFields;

return envelopeDefinition;
}
```

**`PHP`**

```php title="PHP"
$check1 = new Checkbox([
    'tab_label' => 'ckAuthorization', 'selected' => "true"]);
$check3 = new Checkbox([
    'tab_label' => 'ckAgreement', 'selected' => "true"]);
$number1 = new Number([
    'tab_label' => "numbersOnly", 'value' => '54321']);
$radio_group = new RadioGroup(['group_name' => "radio1",
    # You only need to provide the radio entry for the entry you're selecting
    'radios' => [
        new Radio(['value' => "white", 'selected' => "true"]),
    ]]);
$text = new Text([
    'tab_label' => "text", 'value' => "Jabberwocky!"]);

# We can also add a new field to the ones already in the template:
$text_extra = new Text([
    'document_id' => "1", 'page_number' => "1",
    'x_position' => "280", 'y_position' => "172",
    'font' => "helvetica", 'font_size' => "size14", 'tab_label' => "added text field",
    'height' => "23", 'width' => "84", 'required' => "false",
    'bold' => 'true', 'value' => $args['signer_name'],
    'locked' => 'false', 'tab_id' => 'name']);

# Pull together the existing and new tabs in a Tabs object:
$tabs = new Tabs([
    'checkbox_tabs' => [$check1, $check3], 'number_tabs' => [$number1],
    'radio_group_tabs' => [$radio_group], 'text_tabs' => [$text, $text_extra]]);

# Create the template role elements to connect the signer and cc recipients
# to the template
$signer = new TemplateRole([
    'email' => $args['signer_email'], 'name' => $args['signer_name'],
    'role_name' => 'signer',
    'client_user_id' => $args['signer_client_id'], # change the signer to be embedded
    'tabs' => $tabs # Set tab values
]);
# Create a cc template role.
$cc = new TemplateRole([
    'email' => $args['cc_email'], 'name' => $args['cc_name'],
    'role_name' => 'cc'
]);

# Add the TemplateRole objects to the envelope object
$envelope_definition->setTemplateRoles([$signer, $cc]);

# Create an envelope custom field to save the our application's
# data about the envelope
$custom_field = new TextCustomField([
    'name' => 'app metadata item',
    'required' => 'false',
    'show' => 'true', # Yes, include in the CoC
    'value' => '1234567']);
$custom_fields = new CustomFields([
    'text_custom_fields' => [$custom_field]]);
$envelope_definition->setCustomFields($custom_fields);

return $envelope_definition;
```

**`PowerShell`**

```text title="PowerShell"
$text_custom_fields = @{
    "name" = "app metadata item"
    "required" = "false"
    "show" = "true"
    "value" = "1234567"
}

$checkbox_tabs = @{
    "selected1" = "true"
    "tabLabel1" = "ckAuthorization"
    "selected2" = "true"
    "tabLabel2" = "ckAgreement"
}

$list_tabs = @{
    "documentId" = "1"
    "pageNumber" = "1"
    "tabLabel" = "list"
    "value" = "green"
}

$radio_tabs = @{
    "selected" = "true"
    "value" = "white"
}

$text_tabs = @{
    "tabLabel" = "text"
    "value" = "Jabberywocky!"
}
```

**`Python`**

```python title="Python"
list1 = List(
    value="green", document_id="1",
    page_number="1", tab_label="list")

# Checkboxes
check1 = Checkbox(
    tab_label="ckAuthorization", selected="true")

check3 = Checkbox(
    tab_label="ckAgreement", selected="true")

radio_group = RadioGroup(
    group_name="radio1",
    radios=[Radio(value="white", selected="true")]
)

text = Text(
    tab_label="text", value="Jabberywocky!"
)

# We can also add a new tab (field) to the ones already in the template:
text_extra = Text(
    document_id="1", page_number="1",
    x_position="280", y_position="172",
    font="helvetica", font_size="size14",
    tab_label="added text field", height="23",
    width="84", required="false",
    bold="true", value=args["signer_name"],
    locked="false", tab_id="name"
)

# Add the tabs model (including the SignHere tab) to the signer.
# The Tabs object wants arrays of the different field/tab types
# Tabs are set per recipient / signer
tabs = Tabs(
    checkbox_tabs=[check1, check3], radio_group_tabs=[radio_group],
    text_tabs=[text, text_extra], list_tabs=[list1]
)

# create a signer recipient to sign the document, identified by name and email
# We"re setting the parameters via the object creation
signer = TemplateRole(  # The signer
    email=args["signer_email"], name=args["signer_name"],
    # Setting the client_user_id marks the signer as embedded
    client_user_id=args["signer_client_id"],
    role_name="signer",
    tabs=tabs
)

cc = TemplateRole(
    email=args["cc_email"],
    name=args["cc_name"],
    role_name="cc"
)

# create an envelope custom field to save our application"s
# data about the envelope

custom_field = TextCustomField(
    name="app metadata item",
    required="false",
    show="true",  # Yes, include in the CoC
    value="1234567"
)

cf = CustomFields(text_custom_fields=[custom_field])

# Next, create the top level envelope definition and populate it.
envelope_definition = EnvelopeDefinition(
    email_subject="Please sign this document sent from the Python SDK",
    # The Recipients object wants arrays for each recipient type
    template_id=session["template_id"],
    template_roles=[signer, cc],
    custom_fields=cf,
    status="sent"  # requests that the envelope be created and sent.
)

return envelope_definition
```

**`Ruby`**

```ruby title="Ruby"
list1 = DocuSign_eSign::List.new
list1.value = 'Green'
list1.document_id = '1'
list1.page_number = '1'
list1.tab_label = 'list'

# Checkboxes
check1 = DocuSign_eSign::Checkbox.new
check1.tab_label = 'ckAuthorization'
check1.selected = 'true'

check3 = DocuSign_eSign::Checkbox.new
check3.tab_label = 'ckAgreement'
check3.selected = 'true'

radioGroup = DocuSign_eSign::RadioGroup.new
radioGroup.group_name = 'radio1'
radio = DocuSign_eSign::Radio.new
radio.value = 'white'
radio.selected = 'true'
radioGroup.radios = [radio]

text = DocuSign_eSign::Text.new
text.tab_label = 'text'
text.value = 'Jabberwocky!'

# We can also add a new tab (field) to the ones already in the template
textExtra = DocuSign_eSign::Text.new
textExtra.document_id = '1'
textExtra.page_number = '1'
textExtra.x_position = '280'
textExtra.y_position = '172'
textExtra.font = 'helvetica'
textExtra.font_size = 'size14'
textExtra.tab_label = 'added text field'
textExtra.height = '23'
textExtra.width = '84'
textExtra.required = 'false'
textExtra.bold = 'true'
textExtra.value = args[:signer_name]
textExtra.locked = 'false'
textExtra.tab_id = 'name'

# Pull together the existing and new tabs in a Tabs object
tabs = DocuSign_eSign::Tabs.new
tabs.list_tabs = [list1]
tabs.checkbox_tabs = [check1, check3]
tabs.radio_group_tabs = [radioGroup]
tabs.text_tabs = [text, textExtra]
signer.tabs = tabs

# Add the TemplateRole objects to the envelope object
envelope_definition.template_roles = [signer, cc]
envelope_definition
```

## Step 4. Construct the request body

Next, create the request body. If using a launcher, you can use an **Envelope Definition** method to build a valid request body.

Make sure to substitute your valid template ID for \{TEMPLATE_ID} and the correlated `templateRoles` as defined on the [template](/docs/esign-rest-api/how-to/set-template-tab-values) being used.

**`Bash`**

```bash title="Bash"
printf \
'{
    "customFields": {
        "textCustomFields": [{
            "name": "'"${text_custom_fields["name"]}"'",
            "required": "'"${text_custom_fields["required"]}"'",
            "show": "'"${text_custom_fields["show"]}"'",
            "value": "'"${text_custom_fields["value"]}"'"
        }]
    },
    "status": "Sent",
    "templateId": "'"${template_id}"'",
    "templateRoles": [{
        "clientUserId": "1000",
        "email": "'"${SIGNER_EMAIL}"'",
        "name": "'"${SIGNER_NAME}"'",
        "roleName": "signer",
        "tabs": {
            "checkboxTabs": [{
                "selected": "'"${checkbox_tabs["selected1"]}"'",
                "tabLabel": "'"${checkbox_tabs["tabLabel1"]}"'"
            }, {
                "selected": "'"${checkbox_tabs["selected2"]}"'",
                "tabLabel": "'"${checkbox_tabs["tabLabel2"]}"'"
            }],
            "listTabs": [{
                "documentId": "'"${list_tabs["documentId"]}"'",
                "pageNumber": "'"${list_tabs["pageNumber"]}"'",
                "tabLabel": "'"${list_tabs["tabLabel"]}"'",
                "value": "'"${list_tabs["value"]}"'"
            }],
            "radioGroupTabs": [{
                "groupName": "radio1",
                "radios": [{
                    "selected": "'"${radio_tabs["selected"]}"'",
                    "value": "'"${radio_tabs["value"]}"'"
                }]
            }],
            "textTabs": [{
                "tabLabel": "'"${text_tabs["tabLabel"]}"'",
                "value": "'"${text_tabs["value"]}"'"
            }, {
                "bold": "true",
                "documentId": "1",
                "font": "helvetica",
                "fontSize": "size14",
                "height": "23",
                "locked": "false",
                "pageNumber": "1",
                "required": "false",
                "tabId": "name",
                "tabLabel": "added text field",
                "value": "'"${SIGNER_NAME}"'",
                "width": "84",
                "xPosition": "280",
                "yPosition": "172"
            }]
        }
    }, {
        "email": "'"${CC_EMAIL}"'",
        "name": "'"${CC_NAME}"'",
        "roleName": "cc"
    }]
}' >> $request_data
```

**`C#`**

```csharp title="C#"
EnvelopeDefinition envelopeAttributes = new EnvelopeDefinition
{
    // Uses the template ID received from example 08
    TemplateId = templateId,
    Status = "Sent",

    // Add the TemplateRole objects to utilize a pre-defined
    // document and signing/routing order on an envelope.
    // Template role names need to match what is available on
    // the correlated templateID or else an error will occur
    TemplateRoles = new List<TemplateRole> { signer, cc },
    CustomFields = cf,
};
```

**`Java`**

```java title="Java"
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
envelopeDefinition.setEmailSubject("Please sign this document from the Java SDK");
// The Recipients object wants arrays for each recipient type
envelopeDefinition.setTemplateId(templateId);
envelopeDefinition.setTemplateRoles(Arrays.asList(signer, cc));
envelopeDefinition.setCustomFields(cf);
// Request that the envelope be sent by setting |status| to "sent".
// To request that the envelope be created as a draft, set to "created"
envelopeDefinition.setStatus(EnvelopeHelpers.ENVELOPE_STATUS_SENT);

return envelopeDefinition;
```

**`Node.js`**

```javascript title="Node.js"
let envelopeArgs = args.envelopeArgs;
  let envelopeDefinition = makeEnvelope(envelopeArgs);
```

**`PHP`**

```php title="PHP"
$envelope_definition = new EnvelopeDefinition([
    'status' => 'sent', 'template_id' => $args['template_id']
]);
```

**`PowerShell`**

```text title="PowerShell"
@{
    customFields  = @{
        textCustomFields = @(
            @{
                name = $($text_custom_fields['name']);
                required = $($text_custom_fields['required']);
                show     = $($text_custom_fields['show']);
                value    = $($text_custom_fields['value']);
            };
        );
    };
    templateRoles = @(
        @{
            clientUserId = "1000";
            email        = $variables.SIGNER_EMAIL;
            name         = $variables.SIGNER_NAME;
            roleName     = "signer";
            tabs         = @{
                checkboxTabs   = @(
                    @{
                        selected = $($checkbox_tabs['selected1']);
                        tabLabel = $($checkbox_tabs['tabLabel1']);
                    };
                    @{
                        selected = $($checkbox_tabs['selected2']);
                        tabLabel = $($checkbox_tabs['tabLabel2']);
                    };
                );
                listTabs       = @(
                    @{
                        documentId = $($list_tabs['documentId']);
                        pageNumber = $($list_tabs['pageNumber']);
                        tabLabel   = $($list_tabs['tabLabel']);
                        value      = $($list_tabs['value']);
                    };
                );
                radioGroupTabs = @(
                    @{
                        groupName = "radio1";
                        radios    = @(
                            @{
                                selected = $($radio_tabs['selected']);
                                value    = $($radio_tabs['value']);
                            };
                        );
                    };
                );
                textTabs       = @(
                    @{
                        tabLabel = $($text_tabs['tabLabel']);
                        value    = $($text_tabs['value']);
                    };
                    @{
                        bold       = "true";
                        documentId = "1";
                        font       = "helvetica";
                        fontSize   = "size14";
                        height     = "23";
                        locked     = "false";
                        pageNumber = "1";
                        required   = "false";
                        tabId      = "name";
                        tabLabel   = "added text field";
                        value      = $variables.SIGNER_NAME;
                        width      = "84";
                        xPosition  = "280";
                        yPosition  = "172";
                    };
                );
            };
        };
        @{
            email    = $variables.CC_EMAIL;
            name     = $variables.CC_NAME;
            roleName = "cc";
        };
    );
    status        = "Sent";
    templateId    = "$templateId";
} | ConvertTo-Json -Depth 32 > $requestData
```

**`Python`**

```python title="Python"
envelope_definition = cls.make_envelope(envelope_args)
```

**`Ruby`**

```ruby title="Ruby"
envelope_definition = make_envelope(envelope_args)
```

## Step 5. Call the eSignature REST API

Now that you have constructed your API headers, make a POST request to the [Envelopes:create](/docs/esign-rest-api/reference/envelopes/envelopes/create) endpoint to create an envelope.

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

**`Bash`**

```bash title="Bash"
Status=$(curl -w '%{http_code}' -i --request POST ${base_path}/v2.1/accounts/${account_id}/envelopes \
     "${Headers[@]}" \
     --data-binary @${request_data} \
     --output ${response})
```

**`C#`**

```csharp title="C#"
EnvelopesApi envelopesApi = new EnvelopesApi(docuSignClient);
var results = envelopesApi.CreateEnvelopeWithHttpInfo(accountId, envelopeAttributes);
results.Headers.TryGetValue("X-RateLimit-Remaining", out string remaining);
results.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"
var envelopeSummary = envelopesApi.createEnvelopeWithHttpInfo(accountId, envelope, envelopesApi.new CreateEnvelopeOptions());
Map<String, java.util.List<String>> headers = envelopeSummary.getHeaders();
java.util.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);
}
String envelopeId = envelopeSummary.getData().getEnvelopeId();
session.setEnvelopeId(envelopeId);
```

**`Node.js`**

```javascript title="Node.js"
let envelopesApi = new docusign.EnvelopesApi(dsApiClient);
  let results = await envelopesApi.createEnvelope(args.accountId, {
    envelopeDefinition: envelopeDefinition,
  }, (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()}`);
    }
});
  let envelopeId = results.data.envelopeId;
```

**`PHP`**

```php title="PHP"
# Call Envelopes::create API method
# Exceptions will be caught by the calling function
$envelope_api = $clientService->getEnvelopeApi();
$envelopeResponse = $envelope_api->createEnvelopeWithHttpInfo($args['account_id'], $envelope_definition);

$remaining = $envelopeResponse[2]['X-RateLimit-Remaining'] ?? null;
$reset =  $envelopeResponse[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));
}

$envelope_id = $envelopeResponse[0]->getEnvelopeId();
```

**`PowerShell`**

```text title="PowerShell"
Invoke-RestMethod `
    -Uri "${apiUri}/v2.1/accounts/${accountId}/envelopes" `
    -Method 'POST' `
    -Headers $headers `
    -InFile (Resolve-Path $requestData).Path `
    -OutFile $response
```

**`Python`**

```python title="Python"
envelopes_api = EnvelopesApi(api_client)
(results, status, headers) = envelopes_api.create_envelope_with_http_info(account_id=args["account_id"], envelope_definition=envelope_definition)

remaining = headers.get("X-RateLimit-Remaining")
reset = headers.get("X-RateLimit-Reset")

if remaining is not None and reset is not None:
    reset_date = dt.fromtimestamp(int(reset), tz=timezone.utc)
    print(f"API calls remaining: {remaining}")
    print(f"Next Reset: {reset_date}")

envelope_id = results.envelope_id
```

**`Ruby`**

```ruby title="Ruby"
envelope_api = create_envelope_api(args)
results, _status, headers = envelope_api.create_envelope_with_http_info args[:account_id], envelope_definition

remaining = headers['X-RateLimit-Remaining']
reset = headers['X-RateLimit-Reset']

if remaining && reset
  reset_date = Time.at(reset.to_i).utc
  puts "API calls remaining: #{remaining}"
  puts "Next Reset: #{reset_date}"
end

envelope_id = results.envelope_id
```

## Step 6. Create the view request

Create your recipient view request to begin an [embedded signing](/docs/esign-rest-api/esign101/concepts/embedding)

session. Include your Redirect URI as the return URL, plus the \{CLIENT_SIGNER_ID} and the \{SIGNER_NAME}.

Use the [EnvelopeViews:createRecipient](/docs/esign-rest-api/reference/envelopes/envelopeviews/createrecipient) method to return an embedded signing URL by providing your \{API_ACCOUNT_ID}, the generated envelope ID from earlier, and the view request you generated previously. Use the embedded signing URL within your application to sign documents.

> **Note**
>
> View the source code for this how-to on GitHub:
> [Bash](https://github.com/docusign/code-examples-bash/blob/master/examples/eSignature/eg017SetTemplateTabValues.sh), [C#](https://github.com/docusign/code-examples-csharp/blob/master/launcher-csharp/eSignature/Examples/SetTemplateTabValues.cs), [Java](https://github.com/docusign/code-examples-java/blob/master/src/main/java/com/docusign/controller/eSignature/examples/EG017ControllerSetTemplateTabValues.java), [Node.js](https://github.com/docusign/code-examples-node/blob/master/lib/eSignature/examples/setTemplateTabValues.js), [PHP](https://github.com/docusign/code-examples-php/blob/master/src/Services/Examples/eSignature/SetTemplateTabValuesService.php), [PowerShell](https://github.com/docusign/code-examples-powershell/blob/master/examples/eSignature/eg017SetTemplateTabValues.ps1), [Python](https://github.com/docusign/code-examples-python/blob/master/app/eSignature/examples/eg017_set_template_tab_values.py), or [Ruby](https://github.com/docusign/code-examples-ruby/blob/main/app/services/e_sign/eg017_set_template_tab_values_service.rb).

**`Bash`**

```bash title="Bash"
curl --header "Authorization: Bearer ${ACCESS_TOKEN}" \
     --header "Content-Type: application/json" \
     --data-binary '
{
    "returnUrl": "http://httpbin.org/get",
    "authenticationMethod": "none",
    "email": "'"${SIGNER_EMAIL}"'",
    "userName": "'"${SIGNER_NAME}"'",
    "clientUserId": 1000,
}' \
     --request POST ${base_path}/v2.1/accounts/${account_id}/envelopes/${envelope_id}/views/recipient \
     --output ${response}
```

**`C#`**

```csharp title="C#"
RecipientViewRequest viewRequest = new RecipientViewRequest();

// Set the URL where you want the recipient to go once they are done signing;
// this should typically be a callback route somewhere in your app.
// The query parameter is included as an example of how
// to save/recover state information during the redirect to
// the DocuSign signing ceremony. It's usually better to use
// the session mechanism of your web framework. Query parameters
// can be changed/spoofed very easily
viewRequest.ReturnUrl = returnUrl + "?state=123";

// How has your app authenticated the user? In addition to your app's authentication,
// you can include authentication steps from DocuSign; e.g., SMS authentication
viewRequest.AuthenticationMethod = "none";

// Recipient information must match the embedded recipient info
// that we used to create the envelope
viewRequest.Email = signerEmail;
viewRequest.UserName = signerName;
viewRequest.ClientUserId = signerClientId;

// DocuSign recommends that you redirect to DocuSign for the
// signing ceremony. There are multiple ways to save state.
// To maintain your application's session, use the PingUrl
// parameter. It causes the DocuSign Signing Ceremony web page
// (not the DocuSign server) to send pings via AJAX to your app
viewRequest.PingFrequency = "600"; // seconds

// NOTE: The pings will only be sent if the pingUrl is an HTTPS address
viewRequest.PingUrl = pingUrl; // Optional setting

var results1 = envelopesApi.CreateRecipientViewWithHttpInfo(accountId, results.Data.EnvelopeId, viewRequest);
results.Headers.TryGetValue("X-RateLimit-Remaining", out remaining);
results.Headers.TryGetValue("X-RateLimit-Reset", out 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);
}

// ***********
// Don't use an iframe with embedded signing requests!
// ***********
// State can be stored/recovered using the framework's session or a
// query parameter on the return URL (see the makeRecipientViewRequest method)
return (envelopeId, results1.Data.Url);
```

**`Java`**

```java title="Java"
RecipientViewRequest viewRequest = new RecipientViewRequest();
// Set the url where you want the recipient to go once they are done signing
// should typically be a callback route somewhere in your app.
// The query parameter is included as an example of how
// to save/recover state information during the redirect to
// the DocuSign signing. It's usually better to use
// the session mechanism of your web framework. Query parameters
// can be changed/spoofed very easily.
String state = "?state=123";
viewRequest.setReturnUrl(dsReturnUrl + state);

return SetTabValuesService.setEmailAndSignerNameForRecipientViewRequest(
        viewRequest,
        signerEmail,
        signerName,
        dsPingUrl);
```

**`Node.js`**

```javascript title="Node.js"
let viewRequest = docusign.RecipientViewRequest.constructFromObject({
  returnUrl: envelopeArgs.dsReturnUrl,
  authenticationMethod: 'none',
  email: envelopeArgs.signerEmail,
  userName: envelopeArgs.signerName,
  clientUserId: envelopeArgs.signerClientId,
});

// Call the CreateRecipientView API
// Exceptions will be caught by the calling function
results = await envelopesApi.createRecipientView(args.accountId, envelopeId, {
  recipientViewRequest: viewRequest,
}, (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()}`);
    }
});

return { envelopeId: envelopeId, redirectUrl: results.data.url };
};
```

**`PHP`**

```php title="PHP"
# Create the Recipient View request object
$authentication_method = 'None'; # How is this application authenticating
# the signer? See the `authentication_method' definition
# https://developers.docusign.com/esign-rest-api/reference/Envelopes/EnvelopeViews/createRecipient
$recipient_view_request = $clientService->getRecipientViewRequest(
    $authentication_method,
    $args["envelope_args"]
);

# Obtain the recipient_view_url for the embedded signing
# Exceptions will be caught by the calling function
$recipientView = $clientService->getRecipientView($args['account_id'], $envelope_id, $recipient_view_request);

return ['envelope_id' => $envelope_id, 'redirect_url' => $recipientView['url']];
```

**`PowerShell`**

```text title="PowerShell"
@{
    returnUrl            = "http://httpbin.org/get";
    authenticationMethod = "none";
    email                = $variables.SIGNER_EMAIL;
    userName             = $variables.SIGNER_NAME;
    clientUserId         = 1000;
} | ConvertTo-Json -Depth 32 > $requestData

Invoke-RestMethod `
    -Uri "${apiUri}/v2.1/accounts/${accountId}/envelopes/${envelopeId}/views/recipient" `
    -Method 'POST' `
    -Headers @{
    'Authorization' = "Bearer $accessToken";
    'Content-Type'  = "application/json";
} `
    -InFile (Resolve-Path $requestData).Path`
    -OutFile $response
```

**`Python`**

```python title="Python"
recipient_view_request = RecipientViewRequest(
    authentication_method=authentication_method,
    client_user_id=envelope_args["signer_client_id"],
    recipient_id="1",
    return_url=envelope_args["ds_return_url"],
    user_name=envelope_args["signer_name"], email=envelope_args["signer_email"]
)
# Obtain the recipient_view_url for the embedded signing
# Exceptions will be caught by the calling function
(results, status, headers) = envelopes_api.create_recipient_view_with_http_info(
    account_id=args["account_id"],
    envelope_id=envelope_id,
    recipient_view_request=recipient_view_request
)

remaining = headers.get("X-RateLimit-Remaining")
reset = headers.get("X-RateLimit-Reset")

if remaining is not None and reset is not None:
    reset_date = dt.fromtimestamp(int(reset), tz=timezone.utc)
    print(f"API calls remaining: {remaining}")
    print(f"Next Reset: {reset_date}")

return {"envelope_id": envelope_id, "redirect_url": results.url}
```

**`Ruby`**

```ruby title="Ruby"
view_request = make_recipient_view_request(envelope_args[:signer_email], envelope_args[:signer_name], signer_client_id, ds_return_url, ds_ping_url)

# Call the CreateRecipientView API
results, _status, headers = envelope_api.create_recipient_view_with_http_info args[:account_id], envelope_id, view_request

remaining = headers['X-RateLimit-Remaining']
reset = headers['X-RateLimit-Reset']

if remaining && reset
  reset_date = Time.at(reset.to_i).utc
  puts "API calls remaining: #{remaining}"
  puts "Next Reset: #{reset_date}"
end

# Redirect the user to the embedded signing
# Don't use an iframe!
# State can be stored/recovered using the framework's session or a
# query parameter on the return URL (see the makeRecipientViewRequest method)
# Redirect to results.url
results.url
```

## 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.

**`Sample response`**

```json title="Sample response"
{
  "envelopeId": "b4e027e1-xxxx-xxxx-xxxx-ad00ccc8cf3e",
  "uri": "/envelopes/b4e027e1-xxxx-xxxx-xxxx-ad00ccc8cf3e",
  "statusDateTime": "2020-08-12T23:12:01.2930000Z",
  "status": "sent"
}
```

## 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).
* See [tabs](/docs/esign-rest-api/esign101/concepts/tabs) for options on placing tabs.
* Find out more about [templates](/docs/esign-rest-api/esign101/concepts/templates).
* See how to [Go-Live](/docs/esign-rest-api/go-live) with a completed app and find the base path for API calls in the production environment.