> 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 request a signature using focused view

> Demonstrates how to request a signature using focused view, a minimal wrapper around the agreement document.

eSignature REST API 2.1 only

This topic demonstrates how to improve an embedded signing experience by using focused view. [Focused view](/docs/esign-rest-api/esign101/concepts/embedding/embedded-signing#focused-view) offers a minimal wrapper around the agreement document that shows only the agreement and a navigation button, making the experience look similar to embedding just the document within your web page.

> **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:- [PDF file](https://github.com/docusign/code-examples-java/blob/master/src/main/resources/World_Wide_Corp_lorem.pdf)                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| frameAncestors         | An array that represents the potential page origins for the focused view feature. An origin consists of the protocol, domain, and optional port. [https://example.com](https://example.com)is an origin. [https://example.com/](https://example.com/) is not an origin since it includes a path (the trailing /). Include your site’s origin along with [https://apps-d.docusign.com](https://apps-d.docusign.com) for developer environments or [https://apps.docusign.com](https://apps.docusign.com) for production environments. Your site must have a valid SSL certificate unless you are using a  domain. In production, only the HTTPS protocol is supported. |
| messageOrigins         | A string that represents the originating domain for the signature request message. It must be either [https://apps-d.docusign.com](https://apps-d.docusign.com) for developer environments or [https://apps.docusign.com](https://apps.docusign.com) for production environments.                                                                                                                                                                                                                                                                                                                                                                                     |
| Return URL             | A URL to which the user will be forwarded after signing is complete.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| \{SIGNER_EMAIL}        | A string value for the email address where the signer will receive a notification of the signing request.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| \{SIGNER_NAME}         | A string value for the full name of the signer.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |

## 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. Create the envelope definition

The first step in requesting a signature within your app is to define a method (called `makeEnvelope` in our example) that creates the envelope definition using the following steps:

* Add a document to the definition by saving it to a variable as a binary-encoded base64 string. If you intend to attach multiple documents, specify the document order using an array. The order of the array sets the order of the documents.
* Set the signer's data, including their name, email address, and a client user ID (any alphanumeric value is suitable). Including a client user ID automatically specifies the signer as embedded (using your app). If there are multiple signers, you must create a signer recipient for each one.

  **Note:** If the client user ID is set and either the `SignerMustHaveAccount` or `SignerMustLoginToSign` property of the account settings is set to `true`, the system throws an error.
* Create and assign signable fields (also known as tabs) for a specific signer within the document using [AutoPlace](/docs/esign-rest-api/esign101/concepts/tabs/auto-place). This how-to uses anchor tabs to generate tabs automatically in your document by searching for each occurrence of a specific string of characters in the document and adding tabs at those locations. This example uses the string "`/sn1/`" for auto-placing the signature (`signHere`) tab.

  To configure the anchor tabs, specify the number of units from the anchor text to offset the tab, as well as the string to search for and replace with a `signHereTab` within your document. You can create multiple `signHere` tabs for different locations and offsets, if needed.

  After creating the tabs, assign them to the signer created in the previous step.
* Set the envelope's `status` property. To save the envelope as a draft, set `status` to `created`. To configure the envelope to be sent immediately after it is instantiated, set `status` to `sent` instead.

**`Bash`**

```bash title="Bash"
cat > "$request_data" <<EOF
{
    "emailSubject": "Please sign this document set",
    "documents": [
        {
            "documentBase64": "${doc1_base64_content}",
            "name": "Lorem Ipsum",
            "fileExtension": "pdf",
            "documentId": "1"
        }
    ],
    "recipients": {
        "signers": [
            {
                "email": "${SIGNER_EMAIL}",
                "name": "${SIGNER_NAME}",
                "recipientId": "1",
                "routingOrder": "1",
                "clientUserId": "1000"${identity_verification_json}
            }
        ]
    },
    "status": "sent"
}
EOF
```

**`C#`**

```csharp title="C#"
public static EnvelopeDefinition MakeEnvelope(
    string signerEmail,
    string signerName,
    string signerClientId,
    string docPdf,
    string countryCode = null,
    string phoneNumber = null,
    string workflowId = null)
{
    // Data for this method:
    // signerEmail
    // signerName
    // signerClientId -- class global
    // Config.docPdf
    // countryCode (optional)
    // phoneNumber (optional)
    // workflowId (optional)
    byte[] buffer = System.IO.File.ReadAllBytes(docPdf);

    EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
    envelopeDefinition.EmailSubject = "Please sign this document";
    Document doc = new Document();

    string docb64 = Convert.ToBase64String(buffer);

    doc.DocumentBase64 = docb64;
    doc.Name = "Lorem Ipsum"; // Can be different from the actual file name
    doc.FileExtension = "pdf";
    doc.DocumentId = "3";

    // The order in the docs array determines the order in the envelope
    envelopeDefinition.Documents = new List<Document> { doc };

    // Create a signer recipient to sign the document, identified by name and email
    // We set the clientUserId to enable embedded signing for the recipient
    // We're setting the parameters via the object creation
    Signer signer = new Signer
    {
        Email = signerEmail,
        Name = signerName,
        ClientUserId = signerClientId,
        RecipientId = "1",
    };

    if (!string.IsNullOrWhiteSpace(phoneNumber))
    {
        signer.IdentityVerification = new RecipientIdentityVerification
        {
            WorkflowId = workflowId,
            InputOptions = new List<RecipientIdentityInputOption>
            {
                new RecipientIdentityInputOption
                {
                    Name = "phone_number_list",
                    ValueType = "PhoneNumberList",
                    PhoneNumberList = new List<RecipientIdentityPhoneNumber>
                    {
                        new RecipientIdentityPhoneNumber
                        {
                            CountryCode = countryCode,
                            Number = phoneNumber,
                        },
                    },
                },
            },
        };
    }

    // Add the recipient to the envelope object
    Recipients recipients = new Recipients
    {
        Signers = new List<Signer> { signer },
    };
    envelopeDefinition.Recipients = recipients;

    // 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.Status = "sent";

    return envelopeDefinition;
}
```

**`Java`**

```java title="Java"
public EnvelopeDefinition makeEnvelope(
        String signerEmail,
        String signerName,
        String signerClientId,
        String workflowId,
        String phoneNumber,
        String countryCode,
        String documentFileName,
        String documentName) throws IOException {
    String emailSubject = "Please sign this document";
    String recipientId = "1";
    String docId = "3";

    Signer signer = new Signer();
    signer.setEmail(signerEmail);
    signer.setName(signerName);
    signer.clientUserId(signerClientId);
    signer.recipientId(recipientId);

    if (phoneNumber != null && !phoneNumber.isBlank()) {
        RecipientIdentityPhoneNumber recipientIdentityPhoneNumber = new RecipientIdentityPhoneNumber();
        recipientIdentityPhoneNumber.setCountryCode(countryCode);
        recipientIdentityPhoneNumber.setNumber(phoneNumber);

        RecipientIdentityInputOption inputOption = new RecipientIdentityInputOption();
        inputOption.setName("phone_number_list");
        inputOption.setValueType("PhoneNumberList");
        inputOption.setPhoneNumberList(List.of(recipientIdentityPhoneNumber));

        RecipientIdentityVerification identityVerification = new RecipientIdentityVerification();
        identityVerification.setWorkflowId(workflowId);
        identityVerification.setInputOptions(List.of(inputOption));

        signer.setIdentityVerification(identityVerification);
    }

    Recipients recipients = new Recipients();
    recipients.setSigners(Collections.singletonList(signer));

    EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
    envelopeDefinition.setEmailSubject(emailSubject);
    envelopeDefinition.setRecipients(recipients);

    Document document = EnvelopeHelpers.createDocumentFromFile(documentFileName, documentName, docId);
    envelopeDefinition.setDocuments(Collections.singletonList(document));
    envelopeDefinition.setStatus(EnvelopeHelpers.ENVELOPE_STATUS_SENT);

    return envelopeDefinition;
}
```

**`Node.js`**

```javascript title="Node.js"
function makeEnvelope(args) {
  // Data for this method
  // args.signerEmail
  // args.signerName
  // args.signerClientId
  // args.workflowId (optional, when phone auth is used)
  // args.phoneNumber (optional)
  // args.countryCode (optional0)
  // args.docFile

  // document 1 (pdf) has tag /sn1/
  //
  // The envelope has one recipients.
  // recipient 1 - signer

  let docPdfBytes;
  // read file from a local directory
  // The read could raise an exception if the file is not available!
  docPdfBytes = fs.readFileSync(args.docFile);

  // create the envelope definition
  let env = new docusign.EnvelopeDefinition();
  env.emailSubject = 'Please sign this document';

  // add the documents
  let doc1 = new docusign.Document();
  let doc1b64 = Buffer.from(docPdfBytes).toString('base64');
  doc1.documentBase64 = doc1b64;
  doc1.name = 'Lorem Ipsum'; // can be different from actual file name
  doc1.fileExtension = 'pdf';
  doc1.documentId = '3';

  // The order in the docs array determines the order in the envelope
  env.documents = [doc1];

  // Create a signer recipient to sign the document, identified by name and email
  // We set the clientUserId to enable embedded signing for the recipient
  // We're setting the parameters via the object creation
  let signer1 = docusign.Signer.constructFromObject({
    email: args.signerEmail,
    name: args.signerName,
    clientUserId: args.signerClientId,
    recipientId: 1,
  });

  // Add phone authentication if phone number is provided
  if (args.phoneNumber) {
    signer1.identityVerification = {
      workflowId: args.workflowId,
      steps: null,
      inputOptions: [{
        name: 'phone_number_list',
        valueType: 'PhoneNumberList',
        phoneNumberList: [{
          countryCode: args.countryCode,
          number: args.phoneNumber
        }]
      }],
      idCheckConfigurationName: ''
    };
  }

  // Add the recipient to the envelope object
  let recipients = docusign.Recipients.constructFromObject({
    signers: [signer1],
  });
  env.recipients = recipients;

  // Request that the envelope be sent by setting |status| to "sent".
  // To request that the envelope be created as a draft, set to "created"
  env.status = 'sent';

  return env;
}
```

**`PHP`**

```php title="PHP"
public static function makeEnvelope(array $args, string $demo_path, string $pdf_file): EnvelopeDefinition
{
    $content_bytes = file_get_contents($demo_path . $pdf_file);
    $base64_file_content = base64_encode($content_bytes);

    $document = new Document(
        [
            'document_base64' => $base64_file_content,
            'name' => 'Example document',
            'file_extension' => 'pdf',
            'document_id' => 1
        ]
    );

    $signer = new Signer(
        [
            'email' => $args['signer_email'],
            'name' => $args['signer_name'],
            'recipient_id' => '1',
            'routing_order' => '1',
            'client_user_id' => $args['signer_client_id']
        ]
    );

    if (!empty($args['phone_number'])) {
        $phone_number = new RecipientIdentityPhoneNumber();
        $phone_number->setCountryCode($args['country_code'] ?? '');
        $phone_number->setNumber($args['phone_number']);

        $input_option = new RecipientIdentityInputOption();
        $input_option->setName('phone_number_list');
        $input_option->setValueType('PhoneNumberList');
        $input_option->setPhoneNumberList([$phone_number]);

        $identity_verification = new RecipientIdentityVerification();
        $identity_verification->setWorkflowId($args['workflow_id']);
        $identity_verification->setInputOptions([$input_option]);

        $signer->setIdentityVerification($identity_verification);
    }

    return new EnvelopeDefinition(
        [
            'email_subject' => 'Please sign this document sent from the PHP SDK',
            'documents' => [$document],
            'recipients' => new Recipients(['signers' => [$signer]]),
            'status' => 'sent'
        ]
    );
}
```

**`PowerShell`**

```text title="PowerShell"
$signer = @{
    email        = $variables.SIGNER_EMAIL;
    name         = $variables.SIGNER_NAME;
    recipientId  = "1";
    routingOrder = "1";
    clientUserId = "1000";
}

if ($usePhoneAuthentication) {
    $signer.identityVerification = @{
        workflowId               = $workflowId;
        steps                    = $null;
        inputOptions             = @(
            @{
                name            = "phone_number_list";
                valueType       = "PhoneNumberList";
                phoneNumberList = @(
                    @{
                        countryCode = $signerCountryCode;
                        number      = $signerPhoneNumber;
                    }
                );
            }
        );
        idCheckConfigurationName = "";
    }
}

@{
    emailSubject = "Please sign this document set";
    documents    = @(
        @{
            documentBase64 = "$(Get-Content $doc1Base64)";
            name           = "Lorem Ipsum";
            fileExtension  = "pdf";
            documentId     = "1";
        }
    );
    recipients   = @{
        signers = @(
            $signer
        );
    };
    status       = "sent";
} | ConvertTo-Json -Depth 32 > $requestData
```

**`Python`**

```python title="Python"
def make_envelope(cls, args):
    """
    Creates envelope
    args -- parameters for the envelope:
    signer_email, signer_name, signer_client_id
    returns an envelope definition
    """

    # document 1 (pdf) has tag /sn1/
    #
    # The envelope has one recipient.
    # recipient 1 - signer
    with open(path.join(demo_docs_path, DS_CONFIG["doc_pdf"]), "rb") as file:
        content_bytes = file.read()
    base64_file_content = base64.b64encode(content_bytes).decode("ascii")

    # Create the document model
    document = Document(  # create the DocuSign document object
        document_base64=base64_file_content,
        name="Example document",  # can be different from actual file name
        file_extension="pdf",  # many different document types are accepted
        document_id=1  # a label used to reference the doc
    )

    # Create the signer recipient model
    signer = Signer(
        # The signer
        email=args["signer_email"],
        name=args["signer_name"],
        recipient_id="1",
        routing_order="1",
        # Setting the client_user_id marks the signer as embedded
        client_user_id=args["signer_client_id"]
    )

    if args.get("phone_number"):
        signer.identity_verification = RecipientIdentityVerification(
            workflow_id=args["workflow_id"],
            steps=None,
            id_check_configuration_name="",
            input_options = [
                RecipientIdentityInputOption(
                    name="phone_number_list",
                    value_type="PhoneNumberList",
                    phone_number_list=[
                        RecipientIdentityPhoneNumber(
                            country_code=args["country_code"],
                            number=args["phone_number"]
                        )
                    ]
                )
            ]
        )

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

    return envelope_definition
```

**`Ruby`**

```ruby title="Ruby"
def make_envelope(signer_client_id, pdf_filename, signer_email, signer_name, args = {})
  envelope_definition = DocuSign_eSign::EnvelopeDefinition.new
  envelope_definition.email_subject = 'Please sign this document sent from Ruby SDK'

  doc1 = DocuSign_eSign::Document.new
  doc1.document_base64 = Base64.encode64(File.binread(pdf_filename))
  doc1.name = 'Lorem Ipsum'
  doc1.file_extension = 'pdf'
  doc1.document_id = '1'

  # The order in the docs array determines the order in the envelope
  envelope_definition.documents = [doc1]
  # Create a signer recipient to sign the document, identified by name and email
  # We're setting the parameters via the object creation
  signer1 = DocuSign_eSign::Signer.new({
                                         email: signer_email, name: signer_name,
                                         clientUserId: signer_client_id, recipientId: 1
                                       })

  if args[:phone_number].present?
    recipient_identity_phone_number = DocuSign_eSign::RecipientIdentityPhoneNumber.new
    recipient_identity_phone_number.country_code = args[:country_code]
    recipient_identity_phone_number.number = args[:phone_number]

    recipient_identity_input_option = DocuSign_eSign::RecipientIdentityInputOption.new
    recipient_identity_input_option.name = 'phone_number_list'
    recipient_identity_input_option.value_type = 'PhoneNumberList'
    recipient_identity_input_option.phone_number_list = [recipient_identity_phone_number]

    recipient_identity_verification = DocuSign_eSign::RecipientIdentityVerification.new
    recipient_identity_verification.workflow_id = args[:workflow_id]
    recipient_identity_verification.input_options = [recipient_identity_input_option]

    signer1.identity_verification = recipient_identity_verification
  end

  # Add the recipients to the envelope object
  recipients = DocuSign_eSign::Recipients.new
  recipients.signers = [signer1]

  envelope_definition.recipients = recipients
  # Request that the envelope be sent by setting status to "sent".
  # To request that the envelope be created as a draft, set status to "created"
  envelope_definition.status = 'sent'
  envelope_definition
end
```

## Step 3. Call Docusign to create the envelope

With the envelope definition and the attributes defined for the signer, document, and custom fields, you can now use the [Envelopes:create](/docs/esign-rest-api/reference/envelopes/envelopes/create) endpoint to create an envelope for the transaction.

* First, instantiate a new instance of the API client (if you're using a Docusign SDK).
* Set the following default request header to add your access token to all API calls.
  `"Authorization: Bearer ${ACCESS_TOKEN}"`
* Initialize the Envelopes API.
* Using your Docusign integration key and the prepared envelope definition, generate and retrieve an envelope ID using the [Envelopes:create](/docs/esign-rest-api/reference/envelopes/envelopes/create) endpoint.

**`Bash`**

```bash title="Bash"
create_envelope_http_status=$(curl --silent --show-error \
    --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Content-Type: application/json" \
    --data-binary @"${request_data}" \
    --request POST "${base_path}/v2.1/accounts/${ACCOUNT_ID}/envelopes" \
    --output "${response}" \
    --write-out "%{http_code}")
```

**`C#`**

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

string workflowId = null;
if (!string.IsNullOrWhiteSpace(phoneNumber))
{
    var accountsApi = new AccountsApi(docuSignClient);
    var identityVerificationResponse = accountsApi.GetAccountIdentityVerificationWithHttpInfo(accountId);
    identityVerificationResponse.Headers.TryGetValue("X-RateLimit-Remaining", out string identityRemaining);
    identityVerificationResponse.Headers.TryGetValue("X-RateLimit-Reset", out string identityReset);

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

    var phoneAuthWorkflow = identityVerificationResponse.Data.IdentityVerification
        .FirstOrDefault(x => x.DefaultName == "Phone Authentication");

    if (phoneAuthWorkflow == null)
    {
        throw new ApiException(0, "IDENTITY_WORKFLOW_INVALID_ID");
    }

    workflowId = phoneAuthWorkflow.WorkflowId;
}

EnvelopeDefinition envelope = MakeEnvelope(
    signerEmail,
    signerName,
    signerClientId,
    docPdf,
    countryCode,
    phoneNumber,
    workflowId);

EnvelopesApi envelopesApi = new EnvelopesApi(docuSignClient);
var results = envelopesApi.CreateEnvelopeWithHttpInfo(accountId, envelope);
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);
}

string envelopeId = results.Data.EnvelopeId;
```

**`Java`**

```java title="Java"
String workflowId = null;

// Resolve identity verification workflow only when phone auth is requested.
if (phoneNumber != null && !phoneNumber.isBlank()) {
    AccountsApi accountsApi = new AccountsApi(apiClient);
    var workflowRes = accountsApi.getAccountIdentityVerificationWithHttpInfo(
        accountId,
        accountsApi.new GetAccountIdentityVerificationOptions());

    Map<String, List<String>> headers = workflowRes.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);
    }

    List<AccountIdentityVerificationWorkflow> identityVerification =
            workflowRes.getData().getIdentityVerification();
    for (AccountIdentityVerificationWorkflow workflow : identityVerification) {
        if ("Phone Authentication".equals(workflow.getDefaultName())) {
            workflowId = workflow.getWorkflowId();
            break;
        }
    }

    if (workflowId == null) {
        throw new ApiException("IDENTITY_WORKFLOW_INVALID_ID");
    }
}

EnvelopeDefinition envelope = makeEnvelope(
        signerEmail,
        signerName,
        SIGNER_CLIENT_ID,
        workflowId,
        phoneNumber,
        countryCode,
        DOCUMENT_FILE_NAME,
        DOCUMENT_NAME);

EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);

var envelopeSummary = envelopesApi.createEnvelopeWithHttpInfo(accountId, envelope,
        envelopesApi.new CreateEnvelopeOptions());
Map<String, List<String>> headers = envelopeSummary.getHeaders();
java.util.List<String> remaining = headers.get("X-RateLimit-Remaining");
java.util.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();
```

**`Node.js`**

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

// If phone authentication is needed, get the workflow ID
if (args.envelopeArgs.phoneNumber) {
  let accountsApi = new docusign.AccountsApi(dsApiClient);
  let workflowId = null;

  results = await accountsApi.getAccountIdentityVerification(
    args.accountId, (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()}`);
      }
  });

  // Find the workflow ID corresponding to the name "Phone Authentication"
  results.data.identityVerification.forEach(workflow => {
    if (workflow.defaultName === 'Phone Authentication') {
      workflowId = workflow.workflowId;
    }
  });

  if (workflowId === null) {
    throw new Error('IDENTITY_WORKFLOW_INVALID_ID');
  }

  args.envelopeArgs.workflowId = workflowId;
}

// Make the envelope request body
let envelope = makeEnvelope(args.envelopeArgs);

// Call Envelopes::create API method
// Exceptions will be caught by the calling function
results = await envelopesApi.createEnvelope(args.accountId, {
  envelopeDefinition: envelope,
}, (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"
$envelope_definition = FocusedViewService::makeEnvelope($args['envelope_args'], $demo_path, $pdf_file);
$envelope_api = $client_service->getEnvelopeApi();

try {
    $envelope_summary = $envelope_api->createEnvelopeWithHttpInfo($args['account_id'], $envelope_definition);
    $remaining = $envelope_summary[2]['X-RateLimit-Remaining'] ?? null;
    $reset = $envelope_summary[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));
    }
} catch (ApiException $e) {
    $client_service->showErrorTemplate($e);
    exit;
}
$envelope_id = $envelope_summary[0]->getEnvelopeId();
```

**`PowerShell`**

```text title="PowerShell"
try {
    Invoke-RestMethod `
        -Uri "${apiUri}/v2.1/accounts/${accountId}/envelopes" `
        -Method 'POST' `
        -Headers @{
        'Authorization' = "Bearer $accessToken";
        'Content-Type'  = "application/json";
    } `
        -InFile (Resolve-Path $requestData).Path `
        -OutFile $response `
        -ErrorAction Stop
} catch {
    Write-ApiFailureAndExit -StepName "Create envelope request" -ErrorRecord $_ -TempPaths @($requestData, $response, $doc1Base64)
}
```

**`Python`**

```python title="Python"
envelope_args = args["envelope_args"]

# 2. call Envelopes::create API method
# Exceptions will be caught by the calling function
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])

if envelope_args.get("phone_number"):
    account_api = AccountsApi(api_client)
    (workflow_results, status, headers) = account_api.get_account_identity_verification_with_http_info(
        account_id=args["account_id"]
    )
    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}")

    workflow_id = None
    if workflow_results.identity_verification:
        for workflow in workflow_results.identity_verification:
            if workflow.default_name == "Phone Authentication":
                workflow_id = workflow.workflow_id
                break

    if workflow_id is None:
        raise ValueError("IDENTITY_WORKFLOW_INVALID_ID")

    envelope_args["workflow_id"] = workflow_id

# Create the envelope request object
envelope_definition = cls.make_envelope(envelope_args)

envelope_api = EnvelopesApi(api_client)
(results, status, headers) = envelope_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)

if args[:phone_number].present?
  accounts_api = DocuSign_eSign::AccountsApi.new(envelope_api.api_client)
  workflow_results, _status, headers = accounts_api.get_account_identity_verification_with_http_info(args[:account_id])

  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

  workflow_id = nil
  workflow_results.identity_verification&.each do |workflow|
    if workflow.default_name == 'Phone Authentication'
      workflow_id = workflow.workflow_id
      break
    end
  end

  raise 'IDENTITY_WORKFLOW_INVALID_ID' if workflow_id.nil?

  args[:workflow_id] = workflow_id
end

envelope = make_envelope(args[:signer_client_id], pdf_filename, signer_email, signer_name, args)

# Call Docusign to create the envelope

results, _status, headers = envelope_api.create_envelope_with_http_info args[:account_id], envelope

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 4. Create the recipient view definition for focused view

The recipient view is the screen that Docusign generates and displays in your app to enable your signers to sign documents. To create the definition for focused view, you must add the signer's information, the return URL, the `frameAncestors` field, and the `messageOrigins` field.

* Set the return URL to which the user will be forwarded after signing is complete. For Focused View and Focused View Click to Agree, this property is required, but will not be used. Instead, the Docusign JS library will raise custom DOM events.
* To render the Click to Agree experience, create the envelope with no tabs assigned to the signer. When no tabs are present, focused view displays a simplified flow where the signer reviews the document and clicks a single `Agree` button to complete signing, rather than navigating through individual fields.
* To require phone-based identity verification before signing, add an [identityVerification object](/docs/esign-rest-api/how-to/phone-auth) to the signer when creating the envelope. This requires a `workflowId` and the signer's phone number. The `workflowId` is specific to your account and can be retrieved from your account's identity verification settings. When configured, the signer will be prompted to verify their identity via SMS before they can access the document for signing.
* Add the recipient information to the request, including the signer's `email`, `name`, and `clientUserID` that were set for the recipient who will sign the envelope.
* Set the `messageOrigins` field to a single- element array: [https://apps-d.docusign.com](https://apps-d.docusign.com) for the developer environment or [https://apps.docusign.com](https://apps.docusign.com) for production environments.
* Add the `frameAncestors` field. Use **only origins** in this value. An origin includes a protocol (http or https) and a domain and may include a port. Do not include a path or a trailing slash. In production, only the HTTPS protocol is supported.

  These are valid frameAncestors values:

  *
  *

  These values are not valid:

  * (invalid due to the trailing slash)
  * (invalid due to the path appended to the origin)

  Include the origin or origins of the pages that will embed the focused view and the origin used in the `messageOrigins` field.

  Keep in mind that your domain must have a valid SSL certificate or an error message will be returned. We’re using the domain of the launcher, but make sure to replace this with your own domain name.

**`Bash`**

```bash title="Bash"
cat > "$request_data" <<EOF
{
    "returnUrl": "http://httpbin.org/get",
    "authenticationMethod": "none",
    "email": "${SIGNER_EMAIL}",
    "userName": "${SIGNER_NAME}",
    "clientUserId": 1000,
    "frameAncestors": ["http://localhost:8080", "https://apps-d.docusign.com"],
    "messageOrigins": ["https://apps-d.docusign.com"]
}
EOF
```

**`C#`**

```csharp title="C#"
public static RecipientViewRequest MakeRecipientViewRequest(string signerEmail, string signerName, string returnUrl, string signerClientId, string pingUrl = null)
{
    // Data for this method
    // signerEmail
    // signerName
    // dsPingUrl -- class global
    // signerClientId -- class global
    // dsReturnUrl -- class global
    RecipientViewRequest viewRequest = new RecipientViewRequest();

    // Set the URL where you want the recipient to go once they're done signing
    // It 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 session. It's usually better to use
    // the session mechanism of your web framework. Query parameters
    // can be changed or spoofed very easily.
    viewRequest.ReturnUrl = returnUrl + "?state=123";

    // How does your app verify the user's authentication? Additionally,
    // you can integrate authentication steps from DocuSign alongside
    // your app's own authentication process
    // Eg, SMS authentication
    viewRequest.AuthenticationMethod = "none";

    // Recipient information must match embedded recipient info
    // 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 session. There are multiple ways to save state.
    // To maintain your application's session, use the pingUrl
    // parameter. It causes the DocuSign signing session web page
    // (not the DocuSign server) to send pings via AJAX to your
    // app.
    // NOTE: The pings will only be sent if the pingUrl is an https address
    if (pingUrl != null)
    {
        viewRequest.PingFrequency = "600"; // seconds
        viewRequest.PingUrl = pingUrl; // optional setting
    }

    // The FrameAncestors should include the links https://apps-d.docusign.com
    // for demo environments and https://apps.docusign.com for prod environments,
    // and the site where the document should be embedded.
    // The site must have a valid SSL protocol for the embed to work.
    // MessageOrigins includes the demo or prod link and only
    // takes a single string
    viewRequest.FrameAncestors = new List<string> { "https://localhost:44333", "https://apps-d.docusign.com" };
    viewRequest.MessageOrigins = new List<string> { "https://apps-d.docusign.com" };

    return viewRequest;
}
```

**`Java`**

```java title="Java"
public RecipientViewRequest makeRecipientViewRequest(
        String signerEmail, String signerName, String returnUrl, String signerClientId, String pingUrl)
        throws ApiException {
    String pingFrequency = "600";
    String linkToLauncher = "http://localhost:8080";
    String linkToDocuSignServer = "https://apps-d.docusign.com";

    RecipientViewRequest viewRequest = new RecipientViewRequest();

    viewRequest.setReturnUrl(returnUrl + STATE_123);
    viewRequest.setAuthenticationMethod(AUTHENTICATION_METHOD);
    viewRequest.setEmail(signerEmail);
    viewRequest.setUserName(signerName);
    viewRequest.setClientUserId(signerClientId);

    if (pingUrl != null) {
        viewRequest.setPingFrequency(pingFrequency);
        viewRequest.setPingUrl(pingUrl);
    }

    viewRequest.setFrameAncestors(Arrays.asList(new String[] { linkToLauncher, linkToDocuSignServer }));
    viewRequest.setMessageOrigins(Arrays.asList(new String[] { linkToDocuSignServer }));

    return viewRequest;
}
```

**`Node.js`**

```javascript title="Node.js"
function makeRecipientViewRequest(args) {
  // Data for this method
  // args.dsReturnUrl
  // args.signerEmail
  // args.signerName
  // args.signerClientId
  // args.dsPingUrl

  let viewRequest = new docusign.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.
  viewRequest.returnUrl = args.dsReturnUrl + '?state=123';

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

  // Recipient information must match embedded recipient info
  // we used to create the envelope.
  viewRequest.email = args.signerEmail;
  viewRequest.userName = args.signerName;
  viewRequest.clientUserId = args.signerClientId;

  // DocuSign recommends that you redirect to DocuSign for the
  // embedded signing. There are multiple ways to save state.
  // To maintain your application's session, use the pingUrl
  // parameter. It causes the DocuSign signing 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 = args.dsPingUrl; // optional setting
  viewRequest.frameAncestors = ['http://localhost:3000', 'https://apps-d.docusign.com'];
  viewRequest.messageOrigins = ['https://apps-d.docusign.com'];

  return viewRequest;
}
```

**`PHP`**

```php title="PHP"
$authentication_method = 'None';

$recipient_view_request = $client_service->getRecipientViewRequest(
    $authentication_method,
    $args['envelope_args']
);

$recipient_view_request->setFrameAncestors(['http://localhost:8080/public', 'https://apps-d.docusign.com']);
$recipient_view_request->setMessageOrigins(['https://apps-d.docusign.com']);
```

**`PowerShell`**

```text title="PowerShell"
Write-Output "Requesting the url for the embedded signing..."
Write-Output ""

$json = @{
    returnUrl = "http://httpbin.org/get"
    authenticationMethod = "none"
    email = $variables.SIGNER_EMAIL
    userName = $variables.SIGNER_NAME
    clientUserId = 1000
    frameAncestors = @("http://localhost:8080", "https://apps-d.docusign.com")
    messageOrigins = @("https://apps-d.docusign.com")
}

$jsonString = $json | ConvertTo-Json
```

**`Python`**

```python title="Python"
recipient_view_request = RecipientViewRequest(
    authentication_method="none",
    client_user_id=envelope_args["signer_client_id"],
    recipient_id="1",
    return_url=envelope_args["ds_return_url"] + "?state=123",
    user_name=envelope_args["signer_name"],
    email=envelope_args["signer_email"],
    ping_frequency=600,
    ping_url=envelope_args["ds_ping_url"],
    frame_ancestors=["http://localhost:3000", "https://apps-d.docusign.com"],
    message_origins=["https://apps-d.docusign.com"]
)
```

**`Ruby`**

```ruby title="Ruby"
def make_recipient_view_request(signer_client_id, ds_return_url, ds_ping_url, signer_email, signer_name)
  view_request = DocuSign_eSign::RecipientViewRequest.new
  # 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.
  view_request.return_url = "#{ds_return_url}?state=123"

  # How has your app authenticated the user? In addition to your app's
  # authentication, you can include authenticate steps from Docusign;
  # e.g., SMS authentication
  view_request.authentication_method = 'none'

  # Recipient information must match the embedded recipient info
  # that was used to create the envelope
  view_request.email = signer_email
  view_request.user_name = signer_name
  view_request.client_user_id = signer_client_id

  # Docusign recommends that you redirect to Docusign for the embedded signing. There are
  # multiple ways to save state. To maintain your application's session, use the pingUrl
  # parameter. It causes the Docusign signing web page (not the Docusign server)
  # to send pings via AJAX to your app
  view_request.ping_frequency = '600' # seconds
  # NOTE: The pings will only be sent if the pingUrl is an HTTPS address
  view_request.ping_url = ds_ping_url # Optional setting

  view_request.frame_ancestors = ['http://localhost:3000', 'https://apps-d.docusign.com']
  view_request.message_origins = ['https://apps-d.docusign.com']

  view_request
end
```

## Step 5. Create the recipient view and initiate focused view signing

Next, create the recipient view. Use the [EnvelopeViews:createRecipient](/docs/esign-rest-api/reference/envelopes/envelopeviews/createrecipient) endpoint, passing in your API account ID and the `envelopeId` and `viewRequest` objects generated in previous steps.

Finally, extract the `url` property from the JSON response. Send the `url` property to the JavaScript on the browser. Your JavaScript will use the `url` when it calls [Docusign JS](/docs/esign-rest-api/esign101/concepts/embedding/docusign-js-embedded-reference) in the next step.

**`Bash`**

```bash title="Bash"
create_recipient_view_http_status=$(curl --silent --show-error \
    --header "Authorization: Bearer ${ACCESS_TOKEN}" \
    --header "Content-Type: application/json" \
    --data-binary @"${request_data}" \
    --request POST "${base_path}/v2.1/accounts/${ACCOUNT_ID}/envelopes/${envelope_id}/views/recipient" \
    --output "${response}" \
    --write-out "%{http_code}")
```

**`C#`**

```csharp title="C#"
RecipientViewRequest viewRequest = MakeRecipientViewRequest(signerEmail, signerName, returnUrl, signerClientId, pingUrl);

// Call the CreateRecipientView endpoint
var results1 = envelopesApi.CreateRecipientViewWithHttpInfo(accountId, envelopeId, viewRequest);
results1.Headers.TryGetValue("X-RateLimit-Remaining", out remaining);
results1.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);
}

// State can be stored/recovered using the framework's session or a
// query parameter on the returnUrl (see the makeRecipientViewRequest method)
string redirectUrl = results1.Data.Url;

// Returning both the envelopeId as well as the URL to be used for embedded signing
return (envelopeId, redirectUrl);
```

**`Java`**

```java title="Java"
RecipientViewRequest viewRequest = makeRecipientViewRequest(signerEmail, signerName, returnUrl,
        SIGNER_CLIENT_ID, returnUrl);
var viewUrl = envelopesApi.createRecipientViewWithHttpInfo(accountId, envelopeId, viewRequest);
headers = viewUrl.getHeaders();
remaining = headers.get("X-RateLimit-Remaining");
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 redirectUrl = viewUrl.getData().getUrl();

return new String[] { envelopeId, redirectUrl };
```

**`Node.js`**

```javascript title="Node.js"
let viewRequest = makeRecipientViewRequest(args.envelopeArgs);
// 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"
$view_url = $client_service->getRecipientView($args['account_id'], $envelope_id, $recipient_view_request);
return ['envelope_id' => $envelope_id, 'redirect_url' => $view_url['url']];
```

**`PowerShell`**

```text title="PowerShell"
try {
    Invoke-RestMethod `
        -Uri "${apiUri}/v2.1/accounts/${accountId}/envelopes/${envelopeId}/views/recipient" `
        -Method 'POST' `
        -Headers @{
        'Authorization' = "Bearer $accessToken";
        'Content-Type'  = "application/json";
    } `
        -Body $jsonString `
        -OutFile $response `
        -ErrorAction Stop
} catch {
    Write-ApiFailureAndExit -StepName "Create recipient view request" -ErrorRecord $_ -TempPaths @($requestData, $response, $doc1Base64)
}

Write-Output "Response: $(Get-Content -Raw $response)"

$signingUrl = $(Get-Content $response | ConvertFrom-Json).url
if ([string]::IsNullOrWhiteSpace($signingUrl)) {
    Write-Error "Create recipient view request failed: signing URL was not returned."

    Remove-Item $requestData
    Remove-Item $response
    Remove-Item $doc1Base64
    exit 1
}
```

**`Python`**

```python title="Python"
(results, status, headers) = envelope_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(signer_client_id, ds_return_url, ds_ping_url, signer_email, signer_name)

# 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 returnUrl (see the makeRecipientViewRequest method)
# Redirect to results.url
results.url
```

## Step 6. Customize the focused view and embed it in a web page

Next, customize the focused view UI. You’ll need to load the Docusign JS library in order to turn on focused view. The URL for 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.

The `signing` function takes a `style` parameter that can be used to customize styles and blend the agreement with the rest of your application:

**Signing Navigation Button**

* The `position` property takes one of three values: `bottom-left`, `bottom-right`, and `bottom-center`, which changes the placement of the signing button.
* The `finishText` property enables you to customize the text on the button when all the tabs have been completed and the agreement is ready to be signed.
* The shape property takes one of three values: `default`, `sharp`, or `pill`, which change the border radius of the signing button.

**Signing Agree Button**

* The `finishText` property enables you to customize the text on the agree button in the Click to Agree experience.

**Signing Decline Button**

* The `show` property controls whether the decline button is visible, allowing signers to decline to sign the envelope.
* the `finishText` property enables you to customize the text displayed on the decline button.
* The `backgroundColor` and `color` properties can be used to specify custom colors for the decline button.

**Branding**

* The `primaryButton` `backgroundColor` and `color` properties can be used to specify custom colors for the signing navigation button and primary buttons in the agreement.

**Modals**

* The `downloadModal.show` property controls whether a download modal is presented to the signer after signing is complete, enabling them to download a copy of the signed document.
* The `declineModal.show` property controls whether a confirmation modal is displayed when a signer chooses to decline.

Finally, create an HTML with div container to mount the signing URL. The iframe has a minimum height of 400px by default, but we’ve set it to 800px in this example.

> **Note**
>
> View the source code for this how-to on GitHub: [Bash](https://github.com/docusign/code-examples-bash/blob/master/examples/eSignature/lib/startServerForFocusedView.php),  [C#](https://github.com/docusign/code-examples-csharp/blob/master/launcher-csharp/eSignature/Examples/FocusedView.cs), [Java](https://github.com/docusign/code-examples-java/blob/master/src/main/java/com/docusign/controller/eSignature/services/FocusedViewService.java), [Node.js](https://github.com/docusign/code-examples-node/blob/master/lib/eSignature/examples/focusedView.js),  [PHP](https://github.com/docusign/code-examples-php/blob/master/src/Services/Examples/eSignature/FocusedViewService.php),  [Powershell](https://github.com/docusign/code-examples-powershell/blob/master/examples/eSignature/eg044FocusedView.ps1), [Python](https://github.com/docusign/code-examples-python/blob/master/app/eSignature/examples/eg044_focused_view.py), or [Ruby](https://github.com/docusign/code-examples-ruby/blob/master/app/services/e_sign/eg044_focused_view_service.rb).

**`Bash`**

```bash title="Bash"
-->
<br />
<h2>The document has been embedded with focused view.</h2>
<br />

<head>
    <meta charset=\"utf-8\" />
    <title>Signing</title>
    <style>
        html,
        body {
            padding: 0;
            margin: 0;
            font: 13px Helvetica, Arial, sans-serif;
        }

        .docusign-agreement {
            width: 75%;
            height: 800px;
        }
    </style>
</head>
<body>
    <div class=\"docusign-agreement\" id=\"agreement\"></div>
</body>
</html>

<script src='https://js.docusign.com/bundle.js'></script>
<script>
    window.DocuSign.loadDocuSign('" . $integrationKey . "')
        .then((docusign) => {
            const signing = docusign.signing({
                url: '" . $url . "',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },

                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill',
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree',
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff',
                    },

                    downloadModal: {
                        show: true,
                    },

                    declineModal: {
                        show: true,
                    },
                }
            });

            signing.on('ready', (event) => {
                console.log('UI is rendered');
            });

            signing.on('sessionEnd', (event) => {
                /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
                console.log('sessionend', event);
                window.location.href = '/'
            });

            signing.mount('#agreement');
        })
        .catch((ex) => {
            // Any configuration or API limits will be caught here
        });
</script>

<!--
```

**`C#`**

```csharp title="C#"
}
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>Signing</title>
        <style>
            html,
            body {
                padding: 0;
                margin: 0;
                font: 13px Helvetica, Arial, sans-serif;
            }

            .docusign-agreement {
                width: 75%;
                height: 800px;
            }
        </style>
    </head>
    <body>
    <div id="agreement" class="docusign-agreement"></div>
        <script src="script.js"></script>
    </body>
</html>
@Html.Raw("<script src='https://js.docusign.com/bundle.js'></script>")

<script>
    window.DocuSign.loadDocuSign('@ViewBag.IntegrationKey')
        .then((docusign) => {
            const signing = docusign.signing({
                url: '@ViewBag.Url',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },

                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill',
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree',
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff',
                    },

                    downloadModal: {
                        show: true,
                    },

                    declineModal: {
                        show: true,
                    },
                }
            });

            signing.on('ready', (event) => {
                console.log('UI is rendered');
            });

            signing.on('sessionEnd', (event) => {
                /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
                console.log('sessionend', event);
                window.location.href = '/';
            });

            signing.mount('#agreement');
        })
        .catch((ex) => {
            // Any configuration or API limits will be caught here
        });</script>
@{
```

**`Java`**

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Signing</title>
    <style>
        html,
        body {
            margin-top: 30px;
            padding: 0;
            font: 13px Helvetica, Arial, sans-serif;
        }

        .docusign-agreement {
            width: 75%;
            height: 800px;
        }
    </style>
</head>
<body>
<div class="docusign-agreement" id="agreement"></div>
</body>
</html>

<script src='https://js.docusign.com/bundle.js'></script>
<script>
    window.DocuSign.loadDocuSign('${integrationKey}')
        .then((docusign) => {
            const signing = docusign.signing({
                url: '${url}',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },

                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill',
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree',
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff',
                    },

                    downloadModal: {
                        show: true,
                    },

                    declineModal: {
                        show: true,
                    },
                }
            });

            signing.on('ready', (event) => {
                console.log('UI is rendered');
            });

            signing.on('sessionEnd', (event) => {
                /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
                console.log('sessionend', event);
                window.location.href = '/'
            });

            signing.mount('#agreement');
        })
        .catch((ex) => {
            // Any configuration or API limits will be caught here
        });
</script>

<!--
```

**`Node.js`**

```javascript title="Node.js"
-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Signing</title>
    <style>
        html,
        body {
            padding: 0;
            margin-top: 15px;
            font: 13px Helvetica, Arial, sans-serif;
        }

        .docusign-agreement {
            width: 75%;
            height: 800px;
        }
    </style>
</head>
<body>
    <div class="docusign-agreement" id="agreement"></div>
    <script src="script.js"></script>
</body>
</html>

<script src='https://js.docusign.com/bundle.js'></script>
<script>
    window.DocuSign.loadDocuSign('<%= integrationKey %>')
        .then((docusign) => {
            const signing = docusign.signing({
                url: '<%= url %>',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },

                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill',
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree',
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff',
                    },

                    downloadModal: {
                        show: true,
                    },

                    declineModal: {
                        show: true,
                    },
                }
            });

            signing.on('ready', (event) => {
                console.log('UI is rendered');
            });

            signing.on('sessionEnd', (event) => {
                /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
                console.log('sessionend', event);
                window.location.href = '/'
            });

            signing.mount('#agreement');
        })
        .catch((ex) => {
            // Any configuration or API limits will be caught here
        });
</script>
<!--
```

**`PHP`**

```php title="PHP"
-->

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Signing</title>
    <style>
        html,
        body {
            margin-top: 15px;
            padding: 0;
            font: 13px Helvetica, Arial, sans-serif;
        }

        .docusign-agreement {
            width: 75%;
            height: 800px;
        }
    </style>
</head>
<body>
<div class="docusign-agreement" id="agreement"></div>
</body>
</html>

<script src='https://js.docusign.com/bundle.js'></script>
<script>
    window.DocuSign.loadDocuSign('{{ integration_key }}')
        .then((docusign) => {
            const signing = docusign.signing({
                url: '{{ url }}',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },

                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill'
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree'
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff'
                    },

                    downloadModal: {
                        show: true
                    },

                    declineModal: {
                        show: true
                    }
                }
            });

            signing.on('ready', (event) => {
                console.log('UI is rendered');
            });

            signing.on('sessionEnd', (event) => {
                /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
                console.log('sessionend', event);
                window.location.href = '/public/';
            });

            signing.mount('#agreement');
        })
        .catch((ex) => {
            // Any configuration or API limits will be caught here
        });
</script>

<!--
```

**`PowerShell`**

```text title="PowerShell"
-->
<br />
<h2>The document has been embedded with focused view.</h2>
<br />
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Signing</title>
    <style>
        html,
        body {
            padding: 0;
            margin: 0;
            font: 13px Helvetica, Arial, sans-serif;
        }
        .docusign-agreement {
            width: 75%;
            height: 800px;
        }
    </style>
</head>
<body>
    <div class="docusign-agreement" id="agreement"></div>
</body>
</html>
<script src='https://js.docusign.com/bundle.js'></script>
<script>
    window.DocuSign.loadDocuSign('$integrationKey')
    .then((docusign) => {
      const signing = docusign.signing({
                url: '$signingURL',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },
                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill',
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree',
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff',
                    },

                    downloadModal: {
                        show: true,
                    },

                    declineModal: {
                        show: true,
                    },
                }
            });

            signing.on('ready', (event) => {
              console.log('UI is rendered');
          });

          signing.on('sessionEnd', (event) => {
              /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
              console.log('sessionend', event);
              window.location.href = '/'
          });

          signing.mount('#agreement');
      })
      .catch((ex) => {
          // Any configuration or API limits will be caught here
      });
</script>

<!--
```

**`Python`**

```python title="Python"
-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Signing</title>
    <style>
        html,
        body {
            padding: 0;
            margin-top: 15px;
            font: 13px Helvetica, Arial, sans-serif;
        }

        .docusign-agreement {
            width: 75%;
            height: 800px;
        }
    </style>
</head>
<body>
    <div class="docusign-agreement" id="agreement"></div>
    <script src="script.js"></script>
</body>
</html>

<script src='https://js.docusign.com/bundle.js'></script>
<script>
    window.DocuSign.loadDocuSign('{{ integration_key }}')
        .then((docusign) => {
            const signing = docusign.signing({
                url: '{{ url }}',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },

                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill',
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree',
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff',
                    },

                    downloadModal: {
                        show: true,
                    },

                    declineModal: {
                        show: true,
                    },
                }
            });

            signing.on('ready', (event) => {
                console.log('UI is rendered');
            });

            signing.on('sessionEnd', (event) => {
                /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
                console.log('sessionend', event);
                window.location.href = '/'
            });

            signing.mount('#agreement');
        })
        .catch((ex) => {
            // Any configuration or API limits will be caught here
        });</script>
<!--
```

**`Ruby`**

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Signing</title>
    <style>
        html,
        body {
            padding: 0;
            margin-top: 15px;
            font: 13px Helvetica, Arial, sans-serif;
        }

        .docusign-agreement {
            width: 75%;
            height: 800px;
        }
    </style>
</head>
<body>
    <div class="docusign-agreement" id="agreement"></div>
    <script src="script.js"></script>
</body>
</html>

<script src='https://js.docusign.com/bundle.js'></script>
<script>
    window.DocuSign.loadDocuSign('<%= @integration_key %>')
        .then((docusign) => {
            const signing = docusign.signing({
                url: '<%= @url %>',
                displayFormat: 'focused',
                style: {
                    /** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
                    branding: {
                        primaryButton: {
                            /** Background color of primary button */
                            backgroundColor: '#50C878',
                            /** Text color of primary button */
                            color: '#fff',
                        }
                    },

                    /** High-level components we allow specific overrides for */
                    signingNavigationButton: {
                        finishText: 'You have finished the document! Hooray!',
                        position: 'bottom-center',
                        shape: 'pill',
                    },

                    signingAgreeButton: {
                        finishText: 'I Agree',
                    },

                    signingDeclineButton: {
                        show: true,
                        finishText: 'Decline',
                        backgroundColor: '#ff0000',
                        color: '#ffffff',
                    },

                    downloadModal: {
                        show: true,
                    },

                    declineModal: {
                        show: true,
                    },
                }
            });

            signing.on('ready', (event) => {
                console.log('UI is rendered');
            });

            signing.on('sessionEnd', (event) => {
                /** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
                console.log('sessionend', event);
                window.location.href = '/'
            });

            signing.mount('#agreement');
        })
        .catch((ex) => {
            // Any configuration or API limits will be caught here
        });
</script>

        <!--
```

## Expected response

If you run this code example from our Quickstart or launcher projects, you should see the agreement embedded in the results page of the example.

After signing is complete, the sender will receive a carbon copy (CC) of the email that includes all of the completed and signed documents.

![An image of the document embedded in the web page, with one signing tab and the start signing button.](/_fern-files/_img/3d9c3c42107d1142411e4a8d854f60d218f9cbd4aec4547f3208d8c3ef2a3110.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 [Embedded signing](/docs/esign-rest-api/esign101/concepts/embedding).
* See all available eSignature [How-to guides](/docs/esign-rest-api/how-to).
* 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.